Skip to main content

kamu_logging/
lib.rs

1//! `kamu-logging` — opinionated `tracing` setup for PT IMMER services.
2//!
3//! # Feature surfaces
4//!
5//! - `correlation` — W3C `traceparent` parsing and correlation-id spans. Holds
6//!   no global state and installs nothing. Enable it alone from a library that
7//!   must not pick a subscriber on behalf of the binary embedding it.
8//! - `systemd` (default) — TTY-aware console and journald subscriber.
9//! - `wasm32` — JavaScript console subscriber and panic hook.
10//! - `with-actix-web` (default) — correlation-enriched Actix Web middleware.
11//! - `with-otlp` — OpenTelemetry OTLP exporter layer.
12//!
13//! `systemd`, `wasm32`, and `with-actix-web` each imply `correlation`, and at
14//! least one of the four must be enabled. `systemd` and `wasm32` are mutually
15//! exclusive, as are `wasm32` and the Actix Web and OTLP features; `with-otlp`
16//! requires `systemd`.
17#![cfg_attr(
18    any(feature = "systemd", feature = "wasm32"),
19    doc = r"
20# Initialization
21
22Call [`init`] from `main` for the zero-config path, or [`init_with`] with an
23[`InitOptions`] builder for explicit format / sink / filter / OTLP
24configuration. See the crate README for worked examples. On
25`wasm32-unknown-unknown`, enable only the `wasm32` feature to install a panic
26hook and emit `tracing` events to the JavaScript console. This path is suitable
27for Cloudflare Workers via `workers-rs`; systemd, Actix Web, and OTLP exporter
28features are native-only."
29)]
30//!
31//! Re-exports common `tracing` items so consumers can avoid a separate
32//! `tracing` import for the basic logging vocabulary.
33
34#![forbid(unsafe_code)]
35#![deny(missing_docs)]
36
37#[cfg(all(feature = "systemd", feature = "wasm32"))]
38compile_error!("Feature \"systemd\" can't be combined with \"wasm32\".");
39
40#[cfg(all(feature = "with-actix-web", feature = "wasm32"))]
41compile_error!("Feature \"with-actix-web\" can't be combined with \"wasm32\".");
42
43#[cfg(all(feature = "with-otlp", feature = "wasm32"))]
44compile_error!("Feature \"with-otlp\" can't be combined with \"wasm32\".");
45
46#[cfg(all(feature = "with-otlp", not(feature = "systemd")))]
47compile_error!("Feature \"with-otlp\" requires \"systemd\".");
48
49// `systemd`, `wasm32`, and `with-actix-web` each imply `correlation`, so this
50// single condition rejects the empty feature set on behalf of all of them.
51#[cfg(not(feature = "correlation"))]
52compile_error!(
53    "At least feature \"correlation\", \"systemd\", \"wasm32\", or \"with-actix-web\" must be enabled."
54);
55
56#[cfg(feature = "correlation")]
57pub mod correlation;
58
59#[cfg(any(feature = "systemd", feature = "wasm32"))]
60mod init;
61#[cfg(any(feature = "systemd", feature = "wasm32"))]
62mod options;
63
64#[cfg(feature = "with-actix-web")]
65mod actix;
66
67#[cfg(feature = "with-otlp")]
68pub mod otlp;
69
70#[cfg(any(feature = "systemd", feature = "wasm32"))]
71pub use crate::init::{init, init_or_skip, init_with};
72#[cfg(any(feature = "systemd", feature = "wasm32"))]
73pub use crate::options::{Format, InitOptions, ParseFormatError, ParseSinkError, Sink};
74
75#[cfg(feature = "with-actix-web")]
76pub use crate::actix::{EnrichedRootSpanBuilder, get_actix_web_logger, get_actix_web_logger_with};
77
78#[cfg(feature = "with-otlp")]
79pub use crate::otlp::{SpanProcessorMode, flush_otlp, shutdown_otlp};
80
81/// Re-exports of the common `tracing` vocabulary so consumers can
82/// `use kamu_logging::{info, instrument, ...}` without a separate import.
83pub use tracing::{Level, Span, debug, enabled, error, event, info, instrument, span, trace, warn};
84
85/// Errors returned by [`init`] / [`init_with`].
86///
87/// Marked `#[non_exhaustive]` so future variants are not breaking changes.
88#[cfg(any(feature = "systemd", feature = "wasm32"))]
89#[non_exhaustive]
90#[derive(thiserror::Error, Debug)]
91pub enum Error {
92    /// I/O failure during subscriber setup (typically the journald socket).
93    #[error("{0}")]
94    IO(#[from] std::io::Error),
95
96    /// This crate already installed the subscriber and `idempotent` was false.
97    #[error("logging subscriber already initialized")]
98    AlreadyInitialized,
99
100    /// The requested options are not supported on the selected target.
101    #[error("invalid logging configuration: {0}")]
102    InvalidConfiguration(String),
103
104    /// An environment variable contains an unsupported or malformed value.
105    #[error("invalid {variable}: expected {expected}")]
106    InvalidEnvironmentValue {
107        /// Name of the invalid environment variable.
108        variable: String,
109        /// Accepted grammar, without echoing the rejected value.
110        expected: &'static str,
111    },
112
113    /// Another crate installed the process-global tracing subscriber.
114    #[error("a foreign tracing subscriber already owns the process-global slot")]
115    ForeignGlobalSubscriber,
116
117    /// Another crate installed the process-global `log` facade.
118    ///
119    /// The tracing subscriber and any OTLP provider are already committed when
120    /// this error is returned; only the `log`-to-`tracing` bridge is foreign.
121    #[cfg(feature = "systemd")]
122    #[error("a foreign logger already owns the process-global log facade")]
123    ForeignGlobalLogger,
124
125    /// A prior installation panicked after claiming the tracing subscriber.
126    #[cfg(feature = "systemd")]
127    #[error("logging installation stopped before the log bridge committed")]
128    InstallationIncomplete,
129
130    /// OTLP exporter construction failed.
131    #[cfg(feature = "with-otlp")]
132    #[error("OTLP init failed: {0}")]
133    OtlpInit(String),
134}