1use std::collections::BTreeMap as Map;
6
7use famedly_rust_utils::LevelFilter;
8use serde::Deserialize;
9use url::Url;
10
11const DEFAULT_ENDPOINT: &str = "http://localhost:4317";
13
14#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
16#[derive(Debug, Clone, Deserialize)]
17#[repr(transparent)]
18#[serde(transparent)]
19#[allow(missing_docs)]
20pub struct OtelUrl {
21 pub url: Url,
22}
23
24impl From<Url> for OtelUrl {
25 fn from(url: Url) -> Self {
26 Self { url }
27 }
28}
29
30#[allow(clippy::expect_used)]
31impl Default for OtelUrl {
32 fn default() -> Self {
33 Self { url: Url::parse(DEFAULT_ENDPOINT).expect("Error parsing default endpoint") }
34 }
35}
36
37#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
39#[derive(Debug, Clone, Default, Deserialize)]
40pub struct OtelConfig {
41 pub stdout: Option<StdoutLogsConfig>,
43 pub exporter: Option<ExporterConfig>,
45}
46
47impl OtelConfig {
48 #[must_use]
50 pub fn for_tests() -> Self {
51 OtelConfig {
52 stdout: Some(StdoutLogsConfig {
53 enabled: true,
54 level: tracing_subscriber::filter::LevelFilter::TRACE.into(),
55 general_level: tracing_subscriber::filter::LevelFilter::INFO.into(),
56 json_output: false,
57 }),
58 exporter: None,
59 }
60 }
61}
62
63#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
65#[derive(Debug, Clone, Default, Deserialize)]
66pub struct ExporterConfig {
67 #[serde(default)]
69 pub endpoint: OtelUrl,
70 #[serde(default)]
74 pub resource_metadata: Map<String, String>,
75 pub logs: Option<ProviderConfig>,
77 pub traces: Option<ProviderConfig>,
79 pub metrics: Option<ProviderConfig>,
81}
82
83#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
85#[derive(Debug, Clone, Deserialize)]
86pub struct StdoutLogsConfig {
87 #[serde(default = "true_")]
89 pub enabled: bool,
90 #[serde(default = "default_level_filter")]
92 pub level: LevelFilter,
93 #[serde(default = "default_level_filter")]
95 pub general_level: LevelFilter,
96 #[serde(default)]
98 pub json_output: bool,
99}
100
101#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
103#[derive(Debug, Clone, Deserialize)]
104pub struct ProviderConfig {
105 #[serde(default)]
107 pub enabled: bool,
108 #[serde(default = "default_level_filter")]
110 pub level: LevelFilter,
111 #[serde(default = "default_level_filter")]
113 pub general_level: LevelFilter,
114}
115
116impl ProviderConfig {
117 pub(crate) fn get_filter(&self, crate_name: &'static str) -> String {
119 format!("{},{}={}", self.general_level, crate_name, self.level)
120 }
121}
122
123impl StdoutLogsConfig {
124 pub(crate) fn get_filter(&self, crate_name: &'static str) -> String {
126 format!("{},{}={}", self.general_level, crate_name, self.level)
127 }
128}
129
130impl Default for StdoutLogsConfig {
131 fn default() -> Self {
132 Self {
133 enabled: true,
134 level: default_level_filter(),
135 general_level: default_level_filter(),
136 json_output: false,
137 }
138 }
139}
140
141impl Default for ProviderConfig {
142 fn default() -> Self {
143 Self {
144 enabled: false,
145 level: default_level_filter(),
146 general_level: default_level_filter(),
147 }
148 }
149}
150
151const fn default_level_filter() -> LevelFilter {
153 LevelFilter(tracing::level_filters::LevelFilter::INFO)
154}
155
156const fn true_() -> bool {
158 true
159}