Skip to content

Commit

Permalink
fixup! refactor(log): reimplement log using tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
rami3l committed Jun 1, 2024
1 parent 2b5d4dd commit 0b3e73b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 60 deletions.
59 changes: 5 additions & 54 deletions src/bin/rustup-init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,63 +55,14 @@ fn main() {
}

async fn maybe_trace_rustup() -> Result<utils::ExitCode> {
use tracing_subscriber::{
filter::LevelFilter, layer::SubscriberExt, EnvFilter, Layer, Registry,
};

let curr_process = process();
let has_ansi = curr_process.stderr().is_a_tty();
let maybe_rust_log_directives = curr_process.var_os("RUST_LOG").clone();
use tracing_subscriber::{layer::SubscriberExt, Registry};

#[cfg(feature = "otel")]
let telemetry = {
use std::time::Duration;

use opentelemetry::{global, KeyValue};
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::{
propagation::TraceContextPropagator,
trace::{self, Sampler},
Resource,
};

global::set_text_map_propagator(TraceContextPropagator::new());

let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(
opentelemetry_otlp::new_exporter()
.tonic()
.with_timeout(Duration::from_secs(3)),
)
.with_trace_config(
trace::config()
.with_sampler(Sampler::AlwaysOn)
.with_resource(Resource::new(vec![KeyValue::new("service.name", "rustup")])),
)
.install_batch(opentelemetry_sdk::runtime::Tokio)?;
let env_filter = EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new("INFO"));
tracing_opentelemetry::layer()
.with_tracer(tracer)
.with_filter(env_filter)
};
let telemetry = rustup::cli::log::telemetry()?;
let console_logger = {
let logger = tracing_subscriber::fmt::layer()
.with_writer(move || curr_process.stderr())
.with_ansi(has_ansi);
if let Some(directives) = maybe_rust_log_directives {
let env_filter = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.parse_lossy(directives.to_string_lossy());
logger.compact().with_filter(env_filter).boxed()
} else {
// Receive log lines from Rustup only.
let env_filter = EnvFilter::new("rustup=DEBUG");
logger
.event_format(rustup::cli::log::EventFormatter)
.with_filter(env_filter)
.boxed()
}
let curr_process = process();
let has_ansi = curr_process.stderr().is_a_tty();
rustup::cli::log::console_logger(curr_process, has_ansi)
};
let subscriber = {
#[cfg(feature = "otel")]
Expand Down
86 changes: 80 additions & 6 deletions src/cli/log.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use std::{fmt, io::Write};

use termcolor::{Color, ColorSpec, WriteColor};
use tracing::{Event, Subscriber};
use tracing_subscriber::fmt::{
format::{self, FormatEvent, FormatFields},
FmtContext,
use tracing::{level_filters::LevelFilter, Event, Subscriber};
use tracing_subscriber::{
fmt::{
format::{self, FormatEvent, FormatFields},
FmtContext,
},
registry::LookupSpan,
EnvFilter, Layer,
};
use tracing_subscriber::registry::LookupSpan;

use crate::utils::notify::NotificationLevel;
use crate::{
currentprocess::{filesource::StderrSource as _, varsource::VarSource as _, Process},
utils::notify::NotificationLevel,
};

macro_rules! debug {
( $ ( $ arg : tt ) * ) => ( ::tracing::trace ! ( $ ( $ arg ) * ) )
Expand All @@ -30,6 +36,74 @@ macro_rules! err {
( $ ( $ arg : tt ) * ) => ( ::tracing::error ! ( $ ( $ arg ) * ) )
}

/// A [`tracing::Subscriber`] [`Layer`][`tracing_subscriber::Layer`] that prints out the log
/// lines to the current [`Process`]' `stderr`.
///
/// When the `RUST_LOG` environment variable is present, a standard [`tracing_subscriber`]
/// formatter will be used according to the filtering directives set in its value.
/// Otherwise, this logger will use [`EventFormatter`] to mimic "classic" Rustup `stderr` output.
pub fn console_logger<S>(process: Process, with_ansi: bool) -> impl Layer<S>
where
S: Subscriber + for<'span> LookupSpan<'span>,
{
let maybe_rust_log_directives = process.var_os("RUST_LOG").clone();
let logger = tracing_subscriber::fmt::layer()
.with_writer(move || process.stderr())
.with_ansi(with_ansi);
if let Some(directives) = maybe_rust_log_directives {
let env_filter = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.parse_lossy(directives.to_string_lossy());
logger.compact().with_filter(env_filter).boxed()
} else {
// Receive log lines from Rustup only.
let env_filter = EnvFilter::new("rustup=DEBUG");
logger
.event_format(EventFormatter)
.with_filter(env_filter)
.boxed()
}
}

/// A [`tracing::Subscriber`] [`Layer`][`tracing_subscriber::Layer`] that corresponds to Rustup's
/// optional `opentelemetry` (a.k.a. `otel`) feature.
#[cfg(feature = "otel")]
pub fn telemetry<S>() -> anyhow::Result<impl Layer<S>>
where
S: Subscriber + for<'span> LookupSpan<'span>,
{
use std::time::Duration;

use opentelemetry::{global, KeyValue};
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::{
propagation::TraceContextPropagator,
trace::{self, Sampler},
Resource,
};

global::set_text_map_propagator(TraceContextPropagator::new());

let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(
opentelemetry_otlp::new_exporter()
.tonic()
.with_timeout(Duration::from_secs(3)),
)
.with_trace_config(
trace::config()
.with_sampler(Sampler::AlwaysOn)
.with_resource(Resource::new(vec![KeyValue::new("service.name", "rustup")])),
)
.install_batch(opentelemetry_sdk::runtime::Tokio)?;
// NOTE: This reads from the real environment variables instead of `process().var_os()`.
let env_filter = EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new("INFO"));
Ok(tracing_opentelemetry::layer()
.with_tracer(tracer)
.with_filter(env_filter))
}

// Adapted from
// https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/trait.FormatEvent.html#examples
pub struct EventFormatter;
Expand Down

0 comments on commit 0b3e73b

Please sign in to comment.