1use std::str::FromStr;
13use std::time::Duration;
14
15use anyhow::anyhow;
16use mz_dyncfg::{Config, ConfigSet, ConfigUpdates, ParameterScope};
17use mz_tracing::params::TracingParameters;
18use mz_tracing::{CloneableEnvFilter, SerializableDirective};
19use tracing_subscriber::filter::Directive;
20
21pub const SIGTERM_CONNECTION_WAIT: Config<Duration> = Config::new(
27 "balancerd_sigterm_connection_wait",
28 Duration::from_secs(60 * 9),
29 "Duration to wait after listeners closed via SIGTERM for outstanding connections to complete.",
30 ParameterScope::Environment,
31);
32
33pub const SIGTERM_LISTEN_WAIT: Config<Duration> = Config::new(
35 "balancerd_sigterm_listen_wait",
36 Duration::from_secs(60),
37 "Duration to wait after SIGTERM to begin shutdown of servers.",
38 ParameterScope::Environment,
39);
40
41pub const INJECT_PROXY_PROTOCOL_HEADER_HTTP: Config<bool> = Config::new(
43 "balancerd_inject_proxy_protocol_header_http",
44 false,
45 "Whether to inject tcp proxy protocol headers to downstream http servers.",
46 ParameterScope::Environment,
47);
48
49pub const LOGGING_FILTER: Config<&str> = Config::new(
51 "balancerd_log_filter",
52 "info",
53 "Sets the filter to apply to stderr logging.",
54 ParameterScope::Environment,
55);
56
57pub const OPENTELEMETRY_FILTER: Config<&str> = Config::new(
59 "balancerd_opentelemetry_filter",
60 "info",
61 "Sets the filter to apply to OpenTelemetry-backed distributed tracing.",
62 ParameterScope::Environment,
63);
64
65pub const LOGGING_FILTER_DEFAULTS: Config<fn() -> String> = Config::new(
69 "balancerd_log_filter_defaults",
70 || mz_ore::tracing::LOGGING_DEFAULTS_STR.join(","),
71 "Sets additional default directives to apply to stderr logging. \
72 These apply to all variations of `log_filter`. Directives other than \
73 `module=off` are likely incorrect. Comma separated list.",
74 ParameterScope::Environment,
75);
76
77pub const OPENTELEMETRY_FILTER_DEFAULTS: Config<fn() -> String> = Config::new(
82 "balancerd_opentelemetry_filter_defaults",
83 || mz_ore::tracing::OPENTELEMETRY_DEFAULTS_STR.join(","),
84 "Sets additional default directives to apply to OpenTelemetry-backed \
85 distributed tracing. \
86 These apply to all variations of `opentelemetry_filter`. Directives other than \
87 `module=off` are likely incorrect. Comma separated list.",
88 ParameterScope::Environment,
89);
90
91pub const SENTRY_FILTERS: Config<fn() -> String> = Config::new(
95 "balancerd_sentry_filters",
96 || mz_ore::tracing::SENTRY_DEFAULTS_STR.join(","),
97 "Sets additional default directives to apply to sentry logging. \
98 These apply on top of a default `info` directive. Directives other than \
99 `module=off` are likely incorrect. Comma separated list.",
100 ParameterScope::Environment,
101);
102
103pub fn all_dyncfgs(configs: ConfigSet) -> ConfigSet {
105 configs
106 .add(&SIGTERM_CONNECTION_WAIT)
107 .add(&SIGTERM_LISTEN_WAIT)
108 .add(&INJECT_PROXY_PROTOCOL_HEADER_HTTP)
109 .add(&LOGGING_FILTER)
110 .add(&OPENTELEMETRY_FILTER)
111 .add(&LOGGING_FILTER_DEFAULTS)
112 .add(&OPENTELEMETRY_FILTER_DEFAULTS)
113 .add(&SENTRY_FILTERS)
114}
115
116pub(crate) fn set_defaults(
125 config_set: &ConfigSet,
126 default_config: Vec<(String, String)>,
127) -> Result<(), anyhow::Error> {
128 let mut config_updates = ConfigUpdates::default();
129 for (k, v) in default_config.iter() {
130 if k.as_str() == INJECT_PROXY_PROTOCOL_HEADER_HTTP.name() {
131 config_updates.add_dynamic(
132 INJECT_PROXY_PROTOCOL_HEADER_HTTP.name(),
133 mz_dyncfg::ConfigVal::Bool(bool::from_str(v)?),
134 )
135 } else {
136 return Err(anyhow!("Invalid default config value {k}"));
137 }
138 }
139 config_updates.apply(config_set);
140 Ok(())
141}
142
143pub fn tracing_config(configs: &ConfigSet) -> Result<TracingParameters, String> {
145 fn to_serializable_directives(
146 config: &Config<fn() -> String>,
147 configs: &ConfigSet,
148 ) -> Result<Vec<SerializableDirective>, String> {
149 let directives = config.get(configs);
150 let directives: Vec<_> = directives
151 .split(',')
152 .map(Directive::from_str)
153 .collect::<Result<_, _>>()
154 .map_err(|e| e.to_string())?;
155 Ok(directives.into_iter().map(|d| d.into()).collect())
156 }
157
158 let log_filter = LOGGING_FILTER.get(configs);
159 let log_filter = CloneableEnvFilter::from_str(&log_filter).map_err(|e| e.to_string())?;
160
161 let opentelemetry_filter = OPENTELEMETRY_FILTER.get(configs);
162 let opentelemetry_filter =
163 CloneableEnvFilter::from_str(&opentelemetry_filter).map_err(|e| e.to_string())?;
164
165 let log_filter_defaults = to_serializable_directives(&LOGGING_FILTER_DEFAULTS, configs)?;
166
167 let opentelemetry_filter_defaults =
168 to_serializable_directives(&OPENTELEMETRY_FILTER_DEFAULTS, configs)?;
169
170 let sentry_filters = to_serializable_directives(&SENTRY_FILTERS, configs)?;
171
172 Ok(TracingParameters {
173 log_filter: Some(log_filter),
174 opentelemetry_filter: Some(opentelemetry_filter),
175 log_filter_defaults,
176 opentelemetry_filter_defaults,
177 sentry_filters,
178 })
179}
180
181pub fn has_tracing_config_update(updates: &ConfigUpdates) -> bool {
183 [
184 LOGGING_FILTER.name(),
185 OPENTELEMETRY_FILTER.name(),
186 LOGGING_FILTER_DEFAULTS.name(),
187 OPENTELEMETRY_FILTER_DEFAULTS.name(),
188 SENTRY_FILTERS.name(),
189 ]
190 .into_iter()
191 .any(|name| updates.updates.contains_key(name))
192}