sentry_tracing/lib.rs
1//! Support for automatic breadcrumb, event, and trace capturing from `tracing` events and spans.
2//!
3//! The `tracing` crate is supported in four ways:
4//! - `tracing` events can be captured as Sentry events. These are grouped and show up in the Sentry
5//! [issues](https://docs.sentry.io/product/issues/) page, representing high severity issues to be
6//! acted upon.
7//! - `tracing` events can be captured as [breadcrumbs](https://docs.sentry.io/product/issues/issue-details/breadcrumbs/).
8//! Breadcrumbs create a trail of what happened prior to an event, and are therefore sent only when
9//! an event is captured, either manually through e.g. `sentry::capture_message` or through integrations
10//! (e.g. the panic integration is enabled (default) and a panic happens).
11//! - `tracing` events can be captured as traditional [structured logs](https://docs.sentry.io/product/explore/logs/).
12//! The `tracing` fields are captured as attributes on the logs, which can be queried in the Logs
13//! explorer. (Available on crate feature `logs`)
14//! - `tracing` spans can be captured as Sentry spans. These can be used to provide more contextual
15//! information for errors, diagnose [performance
16//! issues](https://docs.sentry.io/product/insights/overview/), and capture additional attributes to
17//! aggregate and compute [metrics](https://docs.sentry.io/product/explore/trace-explorer/).
18//!
19//! By default, events above `Info` are recorded as breadcrumbs, events above `Error` are captured
20//! as error events, and spans above `Info` are recorded as spans.
21//!
22//! # Configuration
23//!
24//! To fully enable the tracing integration, set the traces sample rate and add a layer to the
25//! tracing subscriber:
26//!
27//! ```
28//! use tracing_subscriber::prelude::*;
29//!
30//! let _guard = sentry::init(sentry::ClientOptions {
31//! // Enable capturing of traces; set this a to lower value in production:
32//! traces_sample_rate: 1.0,
33//! ..sentry::ClientOptions::default()
34//! });
35//!
36//! // Register the Sentry tracing layer to capture breadcrumbs, events, and spans:
37//! tracing_subscriber::registry()
38//! .with(tracing_subscriber::fmt::layer())
39//! .with(sentry::integrations::tracing::layer())
40//! .init();
41//! ```
42//!
43//! You can customize the behavior of the layer by providing an explicit event filter, to customize which events
44//! are captured by Sentry and the data type they are mapped to.
45//! Similarly, you can provide a span filter to customize which spans are captured by Sentry.
46//!
47//! ```
48//! use sentry::integrations::tracing::EventFilter;
49//! use tracing_subscriber::prelude::*;
50//!
51//! let sentry_layer = sentry::integrations::tracing::layer()
52//! .event_filter(|md| match *md.level() {
53//! tracing::Level::ERROR => EventFilter::Event,
54//! _ => EventFilter::Ignore,
55//! })
56//! .span_filter(|md| matches!(*md.level(), tracing::Level::ERROR | tracing::Level::WARN));
57//!
58//! tracing_subscriber::registry()
59//! .with(tracing_subscriber::fmt::layer())
60//! .with(sentry_layer)
61//! .init();
62//! ```
63//!
64//! In addition, a custom event mapper can be provided, to fully customize if and how `tracing` events are converted to Sentry data.
65//!
66//! Note that if both an event mapper and event filter are set, the mapper takes precedence, thus the
67//! filter has no effect.
68//!
69//! # Capturing breadcrumbs
70//!
71//! Tracing events automatically create breadcrumbs that are attached to the current scope in
72//! Sentry. They show up on errors and transactions captured within this scope as shown in the
73//! examples below.
74//!
75//! Fields passed to the event macro are automatically tracked as structured data in Sentry. For
76//! breadcrumbs, they are shown directly with the breadcrumb message. For other types of data, read
77//! below.
78//!
79//! ```
80//! for i in 0..10 {
81//! tracing::debug!(number = i, "Generates a breadcrumb");
82//! }
83//! ```
84//!
85//! # Capturing logs
86//!
87//! Tracing events can be captured as traditional structured logs in Sentry.
88//! This is gated by the `logs` feature flag and requires setting up a custom Event filter/mapper
89//! to capture logs.
90//!
91//! ```
92//! // assuming `tracing::Level::INFO => EventFilter::Log` in your `event_filter`
93//! for i in 0..10 {
94//! tracing::info!(number = i, my.key = "val", my.num = 42, "This is a log");
95//! }
96//! ```
97//!
98//! The fields of a `tracing` event are captured as attributes of the log.
99//! Logs can be viewed and queried in the Logs explorer based on message and attributes.
100//! Fields containing dots will be displayed as nested under their common prefix in the UI.
101//!
102//! # Tracking Errors
103//!
104//! The easiest way to emit errors is by logging an event with `ERROR` level. This will create a
105//! grouped issue in Sentry. To add custom information, prepend the message with fields. It is also
106//! possible to add Sentry tags if a field is prefixed with `"tags."`
107//!
108//! ```
109//! tracing::error!(
110//! field = "value", // will become a context field
111//! tags.custom = "value", // will become a tag in Sentry
112//! "this is an error with a custom tag",
113//! );
114//! ```
115//!
116//! To track [error structs](std::error::Error), assign a reference to error trait object as field
117//! in one of the logging macros. By convention, it is recommended to use the `ERROR` level and
118//! assign it to a field called `error`, although the integration will also work with all other
119//! levels and field names.
120//!
121//! All other fields passed to the macro are captured in a custom "Tracing Fields" context in
122//! Sentry.
123//!
124//! ```
125//! use std::error::Error;
126//! use std::io;
127//!
128//! let custom_error = io::Error::new(io::ErrorKind::Other, "oh no");
129//! tracing::error!(error = &custom_error as &dyn Error);
130//! ```
131//!
132//! It is also possible to combine error messages with error structs. In Sentry, this creates issues
133//! grouped by the message and location of the error log, and adds the passed error as nested
134//! source.
135//!
136//! ```
137//! use std::error::Error;
138//! use std::io;
139//!
140//! let custom_error = io::Error::new(io::ErrorKind::Other, "oh no");
141//! tracing::error!(error = &custom_error as &dyn Error, "my operation failed");
142//! ```
143//!
144//! # Tracing Spans
145//!
146//! The integration automatically tracks `tracing` spans as spans in Sentry. A convenient way to do
147//! this is with the `#[instrument]` attribute macro, which creates a transaction for the function
148//! in Sentry.
149//!
150//! Function arguments are added as context fields automatically, which can be configured through
151//! attribute arguments. Refer to documentation of the macro for more information.
152//!
153//! ```
154//! use std::time::Duration;
155//!
156//! use tracing_subscriber::prelude::*;
157//!
158//! // Functions instrumented by tracing automatically report
159//! // their span as transactions.
160//! #[tracing::instrument]
161//! async fn outer() {
162//! for i in 0..10 {
163//! inner(i).await;
164//! }
165//! }
166//!
167//! // This creates spans inside the outer transaction, unless called directly.
168//! #[tracing::instrument]
169//! async fn inner(i: u32) {
170//! // Also works, since log events are ingested by the tracing system
171//! tracing::debug!(number = i, "Generates a breadcrumb");
172//!
173//! tokio::time::sleep(Duration::from_millis(100)).await;
174//! }
175//! ```
176
177#![doc(html_favicon_url = "https://sentry-brand.storage.googleapis.com/favicon.ico")]
178#![doc(html_logo_url = "https://sentry-brand.storage.googleapis.com/sentry-glyph-black.png")]
179#![warn(missing_docs)]
180
181mod converters;
182mod layer;
183
184pub use converters::*;
185pub use layer::*;
186
187const TAGS_PREFIX: &str = "tags.";