1- use opentelemetry:: global:: { self , set_error_handler , Error as OtelError } ;
1+ use opentelemetry:: global:: { self , Error as OtelError } ;
22use opentelemetry:: KeyValue ;
33use opentelemetry_appender_tracing:: layer;
44use opentelemetry_otlp:: { LogExporter , MetricExporter , WithExportConfig } ;
55use opentelemetry_sdk:: metrics:: PeriodicReader ;
6- use tracing_subscriber:: filter:: { EnvFilter , LevelFilter } ;
7- use tracing_subscriber:: fmt;
86use tracing_subscriber:: prelude:: * ;
97
108use std:: error:: Error ;
11- use tracing:: error;
129
1310use once_cell:: sync:: Lazy ;
1411use std:: collections:: HashSet ;
1512use std:: sync:: { Arc , Mutex } ;
1613
1714use std:: sync:: mpsc:: channel;
1815
19- struct ErrorState {
20- seen_errors : Mutex < HashSet < String > > ,
21- }
22-
23- impl ErrorState {
24- fn new ( ) -> Self {
25- ErrorState {
26- seen_errors : Mutex :: new ( HashSet :: new ( ) ) ,
27- }
28- }
29-
30- fn mark_as_seen ( & self , err : & OtelError ) -> bool {
31- let mut seen_errors = self . seen_errors . lock ( ) . unwrap ( ) ;
32- seen_errors. insert ( err. to_string ( ) )
33- }
34- }
35-
36- static GLOBAL_ERROR_STATE : Lazy < Arc < ErrorState > > = Lazy :: new ( || Arc :: new ( ErrorState :: new ( ) ) ) ;
37-
38- fn custom_error_handler ( err : OtelError ) {
39- if GLOBAL_ERROR_STATE . mark_as_seen ( & err) {
40- // log error not already seen
41- match err {
42- OtelError :: Metric ( err) => error ! ( "OpenTelemetry metrics error occurred: {}" , err) ,
43- OtelError :: Trace ( err) => error ! ( "OpenTelemetry trace error occurred: {}" , err) ,
44- OtelError :: Log ( err) => error ! ( "OpenTelemetry log error occurred: {}" , err) ,
45- OtelError :: Propagation ( err) => {
46- error ! ( "OpenTelemetry propagation error occurred: {}" , err)
47- }
48- OtelError :: Other ( err_msg) => error ! ( "OpenTelemetry error occurred: {}" , err_msg) ,
49- _ => error ! ( "OpenTelemetry error occurred: {:?}" , err) ,
50- }
51- }
52- }
53-
5416fn init_logger_provider ( ) -> opentelemetry_sdk:: logs:: LoggerProvider {
5517 let exporter = LogExporter :: builder ( )
5618 . with_http ( )
@@ -64,46 +26,46 @@ fn init_logger_provider() -> opentelemetry_sdk::logs::LoggerProvider {
6426
6527 let cloned_provider = provider. clone ( ) ;
6628
67- // Add a tracing filter to filter events from crates used by opentelemetry-otlp.
68- // The filter levels are set as follows:
69- // - Allow `info` level and above by default.
70- // - Restrict `hyper`, `tonic`, and `reqwest` to `error` level logs only.
71- // This ensures events generated from these crates within the OTLP Exporter are not looped back,
72- // thus preventing infinite event generation.
73- // Note: This will also drop events from these crates used outside the OTLP Exporter.
74- // For more details, see: https://github.com/open-telemetry/opentelemetry-rust/issues/761
75- let filter = EnvFilter :: new ( "info" )
76- . add_directive ( "hyper=error" . parse ( ) . unwrap ( ) )
77- . add_directive ( "tonic=error" . parse ( ) . unwrap ( ) )
78- . add_directive ( "reqwest=error" . parse ( ) . unwrap ( ) ) ;
79-
80- // Configuring the formatting layer specifically for OpenTelemetry internal logs.
81- // These logs starts with "opentelemetry" prefix in target. This allows specific logs
82- // from the OpenTelemetry-related components to be filtered and handled separately
83- // from the application logs
84-
85- let opentelemetry_filter = tracing_subscriber:: filter:: filter_fn ( |metadata| {
86- metadata. target ( ) . starts_with ( "opentelemetry" )
29+ // Specialized filter to process
30+ // - ERROR logs from specific targets
31+ // - ERROR logs generated internally.
32+ let internal_and_dependency_filter = tracing_subscriber:: filter:: filter_fn ( |metadata| {
33+ let target = metadata. target ( ) ;
34+
35+ // Only allow ERROR logs from specific targets
36+ ( target. starts_with ( "hyper" )
37+ || target. starts_with ( "hyper_util" )
38+ || target. starts_with ( "hyper" )
39+ || target. starts_with ( "tonic" )
40+ || target. starts_with ( "tower" )
41+ || target. starts_with ( "reqwest" )
42+ || target. starts_with ( "opentelemetry" ) )
43+ && metadata. level ( ) == & tracing:: Level :: ERROR
8744 } ) ;
88-
89- let fmt_opentelemetry_layer = fmt:: layer ( )
90- . with_filter ( LevelFilter :: DEBUG )
91- . with_filter ( opentelemetry_filter) ;
92-
93- // Configures the appender tracing layer, filtering out OpenTelemetry internal logs
94- // to prevent infinite logging loops.
95-
96- let non_opentelemetry_filter = tracing_subscriber:: filter:: filter_fn ( |metadata| {
97- !metadata. target ( ) . starts_with ( "opentelemetry" )
45+ // Configure fmt::Layer to print detailed log information, including structured fields
46+ let fmt_internal_and_dependency_layer =
47+ tracing_subscriber:: fmt:: layer ( ) . with_filter ( internal_and_dependency_filter. clone ( ) ) ;
48+
49+ // Application filter to exclude specific targets entirely, regardless of level
50+ let application_filter = tracing_subscriber:: filter:: filter_fn ( |metadata| {
51+ let target = metadata. target ( ) ;
52+
53+ // Exclude logs from specific targets for the application layer
54+ !( target. starts_with ( "hyper" )
55+ || target. starts_with ( "hyper_util" )
56+ || target. starts_with ( "hyper" )
57+ || target. starts_with ( "tonic" )
58+ || target. starts_with ( "tower" )
59+ || target. starts_with ( "reqwest" )
60+ || target. starts_with ( "opentelemetry" ) )
9861 } ) ;
9962
100- let otel_layer = layer:: OpenTelemetryTracingBridge :: new ( & cloned_provider)
101- . with_filter ( non_opentelemetry_filter . clone ( ) ) ;
63+ let application_layer = layer:: OpenTelemetryTracingBridge :: new ( & cloned_provider)
64+ . with_filter ( application_filter . clone ( ) ) ;
10265
10366 tracing_subscriber:: registry ( )
104- . with ( fmt_opentelemetry_layer)
105- . with ( fmt:: layer ( ) . with_filter ( filter) )
106- . with ( otel_layer)
67+ . with ( fmt_internal_and_dependency_layer)
68+ . with ( application_layer)
10769 . init ( ) ;
10870 provider
10971}
@@ -130,11 +92,6 @@ fn init_meter_provider() -> opentelemetry_sdk::metrics::SdkMeterProvider {
13092
13193#[ tokio:: main]
13294async fn main ( ) -> Result < ( ) , Box < dyn Error + Send + Sync + ' static > > {
133- // Set the custom error handler
134- if let Err ( err) = set_error_handler ( custom_error_handler) {
135- eprintln ! ( "Failed to set custom error handler: {}" , err) ;
136- }
137-
13895 let logger_provider = init_logger_provider ( ) ;
13996
14097 // Initialize the MeterProvider with the stdout Exporter.
0 commit comments