Skip to content

Commit

Permalink
o11y: add option for json logger
Browse files Browse the repository at this point in the history
**Summary**

This option enables json logging in production by setting the
`RUST_LOG_FORMAT=json` environment variable.
  • Loading branch information
fracek committed Jul 23, 2023
1 parent 66fd23a commit 850f251
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 31 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.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ tower = "0.4.13"
tracing = { version = "0.1.36", features = ["max_level_trace", "release_max_level_debug"] }
tracing-futures = { version = "0.2.5", features = ["tokio", "futures-03"] }
tracing-opentelemetry = "0.18.0"
tracing-subscriber = { version = "0.3.15", features = ["std", "env-filter"] }
tracing-subscriber = { version = "0.3.15", features = ["std", "env-filter", "json"] }
tracing-tree = "0.2.2"
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
Expand Down
74 changes: 44 additions & 30 deletions observability/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ use opentelemetry::{
trace::TraceError,
};
use opentelemetry_otlp::WithExportConfig;
use tracing::dispatcher::SetGlobalDefaultError;
use tracing::{dispatcher::SetGlobalDefaultError, Subscriber};

pub use opentelemetry::metrics::{ObservableCounter, ObservableGauge};
pub use opentelemetry::{Context, Key, KeyValue};
use tracing_opentelemetry::MetricsLayer;
use tracing_subscriber::{filter, prelude::*, EnvFilter};
use tracing_subscriber::{prelude::*, registry::LookupSpan, EnvFilter, Layer};

pub use opentelemetry::metrics::{Counter, Meter};

const OTEL_SDK_DISABLED: &str = "OTEL_SDK_DISABLED";

pub type BoxedLayer<S> = Box<dyn Layer<S> + Send + Sync>;

#[derive(Debug, thiserror::Error)]
pub enum OpenTelemetryInitError {
#[error("error setting global default subscriber")]
Expand All @@ -49,30 +51,26 @@ pub fn init_opentelemetry() -> Result<(), OpenTelemetryInitError> {
std::env::set_var("RUST_LOG", "info");
}

if sdk_disabled {
init_opentelemetry_no_sdk()
} else {
init_opentelemetry_with_sdk()
let mut layers = vec![stdout()];

if !sdk_disabled {
let otel_layer = otel()?;
layers.push(otel_layer);
}
}

fn init_opentelemetry_no_sdk() -> Result<(), OpenTelemetryInitError> {
let log_env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("INFO"));
let logtree_layer = tracing_tree::HierarchicalLayer::new(2).and_then(log_env_filter);
tracing_subscriber::registry().with(layers).init();

tracing_subscriber::Registry::default()
.with(logtree_layer)
.init();
Ok(())
}

fn init_opentelemetry_with_sdk() -> Result<(), OpenTelemetryInitError> {
fn otel<S>() -> Result<BoxedLayer<S>, OpenTelemetryInitError>
where
S: Subscriber + Send + Sync,
for<'a> S: LookupSpan<'a>,
{
// filter traces by crate/level
let otel_env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("INFO"));
let log_env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("INFO"));

// Both tracer and meter are configured with environment variables.
let meter = opentelemetry_otlp::new_pipeline()
Expand All @@ -96,19 +94,35 @@ fn init_opentelemetry_with_sdk() -> Result<(), OpenTelemetryInitError> {
let otel_metrics_layer = MetricsLayer::new(meter);
let otel_layer = otel_trace_layer
.and_then(otel_metrics_layer)
.and_then(otel_env_filter);

// display traces on stdout
let logtree_layer = tracing_tree::HierarchicalLayer::new(2)
.and_then(log_env_filter)
.with_filter(filter::filter_fn(|metadata| {
metadata.fields().field("data.is_metrics").is_none()
}));
.and_then(otel_env_filter)
.boxed();
Ok(otel_layer)
}

tracing_subscriber::Registry::default()
.with(otel_layer)
.with(logtree_layer)
.init();
fn stdout<S>() -> BoxedLayer<S>
where
S: Subscriber,
for<'a> S: LookupSpan<'a>,
{
let log_env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("INFO"));

Ok(())
let json_fmt = std::env::var("RUST_LOG_FORMAT")
.map(|val| val == "json")
.unwrap_or(false);

if json_fmt {
tracing_subscriber::fmt::layer()
.with_ansi(false)
.with_target(true)
.json()
.with_filter(log_env_filter)
.boxed()
} else {
tracing_subscriber::fmt::layer()
.with_ansi(true)
.with_target(true)
.with_filter(log_env_filter)
.boxed()
}
}

0 comments on commit 850f251

Please sign in to comment.