Skip to main content

modo/tracing/
mod.rs

1//! # modo::tracing
2//!
3//! Tracing initialisation and structured logging for modo applications.
4//!
5//! Configures [`tracing_subscriber`] at application startup. Call [`init`]
6//! once from `main` — typically before starting the HTTP server — and hold
7//! the returned [`TracingGuard`] for the lifetime of the process.
8//!
9//! ## Provides
10//!
11//! | Item | Description |
12//! |------|-------------|
13//! | [`Config`] | Log level, output format, and optional Sentry settings |
14//! | [`init`] | Initialises the global tracing subscriber; returns [`TracingGuard`] |
15//! | [`TracingGuard`] | RAII guard that keeps the subscriber (and Sentry client) alive |
16//! | [`SentryConfig`] | Sentry DSN, environment, and sampling rates |
17//! | `info!`, `debug!`, `warn!`, `error!`, `trace!` | Re-exported tracing macros |
18//!
19//! ## Log format
20//!
21//! The format is selected by [`Config::format`]:
22//!
23//! | Value | Description |
24//! |-------|-------------|
25//! | `"pretty"` (default) | Human-readable multi-line output |
26//! | `"json"` | Machine-readable JSON, one object per line |
27//! | anything else | Compact single-line output |
28//!
29//! The active log level is read from the `RUST_LOG` environment variable
30//! when present; otherwise [`Config::level`] is used.
31//!
32//! ## Sentry integration
33//!
34//! Sentry support is always compiled in. Populate [`SentryConfig`] inside
35//! [`Config::sentry`] with a non-empty DSN to enable error and performance
36//! reporting at runtime. The Sentry SDK is initialised inside [`init`] and
37//! flushed when the [`TracingGuard`] is shut down. When the DSN is empty
38//! or the `sentry` section is omitted, Sentry is silently skipped.
39//!
40//! ## HTTP request spans
41//!
42//! This module only handles *subscriber* setup. HTTP request/response
43//! spans are produced by [`crate::middleware::tracing`], which wires a
44//! `tower_http::trace::TraceLayer` with a `ModoMakeSpan` that pre-declares
45//! a `tenant_id` field (initially empty) so the tenant middleware can
46//! later record it via `span.record("tenant_id", ...)`. All tracing field
47//! names use snake_case (`user_id`, `session_id`, `job_id`, etc.).
48//!
49//! ## Quick start
50//!
51//! ```rust,no_run
52//! use modo::config::load;
53//! use modo::Config;
54//! use modo::runtime::Task;
55//!
56//! #[tokio::main]
57//! async fn main() -> modo::Result<()> {
58//!     let config: Config = load("config/").unwrap();
59//!     let guard = modo::tracing::init(&config.tracing)?;
60//!
61//!     // ... start server, then on shutdown:
62//!     guard.shutdown().await
63//! }
64//! ```
65
66mod init;
67mod sentry;
68
69pub use init::{Config, init};
70pub use sentry::SentryConfig;
71pub use sentry::TracingGuard;
72
73// Re-export tracing macros so $crate::tracing::info! works in run! macro
74pub use ::tracing::{debug, error, info, trace, warn};