mz_tracing/
params.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use std::str::FromStr;
11
12use mz_ore::tracing::TracingHandle;
13use mz_proto::{ProtoType, RustType, TryFromProtoError};
14use proptest::prelude::{Arbitrary, BoxedStrategy, Strategy, any};
15use serde::{Deserialize, Serialize};
16use tracing::warn;
17
18use crate::{CloneableEnvFilter, SerializableDirective};
19
20include!(concat!(env!("OUT_DIR"), "/mz_tracing.params.rs"));
21
22/// Parameters related to `tracing`.
23#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
24pub struct TracingParameters {
25    /// Filter to apply to stderr logging.
26    pub log_filter: Option<CloneableEnvFilter>,
27    /// Filter to apply to OpenTelemetry/distributed tracing.
28    pub opentelemetry_filter: Option<CloneableEnvFilter>,
29    /// Additional directives for `log_filter`.
30    pub log_filter_defaults: Vec<SerializableDirective>,
31    /// Additional directives for `opentelemetry_filter`.
32    pub opentelemetry_filter_defaults: Vec<SerializableDirective>,
33    /// Additional directives on top of the `info` filter for `sentry`.
34    pub sentry_filters: Vec<SerializableDirective>,
35}
36
37impl Arbitrary for TracingParameters {
38    type Strategy = BoxedStrategy<Self>;
39    type Parameters = ();
40
41    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
42        (
43            any::<Option<CloneableEnvFilter>>(),
44            any::<Option<CloneableEnvFilter>>(),
45            any::<Vec<SerializableDirective>>(),
46            any::<Vec<SerializableDirective>>(),
47            any::<Vec<SerializableDirective>>(),
48        )
49            .prop_map(
50                |(
51                    log_filter,
52                    opentelemetry_filter,
53                    log_filter_defaults,
54                    opentelemetry_filter_defaults,
55                    sentry_filters,
56                )| Self {
57                    log_filter,
58                    opentelemetry_filter,
59                    log_filter_defaults,
60                    opentelemetry_filter_defaults,
61                    sentry_filters,
62                },
63            )
64            .boxed()
65    }
66}
67
68impl TracingParameters {
69    pub fn apply(&self, tracing_handle: &TracingHandle) {
70        if let Some(filter) = &self.log_filter {
71            if let Err(e) = tracing_handle.reload_stderr_log_filter(
72                filter.clone().into(),
73                self.log_filter_defaults
74                    .iter()
75                    .map(|d| d.clone().into())
76                    .collect(),
77            ) {
78                warn!(
79                    "unable to apply stderr log filter: {:?}. filter={}, defaults={:?}",
80                    e, filter, self.log_filter_defaults
81                );
82            }
83        }
84        if let Some(filter) = &self.opentelemetry_filter {
85            if let Err(e) = tracing_handle.reload_opentelemetry_filter(
86                filter.clone().into(),
87                self.opentelemetry_filter_defaults
88                    .iter()
89                    .map(|d| d.clone().into())
90                    .collect(),
91            ) {
92                warn!(
93                    "unable to apply OpenTelemetry filter: {:?}. filter={}, defaults={:?}",
94                    e, filter, self.opentelemetry_filter_defaults
95                );
96            }
97        }
98        if let Err(e) = tracing_handle.reload_sentry_directives(
99            self.sentry_filters
100                .iter()
101                .map(|d| d.clone().into())
102                .collect(),
103        ) {
104            warn!(
105                "unable to apply sentry directives: {:?}. directives={:?}",
106                e, self.sentry_filters
107            );
108        }
109    }
110
111    pub fn update(&mut self, other: Self) {
112        let Self {
113            log_filter,
114            opentelemetry_filter,
115            log_filter_defaults,
116            opentelemetry_filter_defaults,
117            sentry_filters,
118        } = self;
119
120        let Self {
121            log_filter: other_log_filter,
122            opentelemetry_filter: other_opentelemetry_filter,
123            log_filter_defaults: other_log_filter_defaults,
124            opentelemetry_filter_defaults: other_opentelemetry_filter_defaults,
125            sentry_filters: other_sentry_filters,
126        } = other;
127
128        if let Some(v) = other_log_filter {
129            *log_filter = Some(v);
130        }
131        if let Some(v) = other_opentelemetry_filter {
132            *opentelemetry_filter = Some(v);
133        }
134
135        *log_filter_defaults = other_log_filter_defaults;
136        *opentelemetry_filter_defaults = other_opentelemetry_filter_defaults;
137        *sentry_filters = other_sentry_filters;
138    }
139}
140
141impl RustType<String> for CloneableEnvFilter {
142    fn into_proto(&self) -> String {
143        format!("{}", self)
144    }
145
146    fn from_proto(proto: String) -> Result<Self, TryFromProtoError> {
147        CloneableEnvFilter::from_str(&proto)
148            // this isn't an accurate enum for this error, but it seems preferable
149            // to adding in a dependency on mz_tracing / tracing to mz_proto just
150            // to improve the error message here
151            .map_err(|x| TryFromProtoError::UnknownEnumVariant(x.to_string()))
152    }
153}
154
155impl RustType<String> for SerializableDirective {
156    fn into_proto(&self) -> String {
157        format!("{}", self)
158    }
159
160    fn from_proto(proto: String) -> Result<Self, TryFromProtoError> {
161        SerializableDirective::from_str(&proto)
162            // this isn't an accurate enum for this error, but it seems preferable
163            // to adding in a dependency on mz_tracing / tracing to mz_proto just
164            // to improve the error message here
165            .map_err(|x| TryFromProtoError::UnknownEnumVariant(x.to_string()))
166    }
167}
168
169impl RustType<ProtoTracingParameters> for TracingParameters {
170    fn into_proto(&self) -> ProtoTracingParameters {
171        ProtoTracingParameters {
172            log_filter: self.log_filter.into_proto(),
173            opentelemetry_filter: self.opentelemetry_filter.into_proto(),
174            log_filter_defaults: self.log_filter_defaults.into_proto(),
175            opentelemetry_filter_defaults: self.opentelemetry_filter_defaults.into_proto(),
176            sentry_filters: self.sentry_filters.into_proto(),
177        }
178    }
179
180    fn from_proto(proto: ProtoTracingParameters) -> Result<Self, TryFromProtoError> {
181        Ok(Self {
182            log_filter: proto.log_filter.into_rust()?,
183            opentelemetry_filter: proto.opentelemetry_filter.into_rust()?,
184            log_filter_defaults: proto.log_filter_defaults.into_rust()?,
185            opentelemetry_filter_defaults: proto.opentelemetry_filter_defaults.into_rust()?,
186            sentry_filters: proto.sentry_filters.into_rust()?,
187        })
188    }
189}