cognee_observability/
settings.rs1pub trait SettingsView: Send + Sync {
14 fn tracing_enabled(&self) -> bool;
16 fn service_name(&self) -> &str;
18 fn otlp_endpoint(&self) -> &str;
20 fn otlp_headers(&self) -> &str;
22 fn otlp_protocol(&self) -> &str;
24 fn span_processor(&self) -> &str;
26 fn traces_sampler(&self) -> &str;
28 fn traces_sampler_arg(&self) -> &str;
30}
31
32pub(crate) const DEFAULT_TRACING_ENABLED: bool = false;
36pub(crate) const DEFAULT_SERVICE_NAME: &str = "cognee";
37pub(crate) const DEFAULT_OTLP_ENDPOINT: &str = "";
38pub(crate) const DEFAULT_OTLP_HEADERS: &str = "";
39pub(crate) const DEFAULT_OTLP_PROTOCOL: &str = "grpc";
40pub(crate) const DEFAULT_SPAN_PROCESSOR: &str = "batch";
41pub(crate) const DEFAULT_TRACES_SAMPLER: &str = "";
42pub(crate) const DEFAULT_TRACES_SAMPLER_ARG: &str = "";
43
44#[derive(Debug, Clone)]
49pub struct EnvSettingsView {
50 tracing_enabled: bool,
51 service_name: String,
52 otlp_endpoint: String,
53 otlp_headers: String,
54 otlp_protocol: String,
55 span_processor: String,
56 traces_sampler: String,
57 traces_sampler_arg: String,
58}
59
60impl Default for EnvSettingsView {
61 fn default() -> Self {
62 Self {
63 tracing_enabled: DEFAULT_TRACING_ENABLED,
64 service_name: DEFAULT_SERVICE_NAME.to_string(),
65 otlp_endpoint: DEFAULT_OTLP_ENDPOINT.to_string(),
66 otlp_headers: DEFAULT_OTLP_HEADERS.to_string(),
67 otlp_protocol: DEFAULT_OTLP_PROTOCOL.to_string(),
68 span_processor: DEFAULT_SPAN_PROCESSOR.to_string(),
69 traces_sampler: DEFAULT_TRACES_SAMPLER.to_string(),
70 traces_sampler_arg: DEFAULT_TRACES_SAMPLER_ARG.to_string(),
71 }
72 }
73}
74
75impl EnvSettingsView {
76 pub fn from_env() -> Self {
79 let mut view = Self::default();
80
81 if let Some(v) = read_env("COGNEE_TRACING_ENABLED") {
82 view.tracing_enabled = cognee_utils::parse_env_bool(&v);
83 }
84 if let Some(v) = read_env("OTEL_SERVICE_NAME") {
85 view.service_name = v;
86 }
87 if let Some(v) = read_env("OTEL_EXPORTER_OTLP_ENDPOINT") {
88 view.otlp_endpoint = v;
89 }
90 if let Some(v) = read_env("OTEL_EXPORTER_OTLP_HEADERS") {
91 view.otlp_headers = v;
92 }
93 if let Some(v) = read_env("OTEL_EXPORTER_OTLP_PROTOCOL") {
94 view.otlp_protocol = v;
95 }
96 if let Some(v) = read_env("OTEL_SPAN_PROCESSOR") {
97 view.span_processor = v;
98 }
99 if let Some(v) = read_env("OTEL_TRACES_SAMPLER") {
100 view.traces_sampler = v;
101 }
102 if let Some(v) = read_env("OTEL_TRACES_SAMPLER_ARG") {
103 view.traces_sampler_arg = v;
104 }
105
106 view
107 }
108}
109
110fn read_env(key: &str) -> Option<String> {
113 match std::env::var(key) {
114 Ok(v) if !v.is_empty() => Some(v),
115 _ => None,
116 }
117}
118
119impl SettingsView for EnvSettingsView {
120 fn tracing_enabled(&self) -> bool {
121 self.tracing_enabled
122 }
123 fn service_name(&self) -> &str {
124 &self.service_name
125 }
126 fn otlp_endpoint(&self) -> &str {
127 &self.otlp_endpoint
128 }
129 fn otlp_headers(&self) -> &str {
130 &self.otlp_headers
131 }
132 fn otlp_protocol(&self) -> &str {
133 &self.otlp_protocol
134 }
135 fn span_processor(&self) -> &str {
136 &self.span_processor
137 }
138 fn traces_sampler(&self) -> &str {
139 &self.traces_sampler
140 }
141 fn traces_sampler_arg(&self) -> &str {
142 &self.traces_sampler_arg
143 }
144}
145
146#[cfg(test)]
147#[allow(
148 clippy::expect_used,
149 clippy::unwrap_used,
150 reason = "test code — panics are acceptable failures"
151)]
152mod tests {
153 use super::*;
154 use std::sync::Mutex;
155
156 static ENV_LOCK: Mutex<()> = Mutex::new(());
159
160 fn clear_otel_env() {
161 for key in [
162 "COGNEE_TRACING_ENABLED",
163 "OTEL_SERVICE_NAME",
164 "OTEL_EXPORTER_OTLP_ENDPOINT",
165 "OTEL_EXPORTER_OTLP_HEADERS",
166 "OTEL_EXPORTER_OTLP_PROTOCOL",
167 "OTEL_SPAN_PROCESSOR",
168 "OTEL_TRACES_SAMPLER",
169 "OTEL_TRACES_SAMPLER_ARG",
170 ] {
171 unsafe { std::env::remove_var(key) };
174 }
175 }
176
177 #[test]
178 fn from_env_empty_matches_defaults() {
179 let _g = ENV_LOCK.lock().expect("env lock poisoned");
180 clear_otel_env();
181
182 let view = EnvSettingsView::from_env();
183 assert!(!view.tracing_enabled());
184 assert_eq!(view.service_name(), DEFAULT_SERVICE_NAME);
185 assert_eq!(view.otlp_endpoint(), DEFAULT_OTLP_ENDPOINT);
186 assert_eq!(view.otlp_headers(), DEFAULT_OTLP_HEADERS);
187 assert_eq!(view.otlp_protocol(), DEFAULT_OTLP_PROTOCOL);
188 assert_eq!(view.span_processor(), DEFAULT_SPAN_PROCESSOR);
189 assert_eq!(view.traces_sampler(), DEFAULT_TRACES_SAMPLER);
190 assert_eq!(view.traces_sampler_arg(), DEFAULT_TRACES_SAMPLER_ARG);
191 }
192
193 #[test]
194 fn tracing_enabled_truthy_values() {
195 let _g = ENV_LOCK.lock().expect("env lock poisoned");
196 for v in ["true", "TRUE", "1", "yes", "YES"] {
197 clear_otel_env();
198 unsafe { std::env::set_var("COGNEE_TRACING_ENABLED", v) };
199 let view = EnvSettingsView::from_env();
200 assert!(view.tracing_enabled(), "{v} should enable tracing");
201 }
202 }
203
204 #[test]
205 fn tracing_enabled_falsy_values() {
206 let _g = ENV_LOCK.lock().expect("env lock poisoned");
207 for v in ["false", "0", "no", "off", "anything-else"] {
208 clear_otel_env();
209 unsafe { std::env::set_var("COGNEE_TRACING_ENABLED", v) };
210 let view = EnvSettingsView::from_env();
211 assert!(!view.tracing_enabled(), "{v} should not enable tracing");
212 }
213 }
214
215 #[test]
216 fn from_env_reads_all_fields() {
217 let _g = ENV_LOCK.lock().expect("env lock poisoned");
218 clear_otel_env();
219 unsafe {
220 std::env::set_var("COGNEE_TRACING_ENABLED", "true");
221 std::env::set_var("OTEL_SERVICE_NAME", "my-svc");
222 std::env::set_var("OTEL_EXPORTER_OTLP_ENDPOINT", "http://collector:4317");
223 std::env::set_var("OTEL_EXPORTER_OTLP_HEADERS", "x-key=val");
224 std::env::set_var("OTEL_EXPORTER_OTLP_PROTOCOL", "http/protobuf");
225 std::env::set_var("OTEL_SPAN_PROCESSOR", "simple");
226 std::env::set_var("OTEL_TRACES_SAMPLER", "traceidratio");
227 std::env::set_var("OTEL_TRACES_SAMPLER_ARG", "0.5");
228 }
229
230 let view = EnvSettingsView::from_env();
231 assert!(view.tracing_enabled());
232 assert_eq!(view.service_name(), "my-svc");
233 assert_eq!(view.otlp_endpoint(), "http://collector:4317");
234 assert_eq!(view.otlp_headers(), "x-key=val");
235 assert_eq!(view.otlp_protocol(), "http/protobuf");
236 assert_eq!(view.span_processor(), "simple");
237 assert_eq!(view.traces_sampler(), "traceidratio");
238 assert_eq!(view.traces_sampler_arg(), "0.5");
239
240 clear_otel_env();
241 }
242}