@@ -29,8 +29,7 @@ use tracing_subscriber::util::SubscriberInitExt as _;
2929use tracing_subscriber:: { EnvFilter , Layer } ;
3030use url:: Url ;
3131
32- use crate :: build_info:: GIT_COMMIT_HASH ;
33- use crate :: cli:: TracingOptions ;
32+ use crate :: cli:: { GraylogOptions , TracingOptions } ;
3433
3534#[ derive( Debug , thiserror:: Error ) ]
3635pub enum LoggingError {
@@ -87,57 +86,62 @@ where
8786 }
8887}
8988
90- fn init_graylog < S > ( endpoint : Option < Url > , level : Level , ) -> Result < Option < impl Layer < S > > , LoggingError >
89+ fn init_graylog < S > ( opts : & GraylogOptions ) -> Result < Option < impl Layer < S > > , LoggingError >
9190where
9291 S : Subscriber + for < ' s > LookupSpan < ' s > ,
9392{
94- let Some ( endpoint) = endpoint else {
95- return Ok ( None ) ;
96- } ;
97-
98- let address = format ! (
99- "{}:{}" ,
100- endpoint. host_str( ) . unwrap_or( "localhost" ) ,
101- endpoint. port( ) . unwrap_or( 12201 ) ,
102- ) ;
103-
104- match Logger :: builder ( )
105- . additional_field ( "version" , env ! ( "CARGO_PKG_VERSION" ) )
106- . additional_field ( "build" , GIT_COMMIT_HASH . unwrap_or ( "unknown" ) )
107- . connect_tcp ( address)
108- {
109- Ok ( ( logger, mut handle) ) => {
110- tokio:: spawn ( async move {
111- let errors = handle. connect ( ) . await ;
112- if errors. 0 . is_empty ( ) {
113- error ! ( "Failed to connect to graylog - address lookup failed" ) ;
114- } else {
115- warn ! (
116- "Connection to graylog {:?} closed: {:?}" ,
117- handle. address( ) ,
118- errors
119- ) ;
120- }
121- } ) ;
122- Ok ( Some (
123- logger
124- . with_filter ( LevelFilter :: from_level ( level) )
125- . with_filter ( FilterFn :: new ( |m| {
126- m. target ( ) . starts_with ( env ! ( "CARGO_PKG_NAME" ) )
127- } ) ) ,
128- ) )
129- }
130- Err ( e) => {
131- eprintln ! ( "Couldn't create graylog logger: {e}" ) ;
132- Ok ( None )
93+ if let Some ( endpoint) = & opts. graylog_url {
94+ let level = opts. logging_level ;
95+ let port = endpoint. port ( ) . unwrap_or_else ( || {
96+ warn ! ( "No port specified for Graylog endpoint, using default 12201" ) ;
97+ 12201
98+ } ) ;
99+ let address = format ! (
100+ "{}:{}" ,
101+ endpoint. host_str( ) . unwrap_or( "localhost" ) ,
102+ port,
103+ ) ;
104+
105+ match Logger :: builder ( ) . connect_tcp ( address) {
106+ Ok ( ( logger, mut handle) ) => {
107+ tokio:: spawn ( async move {
108+ loop {
109+ let errors = handle. connect ( ) . await ;
110+ if errors. 0 . is_empty ( ) {
111+ error ! (
112+ "Graylog DNS lookup failed for {:?} - no addresses resolved" ,
113+ handle. address( )
114+ ) ;
115+ break ;
116+ } else {
117+ for ( addr, err) in & errors. 0 {
118+ warn ! ( "Graylog connection to {addr} failed: {err} - reconnecting" ) ;
119+ }
120+ }
121+ }
122+ } ) ;
123+ Ok ( Some (
124+ logger
125+ . with_filter ( LevelFilter :: from_level ( level) )
126+ . with_filter ( FilterFn :: new ( |m| {
127+ m. target ( ) . starts_with ( env ! ( "CARGO_PKG_NAME" ) )
128+ } ) ) ,
129+ ) )
130+ }
131+ Err ( e) => {
132+ eprintln ! ( "Couldn't create graylog logger: {e}" ) ;
133+ Ok ( None )
134+ }
133135 }
136+ } else {
137+ Ok ( None )
134138 }
135139}
136140
137- pub fn init ( logging : Option < Level > , tracing : & TracingOptions ) -> Result < ( ) , LoggingError > {
141+ pub fn init ( logging : Option < Level > , tracing : & TracingOptions , graylog : & GraylogOptions ) -> Result < ( ) , LoggingError > {
138142 let log_layer = init_stdout ( logging) ;
139143 let trace_layer = init_tracing ( tracing. tracing_url ( ) , tracing. level ( ) ) ?;
140- let graylog_layer = init_graylog ( tracing . graylog_url ( ) , tracing . logging_level ( ) ) ?;
144+ let graylog_layer = init_graylog ( graylog ) ?;
141145 // Whatever level is set for logging/tracing, ignore the noise from the low-level libraries
142146 let filter = EnvFilter :: new ( "trace" ) // let everything through
143147 . add_directive ( "h2=info" . parse ( ) . expect ( "Static string is valid" ) ) // except http,
@@ -161,23 +165,24 @@ mod tests {
161165 use tracing_subscriber:: Registry ;
162166
163167 use super :: init_graylog;
168+ use crate :: cli:: GraylogOptions ;
164169
165170 #[ test]
166171 fn no_graylog_endpoint_returns_none ( ) {
167- // No URL configured means no layer should be added
168- let result = init_graylog :: < Registry > ( None , Level :: INFO ) ;
172+ let opts = GraylogOptions { graylog_url : None , logging_level : Level :: INFO } ;
173+ let result = init_graylog :: < Registry > ( & opts ) ;
169174 assert ! ( matches!( result, Ok ( None ) ) ) ;
170175 }
171176
172177 #[ tokio:: test]
173178 async fn graylog_with_endpoint_returns_layer ( ) {
174- // Bind a random local port to accept the TCP connection
175179 let listener = TcpListener :: bind ( "127.0.0.1:0" ) . expect ( "bind local port" ) ;
176180 let port = listener. local_addr ( ) . expect ( "local addr" ) . port ( ) ;
177- let url = format ! ( "tcp://127.0.0.1:{port}" )
178- . parse ( )
179- . expect ( "valid url" ) ;
180- let result = init_graylog :: < Registry > ( Some ( url) , Level :: INFO ) ;
181+ let opts = GraylogOptions {
182+ graylog_url : Some ( format ! ( "tcp://127.0.0.1:{port}" ) . parse ( ) . expect ( "valid url" ) ) ,
183+ logging_level : Level :: INFO ,
184+ } ;
185+ let result = init_graylog :: < Registry > ( & opts) ;
181186 assert ! ( matches!( result, Ok ( Some ( _) ) ) ) ;
182187 }
183188}
0 commit comments