sqlite_graphrag/telemetry.rs
1//! Centralized tracing subscriber initialization.
2//!
3//! Configures the global subscriber with JSON or pretty format,
4//! installs the panic hook and the log-to-tracing bridge.
5
6use tracing_subscriber::EnvFilter;
7
8/// Initializes the global tracing subscriber, panic hook, and log bridge.
9///
10/// Must be called exactly once, before any tracing events are emitted.
11/// After this call, panics on any thread produce `tracing::error!` events,
12/// and `log` crate events from dependencies (refinery, ureq, ort) are
13/// forwarded to the tracing subscriber.
14pub fn init_tracing(log_level: &str, log_format: &str) {
15 // TR02: the log→tracing bridge is activated automatically by
16 // tracing-subscriber's built-in `tracing-log` feature (default).
17 // Calling LogTracer::init() separately would conflict with the
18 // global logger that tracing-subscriber installs via .init().
19 let use_ansi = crate::terminal::should_use_ansi();
20
21 if log_format == "json" {
22 tracing_subscriber::fmt()
23 .json()
24 .with_ansi(false)
25 .with_thread_ids(true)
26 .with_thread_names(true)
27 .with_env_filter(EnvFilter::new(log_level))
28 .with_writer(std::io::stderr)
29 .init();
30 } else {
31 tracing_subscriber::fmt()
32 .with_ansi(use_ansi)
33 .with_env_filter(EnvFilter::new(log_level))
34 .with_writer(std::io::stderr)
35 .init();
36 }
37
38 // TR05: confirm effective filter after init
39 tracing::debug!(
40 target: "telemetry",
41 filter = %log_level,
42 format = %log_format,
43 ansi = use_ansi,
44 "tracing subscriber initialized"
45 );
46
47 // TR01: panic hook emitting structured tracing::error!
48 let prev_hook = std::panic::take_hook();
49 std::panic::set_hook(Box::new(move |info| {
50 let payload = info
51 .payload()
52 .downcast_ref::<&str>()
53 .copied()
54 .or_else(|| info.payload().downcast_ref::<String>().map(|s| s.as_str()))
55 .unwrap_or("<non-string panic>");
56 let location = info
57 .location()
58 .map(|l| format!("{}:{}:{}", l.file(), l.line(), l.column()));
59 tracing::error!(
60 target: "panic",
61 message = %payload,
62 location = location.as_deref().unwrap_or("unknown"),
63 "thread panicked"
64 );
65 prev_hook(info);
66 }));
67}