Skip to main content

modkit/telemetry/
config.rs

1//! OpenTelemetry tracing and metrics configuration types
2//!
3//! These types define the configuration structure for OpenTelemetry distributed
4//! tracing and metrics.
5
6use serde::{Deserialize, Serialize};
7use std::collections::{BTreeMap, HashMap};
8
9/// Top-level OpenTelemetry configuration grouping resource identity,
10/// a shared default exporter, tracing settings and metrics settings.
11#[derive(Debug, Clone, Deserialize, Serialize, Default)]
12#[serde(deny_unknown_fields)]
13pub struct OpenTelemetryConfig {
14    #[serde(default)]
15    pub resource: OpenTelemetryResource,
16    /// Default exporter shared by tracing and metrics. Per-signal `exporter`
17    /// fields override this when present.
18    pub exporter: Option<Exporter>,
19    #[serde(default)]
20    pub tracing: TracingConfig,
21    #[serde(default)]
22    pub metrics: MetricsConfig,
23}
24
25impl OpenTelemetryConfig {
26    /// Resolve the effective exporter for tracing (per-signal or shared fallback).
27    #[must_use]
28    pub fn tracing_exporter(&self) -> Option<&Exporter> {
29        self.tracing.exporter.as_ref().or(self.exporter.as_ref())
30    }
31    /// Resolve the effective exporter for metrics (per-signal or shared fallback).
32    #[must_use]
33    pub fn metrics_exporter(&self) -> Option<&Exporter> {
34        self.metrics.exporter.as_ref().or(self.exporter.as_ref())
35    }
36}
37
38/// OpenTelemetry resource identity — attached to all traces and metrics.
39#[derive(Debug, Clone, Deserialize, Serialize, Default)]
40#[serde(deny_unknown_fields)]
41pub struct OpenTelemetryResource {
42    /// Logical service name.
43    /// Fallback defaults (e.g. `"hyperspot"`) are applied by the application during telemetry initialization.
44    pub service_name: Option<String>,
45    /// Extra resource attributes added to every span and metric data point.
46    pub attributes: Option<BTreeMap<String, String>>,
47}
48
49/// Tracing configuration for OpenTelemetry distributed tracing
50#[derive(Debug, Clone, Deserialize, Serialize, Default)]
51#[serde(deny_unknown_fields)]
52pub struct TracingConfig {
53    pub enabled: bool,
54    /// Per-signal exporter override. When `None`, the shared
55    /// [`OpenTelemetryConfig::exporter`] is used instead.
56    pub exporter: Option<Exporter>,
57    pub sampler: Option<Sampler>,
58    pub propagation: Option<Propagation>,
59    pub http: Option<HttpOpts>,
60    pub logs_correlation: Option<LogsCorrelation>,
61}
62
63/// Metrics configuration for OpenTelemetry metrics collection
64#[derive(Debug, Clone, Deserialize, Serialize, Default)]
65#[serde(deny_unknown_fields)]
66pub struct MetricsConfig {
67    pub enabled: bool,
68    /// Per-signal exporter override. When `None`, the shared
69    /// [`OpenTelemetryConfig::exporter`] is used instead.
70    pub exporter: Option<Exporter>,
71    /// Maximum number of distinct attribute combinations per instrument.
72    /// When the limit is reached, new combinations are folded into an
73    /// overflow data point.  `None` means the SDK default is used.
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub cardinality_limit: Option<usize>,
76}
77
78#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq, Copy)]
79#[serde(rename_all = "snake_case")]
80pub enum ExporterKind {
81    #[default]
82    OtlpGrpc,
83    OtlpHttp,
84}
85
86#[derive(Debug, Clone, Deserialize, Serialize)]
87pub struct Exporter {
88    pub kind: ExporterKind,
89    pub endpoint: Option<String>,
90    pub headers: Option<HashMap<String, String>>,
91    pub timeout_ms: Option<u64>,
92}
93
94#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
95#[serde(rename_all = "snake_case")]
96pub enum Sampler {
97    ParentBasedAlwaysOn {},
98    ParentBasedRatio {
99        #[serde(skip_serializing_if = "Option::is_none")]
100        ratio: Option<f64>,
101    },
102    AlwaysOn {},
103    AlwaysOff {},
104}
105
106#[derive(Debug, Clone, Deserialize, Serialize)]
107pub struct Propagation {
108    pub w3c_trace_context: Option<bool>,
109}
110
111#[derive(Debug, Clone, Deserialize, Serialize)]
112pub struct HttpOpts {
113    pub inject_request_id_header: Option<String>,
114    pub record_headers: Option<Vec<String>>,
115}
116
117#[derive(Debug, Clone, Deserialize, Serialize)]
118pub struct LogsCorrelation {
119    pub inject_trace_ids_into_logs: Option<bool>,
120}