11//! This module contains functionality to initialise tracing Subscribers for
2- //! console output, and OpenTelemetry OTLP export for traces and logs.
2+ //! console output, file output, and OpenTelemetry OTLP export for traces and logs.
33//!
44//! It is intended to be used by the Stackable Data Platform operators and
55//! webhooks, but it should be generic enough to be used in any application.
@@ -16,6 +16,7 @@ use opentelemetry_sdk::{
1616use opentelemetry_semantic_conventions:: resource;
1717use snafu:: { ResultExt as _, Snafu } ;
1818use tracing:: subscriber:: SetGlobalDefaultError ;
19+ use tracing_appender:: rolling:: { InitError , RollingFileAppender , Rotation } ;
1920use tracing_subscriber:: { filter:: Directive , layer:: SubscriberExt , EnvFilter , Layer , Registry } ;
2021
2122use settings:: * ;
@@ -38,6 +39,9 @@ pub enum Error {
3839
3940 #[ snafu( display( "unable to set the global default subscriber" ) ) ]
4041 SetGlobalDefaultSubscriber { source : SetGlobalDefaultError } ,
42+
43+ #[ snafu( display( "failed to initialize rolling file appender" ) ) ]
44+ InitRollingFileAppender { source : InitError } ,
4145}
4246
4347/// Easily initialize a set of pre-configured [`Subscriber`][1] layers.
@@ -214,6 +218,7 @@ pub enum Error {
214218pub struct Tracing {
215219 service_name : & ' static str ,
216220 console_log_settings : ConsoleLogSettings ,
221+ file_log_settings : FileLogSettings ,
217222 otlp_log_settings : OtlpLogSettings ,
218223 otlp_trace_settings : OtlpTraceSettings ,
219224 logger_provider : Option < LoggerProvider > ,
@@ -246,6 +251,29 @@ impl Tracing {
246251 layers. push ( console_output_layer. boxed ( ) ) ;
247252 }
248253
254+ if self . file_log_settings . enabled {
255+ let env_filter_layer = env_filter_builder (
256+ self . file_log_settings . common_settings . environment_variable ,
257+ self . file_log_settings . default_level ,
258+ ) ;
259+
260+ let file_appender = RollingFileAppender :: builder ( )
261+ . rotation ( Rotation :: HOURLY )
262+ . filename_prefix ( self . service_name . to_string ( ) )
263+ . filename_suffix ( "tracing-rs.json" )
264+ . max_log_files ( 6 )
265+ . build ( & self . file_log_settings . file_log_dir )
266+ . context ( InitRollingFileAppenderSnafu ) ?;
267+
268+ layers. push (
269+ tracing_subscriber:: fmt:: layer ( )
270+ . json ( )
271+ . with_writer ( file_appender)
272+ . with_filter ( env_filter_layer)
273+ . boxed ( ) ,
274+ ) ;
275+ }
276+
249277 if self . otlp_log_settings . enabled {
250278 let env_filter_layer = env_filter_builder (
251279 self . otlp_log_settings . environment_variable ,
@@ -385,12 +413,6 @@ mod builder_state {
385413 #[ derive( Default ) ]
386414 pub struct PreServiceName ;
387415
388- /// The state before the [`EnvFilter`][1] environment variable name is set.
389- ///
390- /// [1]: tracing_subscriber::filter::EnvFilter
391- #[ derive( Default ) ]
392- pub struct PreEnvVar ;
393-
394416 /// The state that allows you to configure the supported [`Subscriber`][1]
395417 /// [`Layer`][2].
396418 ///
@@ -414,6 +436,7 @@ pub struct TracingBuilder<S: BuilderState> {
414436 console_log_settings : ConsoleLogSettings ,
415437 otlp_log_settings : OtlpLogSettings ,
416438 otlp_trace_settings : OtlpTraceSettings ,
439+ file_log_settings : FileLogSettings ,
417440
418441 /// Allow the generic to be used (needed for impls).
419442 _marker : std:: marker:: PhantomData < S > ,
@@ -446,6 +469,26 @@ impl TracingBuilder<builder_state::Config> {
446469 console_log_settings : console_log_settings. into ( ) ,
447470 otlp_log_settings : self . otlp_log_settings ,
448471 otlp_trace_settings : self . otlp_trace_settings ,
472+ file_log_settings : self . file_log_settings ,
473+ _marker : self . _marker ,
474+ }
475+ }
476+
477+ /// Enable the file output tracing subscriber and set the default
478+ /// [`LevelFilter`][1] which is overridable through the given environment
479+ /// variable.
480+ ///
481+ /// [1]: tracing_subscriber::filter::LevelFilter
482+ pub fn with_file_output (
483+ self ,
484+ file_log_settings : impl Into < FileLogSettings > ,
485+ ) -> TracingBuilder < builder_state:: Config > {
486+ TracingBuilder {
487+ service_name : self . service_name ,
488+ console_log_settings : self . console_log_settings ,
489+ file_log_settings : file_log_settings. into ( ) ,
490+ otlp_log_settings : self . otlp_log_settings ,
491+ otlp_trace_settings : self . otlp_trace_settings ,
449492 _marker : self . _marker ,
450493 }
451494 }
@@ -466,6 +509,7 @@ impl TracingBuilder<builder_state::Config> {
466509 console_log_settings : self . console_log_settings ,
467510 otlp_log_settings : otlp_log_settings. into ( ) ,
468511 otlp_trace_settings : self . otlp_trace_settings ,
512+ file_log_settings : self . file_log_settings ,
469513 _marker : self . _marker ,
470514 }
471515 }
@@ -486,6 +530,7 @@ impl TracingBuilder<builder_state::Config> {
486530 console_log_settings : self . console_log_settings ,
487531 otlp_log_settings : self . otlp_log_settings ,
488532 otlp_trace_settings : otlp_trace_settings. into ( ) ,
533+ file_log_settings : self . file_log_settings ,
489534 _marker : self . _marker ,
490535 }
491536 }
@@ -502,6 +547,7 @@ impl TracingBuilder<builder_state::Config> {
502547 console_log_settings : self . console_log_settings ,
503548 otlp_log_settings : self . otlp_log_settings ,
504549 otlp_trace_settings : self . otlp_trace_settings ,
550+ file_log_settings : self . file_log_settings ,
505551 logger_provider : None ,
506552 }
507553 }
@@ -517,6 +563,8 @@ fn env_filter_builder(env_var: &str, default_directive: impl Into<Directive>) ->
517563
518564#[ cfg( test) ]
519565mod test {
566+ use std:: path:: PathBuf ;
567+
520568 use rstest:: rstest;
521569 use settings:: Settings ;
522570 use tracing:: level_filters:: LevelFilter ;
@@ -618,6 +666,14 @@ mod test {
618666 . enabled ( true )
619667 . build ( ) ,
620668 )
669+ . with_file_output (
670+ Settings :: builder ( )
671+ . with_environment_variable ( "ABC_FILE" )
672+ . with_default_level ( LevelFilter :: INFO )
673+ . enabled ( true )
674+ . file_log_settings_builder ( PathBuf :: from ( "/abc_file_dir" ) )
675+ . build ( ) ,
676+ )
621677 . with_otlp_log_exporter (
622678 Settings :: builder ( )
623679 . with_environment_variable ( "ABC_OTLP_LOG" )
@@ -645,6 +701,17 @@ mod test {
645701 log_format: Default :: default ( )
646702 }
647703 ) ;
704+ assert_eq ! (
705+ trace_guard. file_log_settings,
706+ FileLogSettings {
707+ common_settings: Settings {
708+ enabled: true ,
709+ environment_variable: "ABC_FILE" ,
710+ default_level: LevelFilter :: INFO
711+ } ,
712+ file_log_dir: PathBuf :: from( "/abc_file_dir" )
713+ }
714+ ) ;
648715 assert_eq ! (
649716 trace_guard. otlp_log_settings,
650717 OtlpLogSettings {
0 commit comments