Skip to content
This repository was archived by the owner on Mar 24, 2024. It is now read-only.

Commit e6b44c9

Browse files
committed
add log format control
1 parent c1b5f3b commit e6b44c9

5 files changed

Lines changed: 118 additions & 32 deletions

File tree

Cargo.lock

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "highlights"
3-
version = "2.1.1"
3+
version = "2.1.2"
44
authors = ["ThatsNoMoon <git@thatsnomoon.dev>"]
55
repository = "https://github.com/ThatsNoMoon/highlights"
66
license = "OSL-3.0"
@@ -43,7 +43,7 @@ serde_json = { version = "1.0", optional = true }
4343
tinyvec = { version = "1.5", features = ["alloc"] }
4444
tracing = "0.1"
4545
tracing-opentelemetry = { version = "0.17", optional = true }
46-
tracing-subscriber = "0.3"
46+
tracing-subscriber = { version = "0.3", features = ["json"] }
4747

4848
[dependencies.config]
4949
version = "0.13"

example_config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ sample_ratio = 1.0
2626
level = "WARN"
2727
# Whether or not to use ANSI color codes (may not work on Windows)
2828
color = true
29+
# Format of standard output logging (can be "compact", "pretty", or "json")
30+
format = "compact"
2931
[logging.filters]
3032
# The `highlights` crate will log at INFO instead
3133
highlights = "INFO"

src/logging/mod.rs

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
use anyhow::Result;
77
#[cfg(any(feature = "monitoring", feature = "reporting"))]
88
use tracing::warn;
9-
use tracing::Metadata;
9+
use tracing::{Metadata, Subscriber};
1010
use tracing_subscriber::{
1111
filter::FilterFn,
12-
layer::{Layer, SubscriberExt},
12+
layer::{Layer, Layered, SubscriberExt},
13+
registry::LookupSpan,
1314
util::SubscriberInitExt,
1415
};
1516

16-
use crate::settings::{settings, Settings};
17+
use crate::settings::{settings, LogFormat, Settings};
1718

1819
#[cfg(feature = "monitoring")]
1920
mod monitoring;
@@ -49,38 +50,61 @@ fn use_filters(settings: &Settings, metadata: &Metadata) -> bool {
4950
/// This initializes [`reporting`] and [`monitoring`], if
5051
/// enabled, as well as basic stdout logging.
5152
pub(crate) fn init() -> Result<()> {
52-
let subscriber = tracing_subscriber::registry().with(
53-
tracing_subscriber::fmt::layer()
54-
.with_ansi(settings().logging.color)
55-
.with_filter({
56-
let settings = settings();
57-
FilterFn::new(|metadata| use_filters(settings, metadata))
58-
}),
59-
);
53+
let fmt =
54+
tracing_subscriber::fmt::layer().with_ansi(settings().logging.color);
6055

61-
#[cfg(feature = "monitoring")]
62-
let (is_monitoring, subscriber) = {
63-
let layer = monitoring::init()?;
64-
(layer.is_some(), subscriber.with(layer))
56+
let filter = {
57+
let settings = settings();
58+
FilterFn::new(|metadata| use_filters(settings, metadata))
6559
};
6660

67-
#[cfg(feature = "reporting")]
68-
let (is_reporting, subscriber) = {
69-
let layer = reporting::init();
70-
(layer.is_some(), subscriber.with(layer))
71-
};
61+
fn init_rest<L, S>(subscriber: Layered<L, S>) -> Result<()>
62+
where
63+
L: Layer<S> + Send + Sync + 'static,
64+
S: Subscriber + for<'span> LookupSpan<'span> + Send + Sync + 'static,
65+
{
66+
#[cfg(feature = "monitoring")]
67+
let (is_monitoring, subscriber) = {
68+
let layer = monitoring::init()?;
69+
(layer.is_some(), subscriber.with(layer))
70+
};
7271

73-
subscriber.try_init()?;
72+
#[cfg(feature = "reporting")]
73+
let (is_reporting, subscriber) = {
74+
let layer = reporting::init();
75+
(layer.is_some(), subscriber.with(layer))
76+
};
7477

75-
#[cfg(feature = "monitoring")]
76-
if !is_monitoring {
77-
warn!("Jaeger agent address not provided; not reporting traces");
78-
}
78+
subscriber.try_init()?;
79+
80+
#[cfg(feature = "monitoring")]
81+
if !is_monitoring {
82+
warn!("Jaeger agent address not provided; not reporting traces");
83+
}
7984

80-
#[cfg(feature = "reporting")]
81-
if !is_reporting {
82-
warn!("Webhook URL is not present, not reporting panics");
85+
#[cfg(feature = "reporting")]
86+
if !is_reporting {
87+
warn!("Webhook URL is not present, not reporting panics");
88+
}
89+
90+
Ok(())
8391
}
8492

85-
Ok(())
93+
match &settings().logging.format {
94+
LogFormat::Compact => {
95+
let subscriber = tracing_subscriber::registry()
96+
.with(fmt.compact().with_filter(filter));
97+
init_rest(subscriber)
98+
}
99+
LogFormat::Pretty => {
100+
let subscriber = tracing_subscriber::registry()
101+
.with(fmt.pretty().with_filter(filter));
102+
init_rest(subscriber)
103+
}
104+
LogFormat::Json => {
105+
let subscriber = tracing_subscriber::registry()
106+
.with(fmt.json().with_filter(filter));
107+
init_rest(subscriber)
108+
}
109+
}
86110
}

src/settings.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,51 @@ mod level {
196196
}
197197

198198
use level::{deserialize_level_filter, deserialize_level_filters};
199+
200+
mod log_format {
201+
use std::fmt;
202+
203+
use serde::{de, Deserialize, Deserializer};
204+
205+
#[derive(Debug)]
206+
pub(crate) enum LogFormat {
207+
Compact,
208+
Pretty,
209+
Json,
210+
}
211+
212+
/// Visitor to deserialize a `LevelFilter` from a string.
213+
struct LogFormatVisitor;
214+
impl<'de> de::Visitor<'de> for LogFormatVisitor {
215+
type Value = LogFormat;
216+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
217+
write!(formatter, "a log format (compact, pretty, json)")
218+
}
219+
220+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
221+
where
222+
E: de::Error,
223+
{
224+
match v {
225+
"compact" | "COMPACT" => Ok(LogFormat::Compact),
226+
"pretty" | "PRETTY" => Ok(LogFormat::Pretty),
227+
"json" | "JSON" => Ok(LogFormat::Json),
228+
_ => Err(E::invalid_value(de::Unexpected::Str(v), &self)),
229+
}
230+
}
231+
}
232+
233+
impl<'de> Deserialize<'de> for LogFormat {
234+
fn deserialize<D>(d: D) -> Result<Self, D::Error>
235+
where
236+
D: Deserializer<'de>,
237+
{
238+
d.deserialize_str(LogFormatVisitor)
239+
}
240+
}
241+
}
242+
243+
pub(crate) use log_format::LogFormat;
199244
#[cfg(feature = "monitoring")]
200245
pub(crate) use user_address::UserAddress;
201246

@@ -259,6 +304,8 @@ pub(crate) struct LoggingSettings {
259304

260305
/// Whether or not to use ANSI color codes.
261306
pub(crate) color: bool,
307+
/// Standard output logging format.
308+
pub(crate) format: LogFormat,
262309
}
263310

264311
/// Settings for the database.

0 commit comments

Comments
 (0)