Skip to content

feat(stackable-telemetry)!: Allow customization of the rolling file appender #995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
9 changes: 9 additions & 0 deletions crates/stackable-telemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 21 additions & 7 deletions crates/stackable-telemetry/src/tracing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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(
Expand All @@ -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)?;

Expand Down Expand Up @@ -592,6 +602,7 @@ mod test {
use rstest::rstest;
use settings::Settings;
use tracing::level_filters::LevelFilter;
use tracing_appender::rolling::Rotation;

use super::*;

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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(|| {
Expand Down
37 changes: 36 additions & 1 deletion crates/stackable-telemetry/src/tracing/settings/file_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<usize>,
},
}

Expand All @@ -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<usize>,
}

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,
}
}
}
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 8 additions & 4 deletions crates/stackable-telemetry/src/tracing/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,17 @@ impl SettingsBuilder {
}

/// Set specific [`FileLogSettings`].
pub fn file_log_settings_builder<P>(self, path: P) -> FileLogSettingsBuilder
where
P: AsRef<Path>,
{
pub fn file_log_settings_builder(
self,
path: impl AsRef<Path>,
filename_suffix: impl Into<String>,
) -> 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,
}
}

Expand Down
Loading