@@ -63,12 +63,24 @@ impl TracingBuilder {
6363 /// it uses [std::io::stdout] which is synchronous
6464 /// and might block the logging thread.
6565 pub fn with_stdout ( mut self , filter : impl AsRef < str > , json : bool ) -> Self {
66- let parsed = EnvFilter :: builder ( )
66+ let mut parsed = EnvFilter :: builder ( )
6767 . parse_lossy ( filter)
6868 . add_directive ( "hyper=off" . parse ( ) . unwrap ( ) )
6969 . add_directive ( "tonic=off" . parse ( ) . unwrap ( ) )
70+ . add_directive ( "tokio=off" . parse ( ) . unwrap ( ) )
71+ . add_directive ( "process_wrap=off" . parse ( ) . unwrap ( ) )
7072 . add_directive ( "h2=off" . parse ( ) . unwrap ( ) )
7173 . add_directive ( "reqwest=off" . parse ( ) . unwrap ( ) ) ;
74+ let env_log = std:: env:: var ( "RUST_LOG" ) . unwrap_or_default ( ) ;
75+ if !env_log. contains ( "dora_daemon" ) {
76+ parsed = parsed. add_directive ( "dora_daemon=info" . parse ( ) . unwrap ( ) ) ;
77+ }
78+ if !env_log. contains ( "dora_core" ) {
79+ parsed = parsed. add_directive ( "dora_core=warn" . parse ( ) . unwrap ( ) ) ;
80+ }
81+ if !env_log. contains ( "zenoh" ) {
82+ parsed = parsed. add_directive ( "zenoh=warn" . parse ( ) . unwrap ( ) ) ;
83+ }
7284 let env_filter = EnvFilter :: from_default_env ( ) . or ( parsed) ;
7385 let layer = tracing_subscriber:: fmt:: layer ( )
7486 . compact ( )
@@ -135,11 +147,17 @@ impl TracingBuilder {
135147
136148 self . guard = Some ( guard) ;
137149 self . layers . push ( MetricsLayer :: new ( meter_provider) . boxed ( ) ) ;
138- let filter_otel = EnvFilter :: new ( "trace" )
150+ let mut filter_otel = EnvFilter :: new ( "trace" )
139151 . add_directive ( "hyper=off" . parse ( ) . unwrap ( ) )
140152 . add_directive ( "tonic=off" . parse ( ) . unwrap ( ) )
153+ . add_directive ( "tokio=off" . parse ( ) . unwrap ( ) )
154+ . add_directive ( "process_wrap=off" . parse ( ) . unwrap ( ) )
141155 . add_directive ( "h2=off" . parse ( ) . unwrap ( ) )
142156 . add_directive ( "reqwest=off" . parse ( ) . unwrap ( ) ) ;
157+ let env_log = std:: env:: var ( "RUST_LOG" ) . unwrap_or_default ( ) ;
158+ if !env_log. contains ( "dora_daemon" ) {
159+ filter_otel = filter_otel. add_directive ( "dora_daemon=debug" . parse ( ) . unwrap ( ) ) ;
160+ }
143161 self . layers . push (
144162 OpenTelemetryLayer :: new ( tracer)
145163 . with_filter ( filter_otel)
@@ -192,3 +210,63 @@ impl Drop for OtelGuard {
192210 self . tracer_provider . shutdown ( ) . ok ( ) ;
193211 }
194212}
213+
214+ /// Initialize tracing with OTLP (if configured) or stdout/file logging.
215+ ///
216+ /// This function should be called after creating a tokio runtime and calling `runtime.enter()`.
217+ ///
218+ /// # Parameters
219+ /// - `name`: Service name for tracing
220+ /// - `stdout_filter`: Optional RUST_LOG-style filter for stdout logging (e.g., "info", "debug")
221+ /// - `file_name`: Optional filename for file logging (will be placed in `out/` directory)
222+ /// - `file_filter`: Level filter for file logging (only used if `file_name` is Some)
223+ ///
224+ /// # Returns
225+ /// Returns `Option<OtelGuard>` which must be kept alive for the duration of the program.
226+ /// When dropped, the guard will flush and shutdown telemetry providers.
227+ ///
228+ /// # Example
229+ /// ```no_run
230+ /// use dora_tracing::init_tracing_subscriber;
231+ /// use tracing::level_filters::LevelFilter;
232+ ///
233+ /// // Note: This function requires a tokio runtime context to be active
234+ /// // when using OTLP tracing. Use runtime.enter() before calling.
235+ /// let _guard = init_tracing_subscriber(
236+ /// "my-service",
237+ /// Some("info"),
238+ /// Some("my-service"),
239+ /// LevelFilter::INFO,
240+ /// ).unwrap();
241+ /// ```
242+ pub fn init_tracing_subscriber (
243+ name : & str ,
244+ stdout_filter : Option < & str > ,
245+ file_name : Option < & str > ,
246+ file_filter : LevelFilter ,
247+ ) -> eyre:: Result < Option < OtelGuard > > {
248+ let mut builder = TracingBuilder :: new ( name) ;
249+ let guard: Option < OtelGuard > ;
250+
251+ if std:: env:: var ( "DORA_OTLP_ENDPOINT" ) . is_ok ( ) || std:: env:: var ( "DORA_JAEGER_TRACING" ) . is_ok ( ) {
252+ builder = builder
253+ . with_otlp_tracing ( )
254+ . wrap_err ( "failed to set up OTLP tracing" ) ?;
255+ guard = builder. guard . take ( ) ;
256+ } else {
257+ if let Some ( filter) = stdout_filter {
258+ builder = builder. with_stdout ( filter, false ) ;
259+ }
260+ guard = None ;
261+ }
262+
263+ if let Some ( filename) = file_name {
264+ builder = builder. with_file ( filename, file_filter) ?;
265+ }
266+
267+ builder
268+ . build ( )
269+ . wrap_err ( "failed to set up tracing subscriber" ) ?;
270+
271+ Ok ( guard)
272+ }
0 commit comments