Skip to content

Commit 32b4750

Browse files
authored
chore(logging): Add support to "off" for logging level (#3055)
Support all the logging levels mentioned in the docs https://docs.sentry.io/product/relay/options/#logging
1 parent 8e73e8c commit 32b4750

File tree

3 files changed

+74
-37
lines changed

3 files changed

+74
-37
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

relay-log/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ build = "build.rs"
1414
chrono = { workspace = true, features = ["clock"], optional = true }
1515
console = { version = "0.15.5", optional = true }
1616
once_cell = { version = "1.13.1", optional = true }
17+
relay-common = { path = "../relay-common" }
1718
relay-crash = { path = "../relay-crash", optional = true }
1819
sentry = { version = "0.31.7", features = [
1920
"debug-images",

relay-log/src/setup.rs

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use std::borrow::Cow;
22
use std::env;
3+
use std::fmt::{self, Display};
34
use std::path::PathBuf;
5+
use std::str::FromStr;
46

7+
use relay_common::impl_str_serde;
58
use sentry::types::Dsn;
69
use serde::{Deserialize, Serialize};
7-
use tracing::{level_filters::LevelFilter, Level};
10+
use tracing::level_filters::LevelFilter;
811
use tracing_subscriber::{prelude::*, EnvFilter, Layer};
912

1013
#[cfg(feature = "dashboard")]
@@ -47,53 +50,78 @@ pub enum LogFormat {
4750
Json,
4851
}
4952

50-
mod level_serde {
51-
use std::fmt;
52-
53-
use serde::de::{Error, Unexpected, Visitor};
54-
use serde::{Deserializer, Serializer};
55-
use tracing::Level;
56-
57-
pub fn serialize<S>(filter: &Level, serializer: S) -> Result<S::Ok, S::Error>
58-
where
59-
S: Serializer,
60-
{
61-
serializer.collect_str(filter)
53+
/// The logging level parse error.
54+
#[derive(Clone, Debug)]
55+
pub struct LevelParseError(String);
56+
57+
impl Display for LevelParseError {
58+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59+
write!(
60+
f,
61+
r#"error parsing "{}" as level: expected one of "error", "warn", "info", "debug", "trace", "off""#,
62+
self.0
63+
)
6264
}
65+
}
6366

64-
pub fn deserialize<'de, D>(deserializer: D) -> Result<Level, D::Error>
65-
where
66-
D: Deserializer<'de>,
67-
{
68-
struct V;
69-
70-
impl<'de> Visitor<'de> for V {
71-
type Value = Level;
72-
73-
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
74-
formatter.write_str("a log level")
75-
}
67+
#[derive(Clone, Copy, Debug)]
68+
pub enum Level {
69+
Error,
70+
Warn,
71+
Info,
72+
Debug,
73+
Trace,
74+
Off,
75+
}
7676

77-
fn visit_str<E>(self, value: &str) -> Result<Level, E>
78-
where
79-
E: Error,
80-
{
81-
value
82-
.parse()
83-
.map_err(|_| Error::invalid_value(Unexpected::Str(value), &self))
84-
}
77+
impl_str_serde!(Level, "The logging level.");
78+
79+
impl Level {
80+
/// Returns the tracing [`LevelFilter`].
81+
pub const fn level_filter(&self) -> LevelFilter {
82+
match self {
83+
Level::Error => LevelFilter::ERROR,
84+
Level::Warn => LevelFilter::WARN,
85+
Level::Info => LevelFilter::INFO,
86+
Level::Debug => LevelFilter::DEBUG,
87+
Level::Trace => LevelFilter::TRACE,
88+
Level::Off => LevelFilter::OFF,
8589
}
90+
}
91+
}
92+
93+
impl Display for Level {
94+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95+
write!(f, "{}", format!("{:?}", self).to_lowercase())
96+
}
97+
}
8698

87-
deserializer.deserialize_str(V)
99+
impl FromStr for Level {
100+
type Err = LevelParseError;
101+
102+
fn from_str(s: &str) -> Result<Self, Self::Err> {
103+
let result = match s {
104+
"" => Level::Error,
105+
s if s.eq_ignore_ascii_case("error") => Level::Error,
106+
s if s.eq_ignore_ascii_case("warn") => Level::Warn,
107+
s if s.eq_ignore_ascii_case("info") => Level::Info,
108+
s if s.eq_ignore_ascii_case("debug") => Level::Debug,
109+
s if s.eq_ignore_ascii_case("trace") => Level::Trace,
110+
s if s.eq_ignore_ascii_case("off") => Level::Off,
111+
s => return Err(LevelParseError(s.into())),
112+
};
113+
114+
Ok(result)
88115
}
89116
}
90117

118+
impl std::error::Error for LevelParseError {}
119+
91120
/// Controls the logging system.
92121
#[derive(Clone, Debug, Deserialize, Serialize)]
93122
#[serde(default)]
94123
pub struct LogConfig {
95124
/// The log level for Relay.
96-
#[serde(with = "level_serde")]
97125
pub level: Level,
98126

99127
/// Controls the log output format.
@@ -112,10 +140,17 @@ pub struct LogConfig {
112140
pub traces_sample_rate: f32,
113141
}
114142

143+
impl LogConfig {
144+
/// Returns the tracing [`LevelFilter`].
145+
pub const fn level_filter(&self) -> LevelFilter {
146+
self.level.level_filter()
147+
}
148+
}
149+
115150
impl Default for LogConfig {
116151
fn default() -> Self {
117152
Self {
118-
level: Level::INFO,
153+
level: Level::Info,
119154
format: LogFormat::Auto,
120155
enable_backtraces: false,
121156
#[cfg(debug_assertions)]
@@ -240,7 +275,7 @@ pub fn init(config: &LogConfig, sentry: &SentryConfig) {
240275
};
241276

242277
let logs_subscriber = tracing_subscriber::registry()
243-
.with(format.with_filter(LevelFilter::from(config.level)))
278+
.with(format.with_filter(config.level_filter()))
244279
.with(sentry::integrations::tracing::layer())
245280
.with(match env::var(EnvFilter::DEFAULT_ENV) {
246281
Ok(value) => EnvFilter::new(value),

0 commit comments

Comments
 (0)