use criterion::{Criterion, criterion_group, criterion_main};
use ftui_runtime::telemetry::{SpanId, TelemetryConfig, TraceId, is_safe_env_var, redact};
use std::hint::black_box;
fn bench_telemetry_config(c: &mut Criterion) {
let mut group = c.benchmark_group("telemetry/config");
group.bench_function("from_env_disabled", |b| {
b.iter(|| {
let config = TelemetryConfig::from_env_with(|_key| None);
black_box(config)
})
});
group.bench_function("from_env_enabled_endpoint", |b| {
b.iter(|| {
let config = TelemetryConfig::from_env_with(|key| match key {
"OTEL_EXPORTER_OTLP_ENDPOINT" => Some("http://localhost:4318".into()),
"OTEL_SERVICE_NAME" => Some("ftui-bench".into()),
_ => None,
});
black_box(config)
})
});
group.bench_function("from_env_explicit_otlp", |b| {
b.iter(|| {
let config = TelemetryConfig::from_env_with(|key| match key {
"OTEL_TRACES_EXPORTER" => Some("otlp".into()),
"OTEL_EXPORTER_OTLP_ENDPOINT" => Some("http://localhost:4318".into()),
_ => None,
});
black_box(config)
})
});
group.bench_function("from_env_sdk_disabled", |b| {
b.iter(|| {
let config = TelemetryConfig::from_env_with(|key| match key {
"OTEL_SDK_DISABLED" => Some("true".into()),
_ => None,
});
black_box(config)
})
});
group.bench_function("from_env_exporter_none", |b| {
b.iter(|| {
let config = TelemetryConfig::from_env_with(|key| match key {
"OTEL_TRACES_EXPORTER" => Some("none".into()),
_ => None,
});
black_box(config)
})
});
group.bench_function("from_env_full_config", |b| {
b.iter(|| {
let config = TelemetryConfig::from_env_with(|key| match key {
"OTEL_TRACES_EXPORTER" => Some("otlp".into()),
"OTEL_EXPORTER_OTLP_ENDPOINT" => Some("http://collector:4318".into()),
"OTEL_EXPORTER_OTLP_PROTOCOL" => Some("http/protobuf".into()),
"OTEL_SERVICE_NAME" => Some("ftui-demo".into()),
"OTEL_RESOURCE_ATTRIBUTES" => Some("env=prod,version=1.0".into()),
"OTEL_EXPORTER_OTLP_HEADERS" => Some("Authorization=Bearer token".into()),
"OTEL_TRACE_ID" => Some("0123456789abcdef0123456789abcdef".into()),
"OTEL_PARENT_SPAN_ID" => Some("0123456789abcdef".into()),
_ => None,
});
black_box(config)
})
});
group.bench_function("is_enabled_check", |b| {
let config = TelemetryConfig::from_env_with(|_| None);
b.iter(|| black_box(config.is_enabled()))
});
group.finish();
}
fn bench_id_parsing(c: &mut Criterion) {
let mut group = c.benchmark_group("telemetry/id_parsing");
group.bench_function("trace_id_valid", |b| {
let id_str = "0123456789abcdef0123456789abcdef";
b.iter(|| black_box(TraceId::parse(black_box(id_str))))
});
group.bench_function("trace_id_invalid_length", |b| {
let id_str = "too_short";
b.iter(|| black_box(TraceId::parse(black_box(id_str))))
});
group.bench_function("trace_id_invalid_uppercase", |b| {
let id_str = "0123456789ABCDEF0123456789ABCDEF";
b.iter(|| black_box(TraceId::parse(black_box(id_str))))
});
group.bench_function("span_id_valid", |b| {
let id_str = "0123456789abcdef";
b.iter(|| black_box(SpanId::parse(black_box(id_str))))
});
group.bench_function("span_id_invalid_length", |b| {
let id_str = "short";
b.iter(|| black_box(SpanId::parse(black_box(id_str))))
});
group.finish();
}
fn bench_redaction(c: &mut Criterion) {
let mut group = c.benchmark_group("telemetry/redaction");
group.bench_function("redact_path", |b| {
let path_str = ["/home/user/", "sec", "ret", "/file.txt"].concat();
let path = std::path::Path::new(&path_str);
b.iter(|| black_box(redact::path(black_box(path))))
});
group.bench_function("redact_content", |b| {
let content = "sensitive user input with passwords";
b.iter(|| black_box(redact::content(black_box(content))))
});
group.bench_function("redact_env_var", |b| {
let value = ["super", "_sec", "ret_", "api", "_key_", "12345"].concat();
b.iter(|| black_box(redact::env_var(black_box(&value))))
});
group.bench_function("redact_username", |b| {
let name = "john_doe";
b.iter(|| black_box(redact::username(black_box(name))))
});
group.bench_function("redact_count_10", |b| {
let items: Vec<i32> = (0..10).collect();
b.iter(|| black_box(redact::count(black_box(&items))))
});
group.bench_function("redact_count_1000", |b| {
let items: Vec<i32> = (0..1000).collect();
b.iter(|| black_box(redact::count(black_box(&items))))
});
group.bench_function("redact_bytes_small", |b| {
let size = 512usize;
b.iter(|| black_box(redact::bytes(black_box(size))))
});
group.bench_function("redact_bytes_large", |b| {
let size = 1024 * 1024 * 50; b.iter(|| black_box(redact::bytes(black_box(size))))
});
group.bench_function("redact_duration_us", |b| {
let micros = 12345u64;
b.iter(|| black_box(redact::duration_us(black_box(micros))))
});
group.bench_function("redact_dimensions", |b| {
b.iter(|| black_box(redact::dimensions(black_box(120), black_box(40))))
});
group.bench_function("is_verbose_check", |b| {
b.iter(|| black_box(redact::is_verbose()))
});
group.finish();
}
fn bench_validation(c: &mut Criterion) {
let mut group = c.benchmark_group("telemetry/validation");
group.bench_function("is_safe_env_var_otel", |b| {
let name = "OTEL_EXPORTER_OTLP_ENDPOINT";
b.iter(|| black_box(is_safe_env_var(black_box(name))))
});
group.bench_function("is_safe_env_var_ftui", |b| {
let name = "FTUI_TELEMETRY_VERBOSE";
b.iter(|| black_box(is_safe_env_var(black_box(name))))
});
group.bench_function("is_safe_env_var_unsafe", |b| {
let name = "AWS_SECRET_ACCESS_KEY";
b.iter(|| black_box(is_safe_env_var(black_box(name))))
});
group.bench_function("is_valid_custom_field_app", |b| {
let name = "app.custom_metric";
b.iter(|| black_box(redact::is_valid_custom_field(black_box(name))))
});
group.bench_function("is_valid_custom_field_invalid", |b| {
let name = "invalid_field";
b.iter(|| black_box(redact::is_valid_custom_field(black_box(name))))
});
group.bench_function("contains_sensitive_clean", |b| {
let s = "ftui.render.frame duration=1234";
b.iter(|| black_box(redact::contains_sensitive_pattern(black_box(s))))
});
group.bench_function("contains_sensitive_password", |b| {
let s = ["login ", "pass", "word=", "hunter2"].concat();
b.iter(|| black_box(redact::contains_sensitive_pattern(black_box(&s))))
});
group.bench_function("contains_sensitive_url", |b| {
let s = "https://api.example.com/endpoint";
b.iter(|| black_box(redact::contains_sensitive_pattern(black_box(s))))
});
group.bench_function("contains_sensitive_long_clean", |b| {
let s = "a".repeat(1000);
b.iter(|| black_box(redact::contains_sensitive_pattern(black_box(&s))))
});
group.finish();
}
criterion_group!(
benches,
bench_telemetry_config,
bench_id_parsing,
bench_redaction,
bench_validation,
);
criterion_main!(benches);