mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-01 01:38:18 +00:00
fix(obs): avoid panic in telemetry init and clamp sampler boundaries (#2118)
Signed-off-by: houseme <housemecn@gmail.com> Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -206,7 +206,7 @@ fn init_file_logging_internal(
|
|||||||
|
|
||||||
builder
|
builder
|
||||||
.build(log_directory)
|
.build(log_directory)
|
||||||
.expect("failed to initialize rolling file appender")
|
.map_err(|e| TelemetryError::Io(format!("failed to initialize rolling file appender: {e}")))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
|
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
|
||||||
@@ -417,3 +417,24 @@ fn spawn_cleanup_task(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::config::OtelConfig;
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_init_file_logging_invalid_filename_does_not_panic() {
|
||||||
|
let temp_dir = tempdir().expect("create temp dir");
|
||||||
|
let temp_path = temp_dir.path().to_str().expect("temp dir path is utf-8");
|
||||||
|
let config = OtelConfig {
|
||||||
|
log_filename: Some("invalid\0name.log".to_string()),
|
||||||
|
..OtelConfig::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = init_file_logging_internal(&config, temp_path, "info", true);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -96,11 +96,7 @@ pub(super) fn init_observability_http(
|
|||||||
let service_name = config.service_name.as_deref().unwrap_or(APP_NAME).to_owned();
|
let service_name = config.service_name.as_deref().unwrap_or(APP_NAME).to_owned();
|
||||||
let use_stdout = config.use_stdout.unwrap_or(!is_production);
|
let use_stdout = config.use_stdout.unwrap_or(!is_production);
|
||||||
let sample_ratio = config.sample_ratio.unwrap_or(SAMPLE_RATIO);
|
let sample_ratio = config.sample_ratio.unwrap_or(SAMPLE_RATIO);
|
||||||
let sampler = if (0.0..1.0).contains(&sample_ratio) {
|
let sampler = build_tracer_sampler(sample_ratio);
|
||||||
Sampler::TraceIdRatioBased(sample_ratio)
|
|
||||||
} else {
|
|
||||||
Sampler::AlwaysOn
|
|
||||||
};
|
|
||||||
|
|
||||||
// ── Endpoint resolution ───────────────────────────────────────────────────
|
// ── Endpoint resolution ───────────────────────────────────────────────────
|
||||||
// Each signal may have a dedicated endpoint; if absent, fall back to the
|
// Each signal may have a dedicated endpoint; if absent, fall back to the
|
||||||
@@ -239,6 +235,14 @@ fn build_tracer_provider(
|
|||||||
Ok(Some(provider))
|
Ok(Some(provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_tracer_sampler(sample_ratio: f64) -> Sampler {
|
||||||
|
if sample_ratio.is_finite() && (0.0..=1.0).contains(&sample_ratio) {
|
||||||
|
Sampler::TraceIdRatioBased(sample_ratio)
|
||||||
|
} else {
|
||||||
|
Sampler::AlwaysOn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build an optional [`SdkMeterProvider`] for the given metrics endpoint.
|
/// Build an optional [`SdkMeterProvider`] for the given metrics endpoint.
|
||||||
///
|
///
|
||||||
/// Returns `None` when the endpoint is empty or metric export is disabled.
|
/// Returns `None` when the endpoint is empty or metric export is disabled.
|
||||||
@@ -360,3 +364,29 @@ fn create_periodic_reader(interval: u64) -> PeriodicReader<opentelemetry_stdout:
|
|||||||
.with_interval(Duration::from_secs(interval))
|
.with_interval(Duration::from_secs(interval))
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_build_tracer_sampler_uses_trace_ratio_for_valid_values() {
|
||||||
|
let sampler = build_tracer_sampler(0.0);
|
||||||
|
assert!(format!("{sampler:?}").contains("TraceIdRatioBased"));
|
||||||
|
|
||||||
|
let sampler = build_tracer_sampler(1.0);
|
||||||
|
assert!(format!("{sampler:?}").contains("TraceIdRatioBased"));
|
||||||
|
|
||||||
|
let sampler = build_tracer_sampler(0.5);
|
||||||
|
assert!(format!("{sampler:?}").contains("TraceIdRatioBased"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_build_tracer_sampler_rejects_invalid_ratio_with_always_on() {
|
||||||
|
let sampler = build_tracer_sampler(-0.1);
|
||||||
|
assert!(format!("{sampler:?}").contains("AlwaysOn"));
|
||||||
|
|
||||||
|
let sampler = build_tracer_sampler(1.2);
|
||||||
|
assert!(format!("{sampler:?}").contains("AlwaysOn"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user