Skip to content

Commit

Permalink
feat: add explicit log format CLI option
Browse files Browse the repository at this point in the history
There are now three log format options.
* Single Line - Uses colors and everything is on a single line
* Multi Line - Uses colors and multiple lines to display more context
* JSON - Does not use colors and formats add structures as JSON on a
  single line.
  • Loading branch information
nathanielc committed Oct 30, 2023
1 parent 953e09b commit 58d276c
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 15 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ tower-http = "0.3"
tower-layer = "0.3"
tracing = "0.1"
tracing-opentelemetry = "0.18"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tracing-subscriber = { version = "0.3", features = [
"ansi",
"env-filter",
"json",
] }
tracing-test = { version = "0.2" }
trust-dns-resolver = "0.22.0"
unsigned-varint = "0.7"
Expand Down
15 changes: 15 additions & 0 deletions beetle/iroh-metrics/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ pub struct Config {
#[cfg(feature = "tokio-console")]
/// Enables tokio console debugging.
pub tokio_console: bool,
/// How to print log lines to STDOUT
pub log_format: LogFormat,
}

/// Format of log events
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum LogFormat {
// Print log lines on multiple lines
#[default]
MultiLine,
// Print log lines on a single line
SingleLine,
// Print logs a newline delimited JSON
Json,
}

impl Config {
Expand Down Expand Up @@ -58,6 +72,7 @@ impl Default for Config {
prom_gateway_endpoint: "http://localhost:9091".to_string(),
#[cfg(feature = "tokio-console")]
tokio_console: false,
log_format: LogFormat::default(),
}
}
}
58 changes: 52 additions & 6 deletions beetle/iroh-metrics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,19 @@ use prometheus_client::registry::Registry;
use std::env::consts::{ARCH, OS};
use std::time::Duration;
use tokio::task::JoinHandle;
use tracing::{debug, warn};
use tracing::{debug, metadata::LevelFilter, warn};
use tracing_opentelemetry::OpenTelemetrySpanExt;
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
use tracing_subscriber::{
fmt::{
self,
format::{Compact, Json, Pretty},
time::SystemTime,
FormatEvent,
},
layer::SubscriberExt,
util::SubscriberInitExt,
EnvFilter, Layer,
};

#[derive(Debug)]
pub struct MetricsHandle {
Expand Down Expand Up @@ -110,14 +120,50 @@ async fn init_metrics(cfg: Config) -> Option<JoinHandle<()>> {
None
}

struct Format {
kind: config::LogFormat,
single: tracing_subscriber::fmt::format::Format<Compact, SystemTime>,
multi: tracing_subscriber::fmt::format::Format<Pretty, SystemTime>,
json: tracing_subscriber::fmt::format::Format<Json, SystemTime>,
}
impl<S, N> FormatEvent<S, N> for Format
where
S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
N: for<'a> fmt::FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &fmt::FmtContext<'_, S, N>,
writer: fmt::format::Writer<'_>,
event: &tracing::Event<'_>,
) -> std::fmt::Result {
match self.kind {
config::LogFormat::SingleLine => self.single.format_event(ctx, writer, event),
config::LogFormat::MultiLine => self.multi.format_event(ctx, writer, event),
config::LogFormat::Json => self.json.format_event(ctx, writer, event),
}
}
}

/// Initialize the tracing subsystem.
fn init_tracer(cfg: Config) -> Result<(), Box<dyn std::error::Error>> {
#[cfg(feature = "tokio-console")]
let console_subscriber = cfg.tokio_console.then(console_subscriber::spawn);

let log_subscriber = fmt::layer()
.pretty()
.with_filter(EnvFilter::from_default_env());
// Default to INFO if no env is specified
let filter_builder = EnvFilter::builder().with_default_directive(LevelFilter::INFO.into());

let log_filter = filter_builder.from_env()?;
let otlp_filter = filter_builder.from_env()?;

let format = Format {
kind: cfg.log_format,
single: fmt::format().with_ansi(true).compact(),
multi: fmt::format().with_ansi(true).pretty(),
json: fmt::format().with_ansi(false).json(),
};

let log_subscriber = fmt::layer().event_format(format).with_filter(log_filter);

let opentelemetry_subscriber = if cfg.tracing {
global::set_text_map_propagator(TraceContextPropagator::new());
Expand All @@ -143,7 +189,7 @@ fn init_tracer(cfg: Config) -> Result<(), Box<dyn std::error::Error>> {
Some(
tracing_opentelemetry::layer()
.with_tracer(tracer)
.with_filter(EnvFilter::from_default_env()),
.with_filter(otlp_filter),
)
} else {
None
Expand Down
29 changes: 21 additions & 8 deletions one/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@ struct DaemonOpts {
/// When true Recon will be used to synchronized events with peers.
#[arg(long, default_value_t = false, env = "CERAMIC_ONE_RECON")]
recon: bool,

/// Specify the format of log events
#[arg(long, default_value = "multi-line", env = "CERAMIC_ONE_LOG_FORMAT")]
log_format: LogFormat,
}

#[derive(ValueEnum, Debug, Clone, Default)]
enum LogFormat {
/// Format log events on multiple lines using ANSI colors.
#[default]
MultiLine,
/// Format log events on a single line using ANSI colors.
SingleLine,
/// Format log events newline delimited JSON objects.
/// No ANSI colors are used.
Json,
}

#[derive(ValueEnum, Debug, Clone)]
Expand Down Expand Up @@ -146,14 +162,6 @@ struct EyeOpts {

#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<()> {
let (non_blocking, _guard) = tracing_appender::non_blocking(std::io::stdout());

let subscriber = tracing_subscriber::fmt().with_writer(non_blocking);

tracing::subscriber::with_default(subscriber.finish(), || {
tracing::event!(tracing::Level::INFO, "Ceramic One Server Running");
});

let args = Cli::parse();
match args.command {
Command::Daemon(opts) => {
Expand Down Expand Up @@ -194,6 +202,11 @@ impl Daemon {
// Do not push metrics to any endpoint.
metrics_config.export = false;
metrics_config.tracing = opts.tracing;
metrics_config.log_format = match opts.log_format {
LogFormat::SingleLine => iroh_metrics::config::LogFormat::SingleLine,
LogFormat::MultiLine => iroh_metrics::config::LogFormat::MultiLine,
LogFormat::Json => iroh_metrics::config::LogFormat::Json,
};
let service_name = metrics_config.service_name.clone();
let instance_id = metrics_config.instance_id.clone();

Expand Down

0 comments on commit 58d276c

Please sign in to comment.