1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
//! # Datadog Formatting Layer
//!
//! A crate providing a tracing-subscriber layer for formatting events so Datadog can parse them.
//!
//! ## Features
//! - Provides a layer for tracing-subscriber
//! - Generates parsable "logs" for datadog and prints them to stdout
//! - Enables log correlation between spans and "logs" (see [datadog docs](https://docs.datadoghq.com/tracing/other_telemetry/connect_logs_and_traces/))
//!
//! ## Why not just `tracing_subscriber::fmt().json()` ?
//! The problem is, that datadog expects the "logs" to be in a specific (mostly undocumented) json format.
//!
//! This crates tries to mimic this format.
//!
//! ## Usage
//!
//! ### Simple
//!
//! ```
//! use datadog_formatting_layer::DatadogFormattingLayer;
//! use tracing::info;
//! use tracing_subscriber::prelude::*;
//!
//! tracing_subscriber::registry()
//! .with(DatadogFormattingLayer)
//! .init();
//!
//! info!(user = "Jack", "Hello World!");
//! ```
//!
//! Running this code will result in the following output on stdout:
//!
//! ```json
//! {"timestamp":"2023-06-21T10:36:50.364874878+00:00","level":"INFO","message":"Hello World user=Jack","target":"simple"}
//! ```
//!
//! ### With Opentelemetry
//! ```
//! use datadog_formatting_layer::DatadogFormattingLayer;
//! use opentelemetry::{
//! global,
//! sdk::{
//! propagation::TraceContextPropagator,
//! trace::{RandomIdGenerator, Sampler},
//! },
//! };
//! use opentelemetry_datadog::ApiVersion;
//! use tracing::{debug, error, info, instrument, warn};
//! use tracing_subscriber::{prelude::*, util::SubscriberInitExt};
//!
//! // Just some otel boilerplate
//! global::set_text_map_propagator(TraceContextPropagator::new());
//!
//! let tracer = opentelemetry_datadog::new_pipeline()
//! .with_service_name("my-service")
//! .with_trace_config(
//! opentelemetry::sdk::trace::config()
//! .with_sampler(Sampler::AlwaysOn)
//! .with_id_generator(RandomIdGenerator::default()),
//! )
//! .with_api_version(ApiVersion::Version05)
//! .with_env("rls")
//! .with_version("420")
//! .install_simple()
//! .unwrap();
//!
//! // Use both the tracer and the formatting layer
//! tracing_subscriber::registry()
//! .with(DatadogFormattingLayer)
//! .with(tracing_opentelemetry::layer().with_tracer(tracer))
//! .init();
//!
//! // Here no span exists
//! info!(user = "Jack", "Hello World!");
//! some_test("fasel");
//!
//! // This will create a span and a trace id which is attached to the "logs"
//! #[instrument(fields(hello = "world"))]
//! fn some_test(value: &str) {
//! // Here some span exists
//! info!(ola = "salve", value, "Bla {value}");
//! }
//! ```
//!
//! When running this code with an datadog agent installed the logs will be sent to datadog
//! and parsed there.
//!
//! Otherwise the following output will be printed to stdout
//!
//! ```json
//! {"timestamp":"2023-06-21T10:36:50.363224217+00:00","level":"INFO","message":"Hello World! user=Jack","target":"otel"}
//! {"timestamp":"2023-06-21T10:36:50.363384118+00:00","level":"INFO","message":"Bla fasel user=Jack ola=salve value=Fasel hello=world","target":"otel","dd.trace_id":0,"dd.span_id":10201226522570980512}
//! ```
mod datadog_ids;
mod fields;
mod layer;
// reexport
pub use layer::DatadogFormattingLayer;