async_profiler_agent/
lib.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4#![deny(missing_docs)]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7//! ## async-profiler Rust agent
8//! An in-process Rust agent for profiling an application using [async-profiler] and uploading the resulting profiles.
9//!
10//! [async-profiler]: https://github.com/async-profiler/async-profiler
11//!
12//! ### OS/CPU Support
13//!
14//! This Rust agent currently only supports Linux, on either x86-64 or aarch64.
15//!
16//! ### Usage
17//!
18//! The agent runs the profiler and uploads the output periodically via a reporter.
19//!
20//! When starting, the profiler [dlopen(3)]'s `libasyncProfiler.so` and returns an [`Err`] if it is not found,
21//! so make sure there is a `libasyncProfiler.so` in the search path[^1].
22//!
23//! [^1]: the dlopen search path includes RPATH and LD_LIBRARY_PATH, but *not* the current directory to avoid current directory attacks.
24//!
25//! [dlopen(3)]: https://linux.die.net/man/3/dlopen
26//!
27//! You can use the [`S3Reporter`], which uploads the reports to an S3 bucket, as follows:
28//!
29#![cfg_attr(feature = "s3-no-defaults", doc = "```no_run")]
30#![cfg_attr(not(feature = "s3-no-defaults"), doc = "```compile_fail")]
31//! # use async_profiler_agent::profiler::{ProfilerBuilder, SpawnError};
32//! # use async_profiler_agent::reporter::s3::{S3Reporter, S3ReporterConfig};
33//! # use aws_config::BehaviorVersion;
34//! # #[tokio::main]
35//! # async fn main() -> Result<(), SpawnError> {
36//!
37//! let bucket_owner = "<your account id>";
38//! let bucket_name = "<your bucket name>";
39//! let profiling_group = "a-name-to-give-the-uploaded-data";
40//!
41//! let sdk_config = aws_config::defaults(BehaviorVersion::latest()).load().await;
42//!
43//! let profiler = ProfilerBuilder::default()
44//!    .with_reporter(S3Reporter::new(S3ReporterConfig {
45//!        sdk_config: &sdk_config,
46//!        bucket_owner: bucket_owner.into(),
47//!        bucket_name: bucket_name.into(),
48//!        profiling_group_name: profiling_group.into(),
49//!    }))
50//!    .build();
51//!
52//! profiler.spawn()?;
53//! # Ok(())
54//! # }
55//! ```
56//!
57//! The [`S3Reporter`] uploads each report in a `zip` file, that currently contains 2 files:
58//! 1. a [JFR] as `async_profiler_dump_0.jfr`
59//! 2. metadata as `metadata.json`, in format [`reporter::s3::MetadataJson`].
60//!
61//! The `zip` file is uploaded to the bucket under the path `profile_{profiling_group_name}_{machine}_{pid}_{time}.zip`,
62//! where `{machine}` is either `ec2_{ec2_instance_id}_`, `ecs_{cluster_arn}_{task_arn}`, or `onprem__`.
63//!
64//! In addition to the S3 reporter, this crate also includes [`LocalReporter`] that writes to a directory, and a `MultiReporter` that allows combining reporters. You can also write your own reporter (via the `Reporter` trait) to upload the profile results to your favorite profiler backend.
65//!
66//! [`LocalReporter`]: reporter::local::LocalReporter
67//! [`S3Reporter`]: reporter::s3::S3Reporter
68//! [JFR]: https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/about.htm
69//!
70//! #### Sample program
71//!
72//! You can test the agent by using the sample program, for example:
73//!
74//! ```notrust
75//! LD_LIBRARY_PATH=/path/to/libasyncProfiler.so cargo run --release --example simple -- --profiling-group PG --bucket-owner YOUR-AWS-ACCOUNT-ID --bucket YOUR_BUCKET_ID
76//! ```
77//!
78//! ### Host Metadata Auto-Detection
79//!
80//! The Rust agent currently auto-detects the machine's [EC2] or [Fargate] id using [IMDS].
81//!
82//! If you want to run the agent on a machine that is not EC2 or Fargate, you can use [`profiler::ProfilerBuilder::with_custom_agent_metadata`] to provide your own metadata.
83//!
84//! The metadata is not used by the agent directly, and only provided to the reporters, to allow them to associate the profiling data with the correct host. In the S3 reporter, it's used to generate the `metadata.json` and zip file name.
85//!
86//! [EC2]: https://aws.amazon.com/ec2
87//! [Fargate]: https://aws.amazon.com/fargate
88//! [IMDS]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
89//!
90//! ### PollCatch
91//!
92//! If you want to find long poll times, and you have `RUSTFLAGS="--cfg tokio_unstable"`, see the
93//! [pollcatch] module for emitting `tokio.PollCatchV1` events.
94mod asprof;
95
96pub mod metadata;
97pub mod pollcatch;
98pub mod profiler;
99pub mod reporter;