diff --git a/crates/stackable-telemetry/CHANGELOG.md b/crates/stackable-telemetry/CHANGELOG.md index a7935073a..b23b820b7 100644 --- a/crates/stackable-telemetry/CHANGELOG.md +++ b/crates/stackable-telemetry/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- BREAKING: Allow customization of the rolling file appender [#995]. + - Add required `filename_suffix` field. + - Add `with_rotation_period` method. + - Add `with_max_log_files` method. + +[#995]: https://github.com/stackabletech/operator-rs/pull/995 + ## [0.3.0] - 2025-01-30 ### Added diff --git a/crates/stackable-telemetry/src/tracing/mod.rs b/crates/stackable-telemetry/src/tracing/mod.rs index cf00503b7..0e806b39b 100644 --- a/crates/stackable-telemetry/src/tracing/mod.rs +++ b/crates/stackable-telemetry/src/tracing/mod.rs @@ -16,7 +16,7 @@ use opentelemetry_sdk::{ use opentelemetry_semantic_conventions::resource; use snafu::{ResultExt as _, Snafu}; use tracing::subscriber::SetGlobalDefaultError; -use tracing_appender::rolling::{InitError, RollingFileAppender, Rotation}; +use tracing_appender::rolling::{InitError, RollingFileAppender}; use tracing_subscriber::{filter::Directive, layer::SubscriberExt, EnvFilter, Layer, Registry}; use crate::tracing::settings::*; @@ -275,6 +275,9 @@ impl Tracing { if let FileLogSettings::Enabled { common_settings, file_log_dir, + rotation_period, + filename_suffix, + max_log_files, } = &self.file_log_settings { let env_filter_layer = env_filter_builder( @@ -283,10 +286,17 @@ impl Tracing { ); let file_appender = RollingFileAppender::builder() - .rotation(Rotation::HOURLY) + .rotation(rotation_period.clone()) .filename_prefix(self.service_name.to_string()) - .filename_suffix("tracing-rs.json") - .max_log_files(6) + .filename_suffix(filename_suffix); + + let file_appender = if let Some(max_log_files) = max_log_files { + file_appender.max_log_files(*max_log_files) + } else { + file_appender + }; + + let file_appender = file_appender .build(file_log_dir) .context(InitRollingFileAppenderSnafu)?; @@ -592,6 +602,7 @@ mod test { use rstest::rstest; use settings::Settings; use tracing::level_filters::LevelFilter; + use tracing_appender::rolling::Rotation; use super::*; @@ -692,7 +703,7 @@ mod test { Settings::builder() .with_environment_variable("ABC_FILE") .with_default_level(LevelFilter::INFO) - .file_log_settings_builder(PathBuf::from("/abc_file_dir")) + .file_log_settings_builder(PathBuf::from("/abc_file_dir"), "tracing-rs.json") .build(), ) .with_otlp_log_exporter( @@ -726,7 +737,10 @@ mod test { environment_variable: "ABC_FILE", default_level: LevelFilter::INFO }, - file_log_dir: PathBuf::from("/abc_file_dir") + file_log_dir: PathBuf::from("/abc_file_dir"), + rotation_period: Rotation::NEVER, + filename_suffix: "tracing-rs.json".to_owned(), + max_log_files: None, } ); assert_eq!( @@ -766,7 +780,7 @@ mod test { .with_file_output(enable_filelog_output.then(|| { Settings::builder() .with_environment_variable("ABC_FILELOG") - .file_log_settings_builder("/dev/null") + .file_log_settings_builder("/dev/null", "tracing-rs.json") .build() })) .with_otlp_trace_exporter(enable_otlp_trace.then(|| { diff --git a/crates/stackable-telemetry/src/tracing/settings/file_log.rs b/crates/stackable-telemetry/src/tracing/settings/file_log.rs index 53c326c4e..75378cc24 100644 --- a/crates/stackable-telemetry/src/tracing/settings/file_log.rs +++ b/crates/stackable-telemetry/src/tracing/settings/file_log.rs @@ -2,6 +2,9 @@ use std::path::PathBuf; +/// Re-export to save the end crate from an extra import. +pub use tracing_appender::rolling::Rotation; + use super::{Settings, SettingsToggle}; /// Configure specific settings for the File Log subscriber. @@ -18,6 +21,15 @@ pub enum FileLogSettings { /// Path to directory for log files. file_log_dir: PathBuf, + + /// Log rotation frequency. + rotation_period: Rotation, + + /// Suffix for log filenames. + filename_suffix: String, + + /// Keep the last `n` files on disk. + max_log_files: Option, }, } @@ -38,14 +50,32 @@ impl SettingsToggle for FileLogSettings { pub struct FileLogSettingsBuilder { pub(crate) common_settings: Settings, pub(crate) file_log_dir: PathBuf, + pub(crate) rotation_period: Rotation, + pub(crate) filename_suffix: String, + pub(crate) max_log_files: Option, } impl FileLogSettingsBuilder { + /// Set file rotation period. + pub fn with_rotation_period(mut self, rotation_period: Rotation) -> Self { + self.rotation_period = rotation_period; + self + } + + /// Set maximum number of log files to keep. + pub fn with_max_log_files(mut self, max_log_files: usize) -> Self { + self.max_log_files = Some(max_log_files); + self + } + /// Consumes self and returns a valid [`FileLogSettings`] instance. pub fn build(self) -> FileLogSettings { FileLogSettings::Enabled { common_settings: self.common_settings, file_log_dir: self.file_log_dir, + rotation_period: self.rotation_period, + filename_suffix: self.filename_suffix, + max_log_files: self.max_log_files, } } } @@ -76,11 +106,16 @@ mod test { default_level: LevelFilter::DEBUG, }, file_log_dir: PathBuf::from("/logs"), + rotation_period: Rotation::HOURLY, + filename_suffix: "tracing-rs.log".to_owned(), + max_log_files: Some(6), }; let result = Settings::builder() .with_environment_variable("hello") .with_default_level(LevelFilter::DEBUG) - .file_log_settings_builder(PathBuf::from("/logs")) + .file_log_settings_builder(PathBuf::from("/logs"), "tracing-rs.json") + .with_rotation_period(Rotation::HOURLY) + .with_max_log_files(6) .build(); assert_eq!(expected, result); diff --git a/crates/stackable-telemetry/src/tracing/settings/mod.rs b/crates/stackable-telemetry/src/tracing/settings/mod.rs index cee7a9328..6eb19e509 100644 --- a/crates/stackable-telemetry/src/tracing/settings/mod.rs +++ b/crates/stackable-telemetry/src/tracing/settings/mod.rs @@ -85,13 +85,17 @@ impl SettingsBuilder { } /// Set specific [`FileLogSettings`]. - pub fn file_log_settings_builder

(self, path: P) -> FileLogSettingsBuilder - where - P: AsRef, - { + pub fn file_log_settings_builder( + self, + path: impl AsRef, + filename_suffix: impl Into, + ) -> FileLogSettingsBuilder { FileLogSettingsBuilder { common_settings: self.build(), file_log_dir: path.as_ref().to_path_buf(), + rotation_period: Rotation::NEVER, + filename_suffix: filename_suffix.into(), + max_log_files: None, } }