1use tracing_subscriber::layer::SubscriberExt;
9use tracing_subscriber::util::SubscriberInitExt;
10use tracing_subscriber::{fmt, EnvFilter};
11
12pub enum LogMode {
14 Cli,
16 Proxy,
18}
19
20#[cfg(feature = "sentry")]
24pub type SentryGuard = sentry::ClientInitGuard;
25#[cfg(not(feature = "sentry"))]
26pub type SentryGuard = ();
27
28pub fn init(mode: LogMode, verbose: bool) -> Option<SentryGuard> {
34 let filter = match std::env::var("RUST_LOG") {
35 Ok(val) if !val.is_empty() => EnvFilter::from_default_env(),
36 _ if verbose => EnvFilter::new("debug"),
37 _ => EnvFilter::new("info"),
38 };
39
40 let sentry_guard = init_sentry();
42
43 let registry = tracing_subscriber::registry().with(filter);
47
48 #[cfg(feature = "sentry")]
49 let registry = registry.with(sentry_guard.as_ref().map(|_| sentry_tracing::layer()));
50
51 match mode {
52 LogMode::Proxy => {
53 registry
54 .with(
55 fmt::layer()
56 .json()
57 .flatten_event(true)
58 .with_writer(std::io::stderr)
59 .with_target(true)
60 .with_current_span(false),
61 )
62 .init();
63 }
64 LogMode::Cli => {
65 registry
66 .with(
67 fmt::layer()
68 .compact()
69 .with_writer(std::io::stderr)
70 .with_target(false),
71 )
72 .init();
73 }
74 }
75
76 #[cfg(not(feature = "sentry"))]
78 if std::env::var("SENTRY_DSN").is_ok() || std::env::var("GREP_SENTRY_DSN").is_ok() {
79 tracing::warn!(
80 "SENTRY_DSN is set but this binary was compiled without the sentry feature — ignoring. \
81 Build with: cargo build --features sentry"
82 );
83 }
84
85 sentry_guard
86}
87
88fn init_sentry() -> Option<SentryGuard> {
91 #[cfg(feature = "sentry")]
92 {
93 let dsn = std::env::var("GREP_SENTRY_DSN")
94 .or_else(|_| std::env::var("SENTRY_DSN"))
95 .ok()?;
96
97 let environment =
98 std::env::var("ENVIRONMENT_TIER").unwrap_or_else(|_| "development".into());
99
100 match environment.as_str() {
102 "production" | "staging" | "demo" => {}
103 _ => {
104 tracing::debug!(environment = %environment, "sentry disabled for this environment");
105 return None;
106 }
107 }
108
109 let service = std::env::var("SERVICE_NAME").unwrap_or_else(|_| "ati-proxy".into());
110
111 let sample_rate = match environment.as_str() {
112 "production" => 0.25,
113 "staging" => 0.5,
114 _ => 1.0,
115 };
116
117 let guard = sentry::init((
118 dsn,
119 sentry::ClientOptions {
120 release: Some(env!("CARGO_PKG_VERSION").into()),
121 environment: Some(environment.into()),
122 server_name: Some(service.into()),
123 traces_sample_rate: sample_rate,
124 attach_stacktrace: true,
125 send_default_pii: false,
126 ..Default::default()
127 },
128 ));
129
130 if guard.is_enabled() {
131 Some(guard)
132 } else {
133 None
134 }
135 }
136
137 #[cfg(not(feature = "sentry"))]
138 {
139 None
140 }
141}