1
- use opentelemetry:: global:: { self , set_error_handler , Error as OtelError } ;
1
+ use opentelemetry:: global:: { self , Error as OtelError } ;
2
2
use opentelemetry:: KeyValue ;
3
3
use opentelemetry_appender_tracing:: layer;
4
4
use opentelemetry_otlp:: { LogExporter , MetricExporter , WithExportConfig } ;
5
5
use opentelemetry_sdk:: metrics:: PeriodicReader ;
6
- use tracing_subscriber:: filter:: { EnvFilter , LevelFilter } ;
7
- use tracing_subscriber:: fmt;
8
6
use tracing_subscriber:: prelude:: * ;
9
7
10
8
use std:: error:: Error ;
11
- use tracing:: error;
12
9
13
10
use once_cell:: sync:: Lazy ;
14
11
use std:: collections:: HashSet ;
15
12
use std:: sync:: { Arc , Mutex } ;
16
13
17
14
use std:: sync:: mpsc:: channel;
18
15
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
-
54
16
fn init_logger_provider ( ) -> opentelemetry_sdk:: logs:: LoggerProvider {
55
17
let exporter = LogExporter :: builder ( )
56
18
. with_http ( )
@@ -64,46 +26,46 @@ fn init_logger_provider() -> opentelemetry_sdk::logs::LoggerProvider {
64
26
65
27
let cloned_provider = provider. clone ( ) ;
66
28
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
87
44
} ) ;
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" ) )
98
61
} ) ;
99
62
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 ( ) ) ;
102
65
103
66
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)
107
69
. init ( ) ;
108
70
provider
109
71
}
@@ -130,11 +92,6 @@ fn init_meter_provider() -> opentelemetry_sdk::metrics::SdkMeterProvider {
130
92
131
93
#[ tokio:: main]
132
94
async 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
-
138
95
let logger_provider = init_logger_provider ( ) ;
139
96
140
97
// Initialize the MeterProvider with the stdout Exporter.
0 commit comments