diff --git a/README.md b/README.md index 5913abf8b..6370374e3 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,12 @@ This workspace contains various crates that provide support for logging events a An integration for the `log` and `env_logger` crate. +- [sentry-opentelemetry](./sentry-opentelemetry) + [![crates.io](https://img.shields.io/crates/v/sentry-opentelemetry.svg)](https://crates.io/crates/sentry-opentelemetry) + [![docs.rs](https://docs.rs/sentry-opentelemetry/badge.svg)](https://docs.rs/sentry-opentelemetry) + + An integration for the `opentelemetry` crate. + - [sentry-panic](./sentry-panic) [![crates.io](https://img.shields.io/crates/v/sentry-panic.svg)](https://crates.io/crates/sentry-panic) [![docs.rs](https://docs.rs/sentry-panic/badge.svg)](https://docs.rs/sentry-panic) diff --git a/sentry-opentelemetry/README.md b/sentry-opentelemetry/README.md new file mode 100644 index 000000000..9a01766cb --- /dev/null +++ b/sentry-opentelemetry/README.md @@ -0,0 +1,94 @@ +

+ + Sentry + +

+ +# Sentry Rust SDK: sentry-opentelemetry + +Support for capturing Sentry spans from OpenTelemetry spans. + +Sentry spans are automatically captured from OpenTelemetry spans via `SentrySpanProcessor`. +Distributed tracing is supported via `SentryPropagator`. +Note that it's assumed that only the OTEL API is used to create and manage spans. +Mixing the OTEL and Sentry tracing API will not work, and will result in separate traces being captured. +Using the Sentry API for other purposes is supported. +For example, capturing an error inside a span will correctly send it to Sentry with the span association. + +If you're using `tracing-opentelemetry`, use `sentry-tracing` instead. + +# Configuration + +Add the necessary dependencies to your Cargo.toml: + +```toml +[dependencies] +opentelemetry = { version = "0.29.1", features = ["trace"] } +opentelemetry_sdk = { version = "0.29.0", features = ["trace"] } +sentry = { version = "0.38.0", features = ["opentelemetry"] } +``` + +Initialize Sentry with a `traces_sample_rate`, then register the [`SentryPropagator`] and the +[`SentrySpanProcessor`]: + +```rust +use opentelemetry::{ + global, + trace::{TraceContextExt, Tracer}, + KeyValue, +}; +use opentelemetry_sdk::trace::SdkTracerProvider; +use sentry::integrations::opentelemetry as sentry_opentelemetry; + +// Initialize the Sentry SDK +let _guard = sentry::init(( + "https://your-dsn@sentry.io/0", + sentry::ClientOptions { + // Enable capturing of traces; set this a to lower value in production. + // For more sophisticated behavior use a custom + // [`sentry::ClientOptions::traces_sampler`] instead. + // That's the equivalent of a tail sampling processor in OpenTelemetry. + // These options will only affect sampling of the spans that are sent to Sentry, + // not of the underlying OpenTelemetry spans. + traces_sample_rate: 1.0, + debug: true, + ..sentry::ClientOptions::default() + }, +)); + +// Register the Sentry propagator to enable distributed tracing +global::set_text_map_propagator(sentry_opentelemetry::SentryPropagator::new()); + +let tracer_provider = SdkTracerProvider::builder() + // Register the Sentry span processor to send OpenTelemetry spans to Sentry + .with_span_processor(sentry_opentelemetry::SentrySpanProcessor::new()) + .build(); + +global::set_tracer_provider(tracer_provider); +``` + +# Usage + +Use the OpenTelemetry API to create spans. They will be captured by Sentry: + +```rust +let tracer = global::tracer("tracer"); +// Creates a Sentry span (transaction) with the name set to "example" +tracer.in_span("example", |_| { + // Creates a Sentry child span with the name set to "child" + tracer.in_span("child", |cx| { + // OTEL span attributes are captured as data attributes on the Sentry span + cx.span().set_attribute(KeyValue::new("my", "attribute")); + + // Captures a Sentry error message and associates it with the ongoing child span + sentry::capture_message("Everything is on fire!", sentry::Level::Error); + }); +}); +``` + +## Resources + +License: MIT + +- [Discord](https://discord.gg/ez5KZN7) server for project discussions. +- Follow [@getsentry](https://twitter.com/getsentry) on Twitter for updates diff --git a/sentry-opentelemetry/src/lib.rs b/sentry-opentelemetry/src/lib.rs index d9de713ba..95c7edc0d 100644 --- a/sentry-opentelemetry/src/lib.rs +++ b/sentry-opentelemetry/src/lib.rs @@ -2,35 +2,53 @@ //! //! This integration allows you to capture spans from your existing OpenTelemetry setup and send //! them to Sentry, with support for distributed tracing. +//! //! It's assumed that only the [OpenTelemetry tracing //! API](https://opentelemetry.io/docs/specs/otel/trace/api/) is used to start/end/modify Spans. //! Mixing it with the Sentry tracing API (e.g. `sentry_core::start_transaction(ctx)`) will not //! work, as the spans created with the two methods will not be nested properly. -//! Capturing events (either manually with e.g. `sentry::capture_event`, or automatically with e.g. the -//! `sentry-panic` integration) will send them to Sentry with the correct trace and span -//! association. +//! +//! Capturing events with `sentry::capture_event` will send them to Sentry with the correct +//! trace and span association. //! //! # Configuration //! -//! Initialize Sentry, then register the [`SentryPropagator`] and the [`SentrySpanProcessor`]: +//! Add the necessary dependencies to your Cargo.toml: +//! +//! ```toml +//! [dependencies] +//! opentelemetry = { version = "0.29.1", features = ["trace"] } +//! opentelemetry_sdk = { version = "0.29.0", features = ["trace"] } +//! sentry = { version = "0.38.0", features = ["opentelemetry"] } +//! ``` +//! +//! Initialize Sentry with a `traces_sample_rate`, then register the [`SentryPropagator`] and the +//! [`SentrySpanProcessor`]: //! //! ``` -//! use opentelemetry::{global}; -//! use opentelemetry_sdk::{ -//! propagation::TraceContextPropagator, trace::SdkTracerProvider, +//! use opentelemetry::{ +//! global, +//! trace::{TraceContextExt, Tracer}, +//! KeyValue, //! }; +//! use opentelemetry_sdk::trace::SdkTracerProvider; +//! use sentry::integrations::opentelemetry as sentry_opentelemetry; //! //! // Initialize the Sentry SDK -//! let _guard = sentry::init(sentry::ClientOptions { -//! // Enable capturing of traces; set this a to lower value in production. -//! // For more sophisticated behavior use a custom -//! // [`sentry::ClientOptions::traces_sampler`] instead. -//! // That's the equivalent of a tail sampling processor in OpenTelemetry. -//! // These options will only affect sampling of the spans that are sent to Sentry, -//! // not of the underlying OpenTelemetry spans. -//! traces_sample_rate: 1.0, -//! ..sentry::ClientOptions::default() -//! }); +//! let _guard = sentry::init(( +//! "https://your-dsn@sentry.io/0", +//! sentry::ClientOptions { +//! // Enable capturing of traces; set this a to lower value in production. +//! // For more sophisticated behavior use a custom +//! // [`sentry::ClientOptions::traces_sampler`] instead. +//! // That's the equivalent of a tail sampling processor in OpenTelemetry. +//! // These options will only affect sampling of the spans that are sent to Sentry, +//! // not of the underlying OpenTelemetry spans. +//! traces_sample_rate: 1.0, +//! debug: true, +//! ..sentry::ClientOptions::default() +//! }, +//! )); //! //! // Register the Sentry propagator to enable distributed tracing //! global::set_text_map_propagator(sentry_opentelemetry::SentryPropagator::new()); @@ -42,6 +60,25 @@ //! //! global::set_tracer_provider(tracer_provider); //! ``` +//! +//! # Usage +//! +//! Use the OpenTelemetry API to create spans. They will be captured by Sentry: +//! +//! ```no_run +//! let tracer = global::tracer("tracer"); +//! // Creates a Sentry span (transaction) with the name set to "example" +//! tracer.in_span("example", |_| { +//! // Creates a Sentry child span with the name set to "child" +//! tracer.in_span("child", |cx| { +//! // OTEL span attributes are captured as data attributes on the Sentry span +//! cx.span().set_attribute(KeyValue::new("my", "attribute")); +//! +//! // Captures a Sentry error message and associates it with the ongoing child span +//! sentry::capture_message("Everything is on fire!", sentry::Level::Error); +//! }); +//! }); +//! ``` mod converters; mod processor; diff --git a/sentry/README.md b/sentry/README.md index 9da99f0b5..38b794521 100644 --- a/sentry/README.md +++ b/sentry/README.md @@ -80,14 +80,20 @@ extra setup to function properly. | `reqwest` | ✅ | | | | | `native-tls` | ✅ | | | `reqwest` must be enabled. | | `rustls` | | | | `reqwest` must be enabled. `native-tls` must be disabled via `default-features = false`. | -| `curl` | | | | | -| `tower` | | 🔌 | | Requires extra setup; See [`sentry-tower`]'s documentation. | | `ureq` | | | | `ureq` transport support using `rustls` by default | | `ureq-native-tls` | | | | | +| `curl` | | | | | +| `actix` | | 🔌 | | Requires extra setup; See [`sentry-actix`]'s documentation. | +| `tower` | | 🔌 | | Requires extra setup; See [`sentry-tower`]'s documentation. | +| `tracing` | | 🔌 | | Requires extra setup; See [`sentry-tracing`]'s documentation. | +| `opentelemetry` | | 🔌 | | Requires extra setup; See [`sentry-opentelemetry`]'s documentation. | [`sentry-log`]: https://crates.io/crates/sentry-log [`sentry-slog`]: https://crates.io/crates/sentry-slog +[`sentry-actix`]: https://crates.io/crates/sentry-actix [`sentry-tower`]: https://crates.io/crates/sentry-tower +[`sentry-tracing`]: https://crates.io/crates/sentry-tracing +[`sentry-opentelemetry`]: https://crates.io/crates/sentry-opentelemetry ### Default features - `backtrace`: Enables backtrace support. @@ -116,7 +122,10 @@ extra setup to function properly. - `ureq-native-tls`: Enables the `ureq` transport using `native-tls`. ### Integrations +- `actix`: Enables support for the `actix-web` crate. - `tower`: Enables support for the `tower` crate and those using it. +- `tracing`: Enables support for the `tracing` crate and those using it. +- `opentelemetry`: Enables support for the `opentelemetry` and `opentelemetry-sdk` crates. ## Resources diff --git a/sentry/src/lib.rs b/sentry/src/lib.rs index 352094d75..27144321a 100644 --- a/sentry/src/lib.rs +++ b/sentry/src/lib.rs @@ -52,6 +52,7 @@ //! [`Transport`]: trait.Transport.html //! [`sentry-core`]: https://crates.io/crates/sentry-core //! +//! //! # Features //! //! Additional functionality and integrations are enabled via feature flags. Some features require @@ -72,14 +73,20 @@ //! | `reqwest` | ✅ | | | | //! | `native-tls` | ✅ | | | `reqwest` must be enabled. | //! | `rustls` | | | | `reqwest` must be enabled. `native-tls` must be disabled via `default-features = false`. | -//! | `curl` | | | | | -//! | `tower` | | 🔌 | | Requires extra setup; See [`sentry-tower`]'s documentation. | //! | `ureq` | | | | `ureq` transport support using `rustls` by default | //! | `ureq-native-tls` | | | | | +//! | `curl` | | | | | +//! | `actix` | | 🔌 | | Requires extra setup; See [`sentry-actix`]'s documentation. | +//! | `tower` | | 🔌 | | Requires extra setup; See [`sentry-tower`]'s documentation. | +//! | `tracing` | | 🔌 | | Requires extra setup; See [`sentry-tracing`]'s documentation. | +//! | `opentelemetry` | | 🔌 | | Requires extra setup; See [`sentry-opentelemetry`]'s documentation. | //! //! [`sentry-log`]: https://crates.io/crates/sentry-log //! [`sentry-slog`]: https://crates.io/crates/sentry-slog +//! [`sentry-actix`]: https://crates.io/crates/sentry-actix //! [`sentry-tower`]: https://crates.io/crates/sentry-tower +//! [`sentry-tracing`]: https://crates.io/crates/sentry-tracing +//! [`sentry-opentelemetry`]: https://crates.io/crates/sentry-opentelemetry //! //! ## Default features //! - `backtrace`: Enables backtrace support. @@ -108,7 +115,10 @@ //! - `ureq-native-tls`: Enables the `ureq` transport using `native-tls`. //! //! ## Integrations +//! - `actix`: Enables support for the `actix-web` crate. //! - `tower`: Enables support for the `tower` crate and those using it. +//! - `tracing`: Enables support for the `tracing` crate and those using it. +//! - `opentelemetry`: Enables support for the `opentelemetry` and `opentelemetry-sdk` crates. #![doc(html_favicon_url = "https://sentry-brand.storage.googleapis.com/favicon.ico")] #![doc(html_logo_url = "https://sentry-brand.storage.googleapis.com/sentry-glyph-black.png")]