Pyroscope CLI (pyroscope-cli)
-----------------------------
`pyroscope-cli` is a general purpose profiler. It currently supports profiling ruby and python applications. The aggregated data from profiling is then sent to a [Pyroscope Server](https://pyroscope.io/docs/installing-pyroscope-overview/). Under the hood, it uses the [Pyroscope Rust library](https://github.com/pyroscope-io/pyroscope-rs) and its [backends](https://github.com/pyroscope-io/pyroscope-rs/tree/main/pyroscope_backends).
This is a Work-in-Progress implementation. Some features (like adhoc/pull mode) are still not available and the profiling spies are limited to Ruby/Python. For the original implementation, you should check the [Pyroscope Go agent](https://pyroscope.io/docs/agent-overview/j).
### CHANGELOG
Please see the [CHANGELOG](CHANGELOG.md) for a release history.
### Table of Contents
- [Installation](#installation)
- [How to use](#how-to-use)
- 1. [Basic Usage](#1-basic-usage)
- 2. [Connect to process](#2-connect-to-process)
- 3. [Execute commands](#3-execute-commands)
- 4. [Options](#4-options)
- 5. [Configuration](#5-configuration)
- 5. 1. [Configuration file](#1-configuration-file)
- 5. 2. [Environment variables](#2-environment-variables)
- 6. [Logging](#6-logging)
- [Supported Profilers](#supported-profilers)
- 1. [rbspy](#1-rbspy)
- 2. [pyspy](#2-pyspy)
- [Frequently Asked Questions](#frequently-asked-questions)
- [Shell Completions](#shell-completions)
- [Building from source](#building-from-source)
- [License](#license)
### Installation
Currently, the best method to locally install `pyrsocope-cli` is to use the rustc compiler with Cargo.
```
$ cargo install pyrsocope-cli
```
Binaries are also available in the Release page. The targeted platforms are `x86_64`/`ARM` and `linux`/`macos`.
### How to use
#### 1. Basic Usage
There are two options to profile programs, regardless of the profiler: Either by connecting to the process [PID](https://en.wikipedia.org/wiki/Process_identifier), or by passing a command where the agent will handle both its execution and profiling.
```
$ pyroscope-cli connect --pid=$pid --spy-name=rbspy
```
```
$ pyroscope-cli exec --spy-name=rbspy ruby ./program.rb
```
#### 2. Connect to Process
To connect to a process and attach a profiler, you'll need both a PID and the required system privileges. The last one will vary depending on your Operating System and its configuration.
To get the PID of a program, you can use `ps` and `grep`:
```
You also need to specify the profiler, the possible values are rbspy (for Ruby) and pyspy (for Python). The `pid` and `spy-name` are the two required arguments to profile a process.
```
$ pyroscope-cli connect --pid=1222 --spy-name=rbspy
```
#### 3. Execute Commands
`pyroscope-cli` can execute a command and profile the spawned process. The command is spawned as a child of the agent process. Once the agent process exits, the executed command its child processes exit too.
```
$ pyroscope-cli exec --spy-name=rbspy ruby ./program.rb
```
You can also pass arguments to the executed command by appending `--`
```
$ pyroscope-cli exec --spy-name=rbspy ruby ./program.rb -- --ruby-arg=value
```
#### 4. Options
Both the pyroscope-cli agent, and its backend profilers can accept configuration. Some options are accepted by all profilers, while other can only apply to a certain profiler or a multiple of them. The CLI `--help` menu should give a detailed list of all options that the program can accept.
##### 4.1 Options accepted by all profilers and commands
- **application-name**: application name used when uploading profiling data. Default is a randomly generated name.
- **log-level**: log level for the application. Default is `info`. For more information, check [logging](#6-logging).
- **sample-rate**: sample rate for the profiler in Hz. 100 means reading 100 times per second. Default is `100`
- **server-address**: Pyroscope server address. Default is `http://localhost:4040`.
- **tag**: tag in key=value form. May be specified multiple times. Default is empty.
##### 4.2 Options accepted by `exec` command
- **user-name**: start process under specified user name.
- **group-name**: start process under specified group name.
#### 5. Configuration
There are 3 ways to configure Pyroscope Agent. Configuration precedence is evaluated in the following order: environment variables > configuration files > command-line arguments.
##### 1. Configuration file
Configuration files are stored in [TOML format](https://en.wikipedia.org/wiki/TOML). You can specify configuration file location with `-config <path>`. This is supported for both `exec` and `connect` commands.
```
pyroscope-cli -c -config /tmp/custom-config.toml <COMMAND>
```
##### 2. Environment variables
Environment variables must have `PYROSCOPE_` prefix and be in UPPER_SNAKE_CASE format, for example:
```
PYROSCOPE_APPLICATION_NAME=:my-ruby-app pyroscope-cli connect --pid=100 --spy-name=rbspy
```
#### 6. Logging
Logs are output to the terminal. There are 6 levels of logging. Log levels are not displayed seperately but rather takes precedence. For example, if you specify the `info` log level, you'll get output for `info`, `warn`, `error` and `critical` logs.
- **trace**: very low priority, often extremely verbose, information.
- **debug**: lower priority information.
- **info**: useful information.
- **warn**: hazardous situations.
- **error**: very serious errors.
- **critical**: errors that result in program panic.
### Supported Profilers
#### 1. rbspy
The `rbspy` profiler can be used to profile Ruby application. It uses the rbspy backend, which itself is a wrapper around the rbspy profiler.
##### Options accepted by rbspy
- **detect-subprocesses**: keep track of and profile subprocesses of the main process.
- **blocking**: enable blocking mode
#### 2. pyspy
The `pyspy` profiler can be used to profile Ruby application. It uses the pyspy backend, which itself is a wrapper around the py-spy profiler.
##### Options accepted by pyspy
- **detect-subprocesses**: keep track of and profile subprocesses of the main process.
- **blocking**: enable blocking mode.
- **pyspy-idle**: include idle threads.
- **pyspy-gil**: enable GIL mode.
- **pyspy-native**: enable native extensions profiling.
### Frequently Asked Questions
Please see the [FAQ](FAQ.md) page for Frequently Asked Questions.
### Shell Completions
`pyroscope-cli` supports shell auto-completion for `bash`, `zsh`, `fish`, and `powershell`. You can generate the auto-completion file using the `completion` command.
For example, to generate auto-complete for `fish`:
```fish
$ pyroscope-cli completion fish > pyroscope-cli.fish
```
### Building from source
You can build `pyroscope-cli` from source if you have a Rust toolchain installed. You will need Rust 1.59 or newer.
1. Install Rust toolchain with rustup:
```
For other systems, please check the instructions at https://rustup.rs/.
2. Add ~/.cargo/bin to your PATH:
```
. "$HOME/.cargo/env"
```
3. Build `pyroscope-cli`
```
git clone https://github.com/pyroscope-io/pyroscope-rs
cd pyroscope-rs/pyroscope_cli
cargo build --release
./target/release/pyroscope-cli --help
```
### License
Pyroscope is distributed under the Apache License (Version 2.0).
See [LICENSE](LICENSE) for details.