git.delta.rocks / fleet / refs/commits / 347078813131

difftreelog

source

crates/goodlog-subscriber/src/lib.rs4.0 KiBsourcehistory
1mod log_tree;23use anyhow::Result;4use clap::Parser;5#[cfg(feature = "indicatif")]6use human_repr::HumanCount;7#[cfg(feature = "indicatif")]8use indicatif::{ProgressState, ProgressStyle};9use log_tree::TreeLayer;10use opentelemetry::trace::TracerProvider;11use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;12use opentelemetry_exporter_env::{13	OtlpBaseSettings, OtlpLogsSettings, OtlpTracesSettings, ResolvedOtlpSettings,14};15use opentelemetry_sdk::{logs::SdkLoggerProvider, trace::SdkTracerProvider};16#[cfg(feature = "indicatif")]17use tracing_indicatif::IndicatifLayer;18use tracing_subscriber::layer::SubscriberExt as _;19use tracing_subscriber::util::SubscriberInitExt as _;20use tracing_subscriber::{EnvFilter, Layer as _};2122#[derive(Parser)]23#[clap(next_help_heading = "Telemetry")]24pub struct LogOpts {25	/// Whatever opentelemetry logging should be enabled26	#[clap(long, env = "OTEL_FLEET")]27	otel: bool,28	#[clap(flatten)]29	otlp_base: OtlpBaseSettings,30	#[clap(flatten)]31	otel_logs: OtlpLogsSettings,32	#[clap(flatten)]33	otel_traces: OtlpTracesSettings,34}3536pub fn setup_logging(opts: &LogOpts) -> Result<()> {37	#[cfg(feature = "indicatif")]38	let indicatif_layer = {39		use std::fmt;40		use std::time::Duration;4142		IndicatifLayer::new().with_max_progress_bars(10, Some(ProgressStyle::default_spinner()))43			.with_span_child_prefix_indent("  ")44			.with_span_child_prefix_symbol("")45			.with_progress_style(46			ProgressStyle::with_template(47				"{span_child_prefix:.magenta}{chevron:.magenta}{span_name:<18.blue.bold} {wide_msg} {span_fields:.dim} {color_start}{download_progress} {elapsed}{color_end}",48			)49				.unwrap()50				.with_key("chevron", |_: &ProgressState, writer: &mut dyn fmt::Write| {51					let _ = write!(writer, "> ");52				})53				.with_key("download_progress", |state: &ProgressState, writer: &mut dyn fmt::Write| {54					let Some(len) = state.len() else {55						return;56					};57					let pos = state.pos();58					if pos > len {59						let _ = write!(writer, "{}", pos.human_count_bare());60					} else {61						let _ = write!(writer, "{} / {}", pos.human_count_bare(), len.human_count_bare());62					}63				})64				.with_key(65					"color_start",66					|state: &ProgressState, writer: &mut dyn fmt::Write| {67						let elapsed = state.elapsed();6869						if elapsed > Duration::from_secs(60) {70							// Red71							let _ = write!(writer, "\x1b[{}m", 1 + 30);72						} else if elapsed > Duration::from_secs(30) {73							// Yellow74							let _ = write!(writer, "\x1b[{}m", 3 + 30);75						}76					},77				)78				.with_key(79					"color_end",80					|state: &ProgressState, writer: &mut dyn fmt::Write| {81						if state.elapsed() > Duration::from_secs(30) {82							let _ = write!(writer, "\x1b[0m");83						}84					},85				),86		)87	};8889	// TODO: Default filter should be configurable90	let filter =91		EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("noq_udp=warn,info"));9293	let tree = {94		#[cfg(feature = "indicatif")]95		let writer = indicatif_layer.get_stderr_writer();96		#[cfg(not(feature = "indicatif"))]97		let writer = || std::io::stderr();98		TreeLayer::new(writer)99	};100101	let reg = tracing_subscriber::registry();102103	#[cfg(feature = "tokio-console")]104	let reg = reg.with(console_subscriber::spawn());105106	let reg = reg.with(tree.with_filter(filter));107108	#[cfg(feature = "indicatif")]109	let reg = reg.with(indicatif_layer);110111	if opts.otel {112		let traces = ResolvedOtlpSettings::traces(&opts.otlp_base, &opts.otel_traces)?;113		let span_exporter = traces.span_exporter()?;114		let logs = ResolvedOtlpSettings::logs(&opts.otlp_base, &opts.otel_logs)?;115		let log_exporter = logs.log_exporter()?;116117		let span_provider = SdkTracerProvider::builder()118			.with_batch_exporter(span_exporter)119			.build();120		let log_provider = SdkLoggerProvider::builder()121			.with_batch_exporter(log_exporter)122			.build();123124		let logger = OpenTelemetryTracingBridge::new(&log_provider);125		let tracer = span_provider.tracer("fleet");126127		reg.with(tracing_opentelemetry::layer().with_tracer(tracer))128			.with(logger)129			.init();130	} else {131		reg.init();132	}133134	Ok(())135}