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();
41
42 let registry = tracing_subscriber::registry().with(filter);
46
47 #[cfg(feature = "sentry")]
48 let registry = registry.with(sentry_guard.as_ref().map(|_| sentry_tracing::layer()));
49
50 match mode {
51 LogMode::Proxy => {
52 registry
53 .with(
54 fmt::layer()
55 .json()
56 .flatten_event(true)
57 .with_writer(std::io::stderr)
58 .with_target(true)
59 .with_current_span(false),
60 )
61 .init();
62 }
63 LogMode::Cli => {
64 registry
65 .with(
66 fmt::layer()
67 .compact()
68 .with_writer(std::io::stderr)
69 .with_target(false),
70 )
71 .init();
72 }
73 }
74
75 sentry_guard
76}
77
78fn init_sentry() -> Option<SentryGuard> {
81 #[cfg(feature = "sentry")]
82 {
83 let dsn = std::env::var("GREP_SENTRY_DSN")
84 .or_else(|_| std::env::var("SENTRY_DSN"))
85 .ok()?;
86
87 let environment =
88 std::env::var("ENVIRONMENT_TIER").unwrap_or_else(|_| "development".into());
89
90 let service = std::env::var("SERVICE_NAME").unwrap_or_else(|_| "ati-proxy".into());
91
92 let sample_rate = match environment.as_str() {
93 "production" => 0.25,
94 "staging" => 0.5,
95 _ => 1.0,
96 };
97
98 let guard = sentry::init((
99 dsn,
100 sentry::ClientOptions {
101 release: Some(env!("CARGO_PKG_VERSION").into()),
102 environment: Some(environment.into()),
103 server_name: Some(service.into()),
104 traces_sample_rate: sample_rate,
105 attach_stacktrace: true,
106 send_default_pii: false,
107 ..Default::default()
108 },
109 ));
110
111 if guard.is_enabled() {
112 Some(guard)
113 } else {
114 None
115 }
116 }
117
118 #[cfg(not(feature = "sentry"))]
119 {
120 None
121 }
122}