Skip to content

Commit 12053e4

Browse files
authored
Merge pull request #25 from pyroscope-io/0.5.0
Version 0.5.0
2 parents 2cba18b + a43f000 commit 12053e4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2348
-1174
lines changed

.github/workflows/build.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
name: Build
22

3-
on: [push, pull_request]
3+
on:
4+
push:
5+
paths:
6+
- 'pyroscope_backends/**'
7+
- 'pyroscope_cli/**'
8+
- 'src/**'
9+
- 'tests/**'
10+
- '.github/workflows/build.yml'
11+
pull_request:
12+
paths:
13+
- 'pyroscope_backends/**'
14+
- 'pyroscope_cli/**'
15+
- 'src/**'
16+
- 'tests/**'
17+
- '.github/workflows/build.yml'
418

519
jobs:
620
build:

.github/workflows/python.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Python Package
2+
3+
on:
4+
push:
5+
paths:
6+
- 'pyroscope_ffi/python/**'
7+
- '.github/workflows/python.yml'
8+
pull_request:
9+
paths:
10+
- 'pyroscope_ffi/python/**'
11+
- '.github/workflows/python.yml'
12+
13+
jobs:
14+
build_wheels:
15+
name: Build wheels on ${{ matrix.os }}
16+
runs-on: ${{ matrix.os }}
17+
strategy:
18+
matrix:
19+
os: [ubuntu-latest, macos-latest]
20+
target: [x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin]
21+
exclude:
22+
- os: ubuntu-latest
23+
target: x86_64-apple-darwin
24+
- os: ubuntu-latest
25+
target: aarch64-apple-darwin
26+
- os: macos-latest
27+
target: x86_64-unknown-linux-gnu
28+
- os: macos-latest
29+
target: aarch64-unknown-linux-gnu
30+
31+
env:
32+
CIBW_BEFORE_ALL_LINUX: "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y && apt update && apt install -y libssl-dev libunwind8-dev"
33+
CIBW_BUILD_VERBOSITY: "1"
34+
CIBW_ENVIRONMENT: 'PATH="$PATH:$HOME/.cargo/bin"'
35+
CIBW_MANYLINUX_X86_64_IMAGE: "quay.io/pypa/manylinux_2_24_x86_64:latest"
36+
37+
steps:
38+
- uses: actions/checkout@v2
39+
40+
- uses: actions/setup-python@v2
41+
42+
- name: Install cibuildwheel
43+
run: python -m pip install cibuildwheel==2.4.0
44+
45+
- name: Build wheels
46+
run: python pyroscope_ffi/python -m cibuildwheel --output-dir wheelhouse
47+
48+
- uses: actions/upload-artifact@v2
49+
with:
50+
path: ./wheelhouse/*.whl
51+
52+
- name: Display repo
53+
shell: bash
54+
run: |
55+
cd wheelhouse
56+
ls -la

.github/workflows/tests.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
name: Tests
22

3-
on: [push, pull_request]
3+
on:
4+
push:
5+
paths:
6+
- 'pyroscope_backends/**'
7+
- 'pyroscope_cli/**'
8+
- 'src/**'
9+
- 'tests/**'
10+
- '.github/workflows/tests.yml'
11+
pull_request:
12+
paths:
13+
- 'pyroscope_backends/**'
14+
- 'pyroscope_cli/**'
15+
- 'src/**'
16+
- 'tests/**'
17+
- '.github/workflows/tests.yml'
418

519
jobs:
620
test:

Cargo.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[package]
22
name = "pyroscope"
33
description = """
4-
Pyroscope Profiler
4+
Pyroscope Profiler Agent for continuous profiling of Rust, Python and Ruby applications.
55
"""
6-
keywords = ["pyroscope", "profiler"]
6+
keywords = ["pyroscope", "profiler", "profiling", "pprof"]
77
authors = ["Abid Omar <[email protected]>"]
8-
version = "0.4.0"
8+
version = "0.5.0"
99
edition = "2021"
1010
license = "Apache-2.0"
11-
homepage = "https://pyroscope.io"
11+
homepage = "https://pyroscope.io/docs/rust"
1212
documentation = "https://docs.rs/pyroscope"
1313
repository = "https://github.com/pyroscope-io/pyroscope-rs"
1414
readme = "README.md"
@@ -23,6 +23,7 @@ members = [
2323
exclude = [
2424
"pyroscope_backends",
2525
"pyroscope_cli",
26+
"pyroscope_ffi",
2627
]
2728

2829
[[example]]
@@ -53,15 +54,15 @@ path = "examples/internal/rbspy-connect.rs"
5354
thiserror ="1.0"
5455
log = "0.4"
5556
reqwest = { version = "0.11", features = ["blocking"]}
56-
libc = "^0.2.66"
57+
libc = "^0.2.124"
5758

5859
[dev-dependencies]
59-
tokio = { version = "1.13", features = ["full"] }
60+
tokio = { version = "1.18", features = ["full"] }
6061
pretty_env_logger = "0.4.0"
6162
assert_matches = "1"
6263
pyroscope_pprofrs = { path = "pyroscope_backends/pyroscope_pprofrs" }
63-
pyroscope_rbspy = { path = "pyroscope_backends/pyroscope_rbspy" }
6464
pyroscope_pyspy = { path = "pyroscope_backends/pyroscope_pyspy" }
65+
pyroscope_rbspy = { path = "pyroscope_backends/pyroscope_rbspy" }
6566

6667
[profile.dev]
6768
opt-level=0

README.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ You may be looking for:
1515
- [Crate Documentation](https://docs.rs/pyroscope/)
1616
- [Examples](examples)
1717
- [Release notes](https://github.com/omarabid/pyroscope/releases)
18+
- [Pyroscope CLI](pyroscope_cli)
1819

1920
## Table of Contents
2021
- [Quick Start](#quick-start)
22+
- [Pyroscope Server](#pyroscope-server)
23+
- [Multi-Threading](#multi-threading)
24+
- [Profiling Backends](#profiling-backends)
2125
- [Limitations](#limitations)
2226
- [Getting Help](#getting-help)
2327
- [License](#license)
@@ -28,8 +32,8 @@ Add this to your `Cargo.toml`:
2832

2933
```toml
3034
[dependencies]
31-
pyroscope = "0.4.0"
32-
pyroscope-pprofrs = "0.1"
35+
pyroscope = "0.5.0"
36+
pyroscope-pprofrs = "0.2"
3337
```
3438

3539
Configure and create the backend (pprof-rs)
@@ -42,7 +46,7 @@ let pprof_backend = Pprof::new(pprof_config);
4246
Configure the Pyroscope agent:
4347

4448
```rust
45-
let mut agent =
49+
let agent =
4650
PyroscopeAgent::builder("http://localhost:4040", "myapp-profile")
4751
.backend(pprof_backend)
4852
.build()?;
@@ -51,19 +55,38 @@ Configure the Pyroscope agent:
5155
Profile your code:
5256

5357
```rust
54-
agent.start();
55-
// Profiled computation
56-
agent.stop();
57-
58-
// Non-profiled computation
58+
let agent_running = agent.start()?;
59+
60+
// Computation to profile
61+
62+
let agent_ready = agent_running.stop()?;
63+
agent_ready.shutdown();
5964
```
6065

66+
### Pyroscope Server
67+
68+
The Pyroscope Agent send the profiling data to a [Pyroscope Server](https://pyroscope.io/docs/installing-pyroscope-overview/). You need to have a Pyroscope Server running in order to consume and visualize this data. It's not possible, currently, to forward the data to another endpoint.
69+
70+
### Multi-Threading
71+
72+
The Pyroscope Agent and the [pprof-rs backend](pyroscope_backends/pyroscope_pprofrs) can profile and report data from a multi-threaded program. [pprof-rs](https://github.com/tikv/pprof-rs), however, does not track child-processes and thus profiling is limited to a single process.
73+
74+
### Profiling Backends
75+
76+
The Pyroscope Agent doesn't do any profiling. The agent role is to orchasrate a profiling backend, and report the profiling data to the Pyroscope Server. The Agent can support external backends (in fact, all current backends are independent crates) and you can make your own. Backends can also be used seperately. The currently available backends are:
77+
78+
- [pprof-rs](pyroscope_backends/pyroscope_pprofrs): Rust profiler. A wrapper around [pprof-rs](https://github.com/tikv/pprof-rs).
79+
- [rbspy](pyroscope_backends/pyroscope_rbspy): Ruby Profiler. A wrapper around [rbspy](https://rbspy.github.io/).
80+
- [py-spy](pyroscope_backends/pyroscope_pyspy): Python Profiler. A wrapper around [py-spy](https://github.com/benfred/py-spy).
81+
82+
6183
### Limitations
6284

6385
- **Backend**: The Pyroscope Agent uses [pprof-rs](https://github.com/tikv/pprof-rs) as a backend. As a result, the [limitations](https://github.com/tikv/pprof-rs#why-not-) for pprof-rs also applies.
64-
- **Tagging**: Adding or removing tags is not possible within threads. In general, the [Pyroscope Agent](https://docs.rs/pyroscope/latest/pyroscope/pyroscope/struct.PyroscopeAgent.html) is not Sync; and as a result a reference cannot be shared between threads. A multi-threaded program could be profiled but the agent is not thread-aware and a particular thread cannot be tagged.
86+
- **Tagging**: ~~Adding or removing tags is not possible within threads. In general, the [Pyroscope Agent](https://docs.rs/pyroscope/latest/pyroscope/pyroscope/struct.PyroscopeAgent.html) is not Sync; and as a result a reference cannot be shared between threads. A multi-threaded program could be profiled but the agent is not thread-aware and a particular thread cannot be tagged.~~
87+
As of 0.5.0, the Pyroscope Agent support tagging within threads. Check the [Tags](examples/tags.rs) and [Multi-Thread](examples/multi-thread.rs) examples for usage.
6588
- **Timer**: epoll (for Linux) and kqueue (for macOS) are required for a more precise timer.
66-
- **Shutdown**: The Pyroscope Agent might take some time (usually less than 10 seconds) to shutdown properly and drop its threads.
89+
- **Shutdown**: The Pyroscope Agent might take some time (usually less than 10 seconds) to shutdown properly and drop its threads. For a proper shutdown, it's recommended that you run the `shutdown` function before dropping the Agent.
6790

6891
### Getting help
6992

SECURITY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
| Version | Supported |
66
| ------- | ------------------ |
7+
| 0.5.x | :white_check_mark: |
78
| 0.4.x | :white_check_mark: |
89
| 0.3.x | :white_check_mark: |
910
| < 3.0 | :x: |

examples/async.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate pyroscope;
22

33
use pyroscope::{PyroscopeAgent, Result};
4-
use pyroscope_pprofrs::{Pprof, PprofConfig};
4+
use pyroscope_pprofrs::{pprof_backend, PprofConfig};
55
use std::hash::{Hash, Hasher};
66

77
fn hash_rounds1(n: u64) -> u64 {
@@ -34,13 +34,20 @@ fn hash_rounds2(n: u64) -> u64 {
3434

3535
#[tokio::main]
3636
async fn main() -> Result<()> {
37-
let mut agent = PyroscopeAgent::builder("http://localhost:4040", "example.async")
38-
.backend(Pprof::new(PprofConfig::new().sample_rate(100)))
37+
let agent = PyroscopeAgent::builder("http://localhost:4040", "example.async")
38+
.backend(pprof_backend(PprofConfig::new().sample_rate(100)))
3939
.tags([("TagA", "ValueA"), ("TagB", "ValueB")].to_vec())
4040
.build()?;
4141

42+
// Show start time
43+
let start = std::time::SystemTime::now()
44+
.duration_since(std::time::UNIX_EPOCH)
45+
.unwrap()
46+
.as_secs();
47+
println!("Start Time: {}", start);
48+
4249
// Start Agent
43-
agent.start()?;
50+
let agent_running = agent.start()?;
4451

4552
tokio::task::spawn(async {
4653
let n = hash_rounds1(300_000);
@@ -57,7 +64,17 @@ async fn main() -> Result<()> {
5764
.unwrap();
5865

5966
// Stop Agent
60-
agent.stop()?;
67+
let agent_ready = agent_running.stop()?;
68+
69+
// Shutdown the Agent
70+
agent_ready.shutdown();
71+
72+
// Show program exit time
73+
let exit = std::time::SystemTime::now()
74+
.duration_since(std::time::UNIX_EPOCH)
75+
.unwrap()
76+
.as_secs();
77+
println!("Exit Time: {}", exit);
6178

6279
Ok(())
6380
}

examples/backend.rs

Lines changed: 0 additions & 32 deletions
This file was deleted.

examples/basic.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate pyroscope;
22

33
use pyroscope::{PyroscopeAgent, Result};
4-
use pyroscope_pprofrs::{Pprof, PprofConfig};
4+
use pyroscope_pprofrs::{pprof_backend, PprofConfig};
55
use std::hash::{Hash, Hasher};
66

77
fn hash_rounds(n: u64) -> u64 {
@@ -19,8 +19,8 @@ fn hash_rounds(n: u64) -> u64 {
1919
}
2020

2121
fn main() -> Result<()> {
22-
let mut agent = PyroscopeAgent::builder("http://localhost:4040", "example.basic")
23-
.backend(Pprof::new(PprofConfig::new().sample_rate(100)))
22+
let agent = PyroscopeAgent::builder("http://localhost:4040", "example.basic")
23+
.backend(pprof_backend(PprofConfig::new().sample_rate(100)))
2424
.tags([("TagA", "ValueA"), ("TagB", "ValueB")].to_vec())
2525
.build()?;
2626

@@ -32,7 +32,7 @@ fn main() -> Result<()> {
3232
println!("Start Time: {}", start);
3333

3434
// Start Agent
35-
agent.start()?;
35+
let agent_running = agent.start()?;
3636

3737
let _result = hash_rounds(300_000);
3838

@@ -44,9 +44,10 @@ fn main() -> Result<()> {
4444
println!("Stop Time: {}", stop);
4545

4646
// Stop Agent
47-
agent.stop()?;
47+
let agent_ready = agent_running.stop()?;
4848

49-
drop(agent);
49+
// Shutdown the Agent
50+
agent_ready.shutdown();
5051

5152
// Show program exit time
5253
let exit = std::time::SystemTime::now()

examples/error.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate pyroscope;
22

33
use pyroscope::{PyroscopeAgent, Result};
4-
use pyroscope_pprofrs::{Pprof, PprofConfig};
4+
use pyroscope_pprofrs::{pprof_backend, PprofConfig};
55

66
fn fibonacci(n: u64) -> u64 {
77
match n {
@@ -17,19 +17,19 @@ fn main() -> Result<()> {
1717
// Initialize the logger.
1818
pretty_env_logger::init_timed();
1919

20-
let mut agent = PyroscopeAgent::builder("http://invalid_url", "example.error")
21-
.backend(Pprof::new(PprofConfig::new().sample_rate(100)))
20+
let agent = PyroscopeAgent::builder("http://invalid_url", "example.error")
21+
.backend(pprof_backend(PprofConfig::new().sample_rate(100)))
2222
.build()
2323
.unwrap();
2424
// Start Agent
25-
agent.start()?;
25+
let agent_running = agent.start()?;
2626

2727
let _result = fibonacci(47);
2828

2929
// Stop Agent
30-
agent.stop()?;
30+
let agent_ready = agent_running.stop()?;
3131

32-
drop(agent);
32+
agent_ready.shutdown();
3333

3434
Ok(())
3535
}

0 commit comments

Comments
 (0)