Skip to content

feat(logging): Add configurable rate limit for logging#1464

Open
sergeymatov wants to merge 1 commit intomainfrom
pr/smatov/log-rate-limit
Open

feat(logging): Add configurable rate limit for logging#1464
sergeymatov wants to merge 1 commit intomainfrom
pr/smatov/log-rate-limit

Conversation

@sergeymatov
Copy link
Copy Markdown
Contributor

Introduce --tracing-rate-limit BURST:REPLENISH_PER_SECOND. if omitted, logging is unchanged and no throttling is applied. Initialize tracing explicitly from main() so CLI-provided throttle settings are applied before startup logs.

Copilot AI review requested due to automatic review settings April 14, 2026 12:09
@sergeymatov sergeymatov requested a review from a team as a code owner April 14, 2026 12:09
@sergeymatov sergeymatov requested review from qmonnet and removed request for a team April 14, 2026 12:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional CLI-configured tracing/logging rate limiter so lower-severity logs (info/debug/trace) can be throttled while keeping warn/error unthrottled, and ensures tracing is initialized early enough for startup logs to respect CLI settings.

Changes:

  • Add --tracing-rate-limit BURST:REPLENISH_PER_SECOND parsing + config plumbing in args.
  • Add TracingControl::init_with_rate_limit(...) and integrate tracing-throttle in tracectl.
  • Initialize tracing from dataplane::main() before emitting startup logs / applying tracing commands.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tracectl/src/lib.rs Re-export TracingRateLimitConfig from tracectl.
tracectl/src/control.rs Introduce rate-limit config + initialization path using OnceLock and tracing-throttle.
tracectl/Cargo.toml Add tracing-throttle dependency.
dataplane/src/main.rs Initialize tracing with optional rate limit before startup logs and tracing command processing.
args/src/lib.rs Add TracingRateLimit type, FromStr parser, CLI flag, and config section field.
Cargo.toml Add workspace dependency for tracing-throttle (and minor formatting change).
Cargo.lock Lockfile updates to include tracing-throttle and transitive dependency changes.

Comment thread tracectl/src/control.rs Outdated
Comment thread tracectl/src/control.rs Outdated
Comment thread args/src/lib.rs
Comment thread Cargo.toml Outdated
@sergeymatov sergeymatov force-pushed the pr/smatov/log-rate-limit branch from 10856c0 to 5404136 Compare April 14, 2026 14:01
@sergeymatov sergeymatov requested a review from Copilot April 14, 2026 14:01
@sergeymatov sergeymatov force-pushed the pr/smatov/log-rate-limit branch 3 times, most recently from d7b33f3 to 082662d Compare April 14, 2026 14:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional CLI-configurable tracing/logging rate limit and ensures tracing is initialized early in dataplane so startup logs honor the CLI settings.

Changes:

  • Add --tracing-rate-limit BURST:REPLENISH_PER_SECOND parsing and plumbing into runtime configuration.
  • Extend tracectl tracing initialization to optionally apply a throttle layer for INFO/DEBUG/TRACE (leaving WARN/ERROR unthrottled).
  • Initialize tracing from dataplane::main() before emitting startup logs.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tracectl/src/lib.rs Re-export TracingRateLimitConfig for downstream initialization.
tracectl/src/control.rs Introduce rate-limit config + OnceLock init, and wire in tracing-throttle for lower-severity logs.
tracectl/Cargo.toml Add tracing-throttle dependency.
dataplane/src/main.rs Initialize tracing earlier and pass CLI-provided rate-limit config.
args/src/lib.rs Add TracingRateLimit type, CLI flag, config propagation, and parsing tests.
Cargo.toml Add workspace dependency on tracing-throttle.
Cargo.lock Lockfile updates for new dependency (and transitive bumps).
Comments suppressed due to low confidence (1)

args/src/lib.rs:1616

confidence: 10
tags: [logic]

`args/src/lib.rs` defines `#[cfg(test)] mod tests` twice at the same module scope, which will not compile (duplicate module name). Merge the new `TracingRateLimit` tests into the existing `mod tests` block (or rename one of the modules).
#[test]
fn tracing_rate_limit_parses_valid_values() {
    let rate_limit = TracingRateLimit::from_str("10:20").unwrap();
    assert_eq!(rate_limit.burst, 10);
    assert_eq!(rate_limit.replenish_per_second, 20);
}
#[test]
fn tracing_rate_limit_rejects_missing_separator() {
    let err = TracingRateLimit::from_str("10").unwrap_err();
    assert_eq!(err, "Bad syntax: missing :");
}
#[test]
fn tracing_rate_limit_rejects_non_numeric_values() {
    let err = TracingRateLimit::from_str("abc:20").unwrap_err();
    assert!(err.starts_with("Bad burst value:"));
    let err = TracingRateLimit::from_str("10:def").unwrap_err();
    assert!(err.starts_with("Bad replenish-per-second value:"));
}
#[test]
fn tracing_rate_limit_rejects_zero_values() {
    let err = TracingRateLimit::from_str("0:20").unwrap_err();
    assert_eq!(err, "Burst must be greater than 0");
    let err = TracingRateLimit::from_str("10:0").unwrap_err();
    assert_eq!(err, "Replenish-per-second must be greater than 0");
}

}

</details>

Comment thread dataplane/src/main.rs Outdated
Comment on lines +131 to +135
if args.tracing().is_none() {
get_trace_ctl()
.set_default_level(LevelFilter::DEBUG)
.expect("Setting default loglevel failed");
}
Comment thread tracectl/src/control.rs Outdated
Comment on lines +322 to +386
Ok(policy) => match TracingRateLimitLayer::builder()
.with_policy(policy)
.with_summary_interval(Duration::from_secs(30))
.build()
{
Ok(rate_limit) => {
let throttled_fmt_layer = tracing_subscriber::fmt::layer()
.with_line_number(true)
.with_target(true)
.with_thread_ids(false)
.with_thread_names(true)
.with_level(true)
.with_filter(throttled_level_filter.and(rate_limit));
if let Err(e) = tracing_subscriber::registry()
.with(filter)
.with(unthrottled_fmt_layer)
.with(throttled_fmt_layer)
.with(tracing_error::ErrorLayer::default())
.try_init()
{
eprintln!("Failed to set global tracing subscriber: {e} !!");
}
}
Err(e) => {
eprintln!(
"Failed to create tracing throttle layer: {e}; falling back to unthrottled logging"
);
let throttled_fmt_layer = tracing_subscriber::fmt::layer()
.with_line_number(true)
.with_target(true)
.with_thread_ids(false)
.with_thread_names(true)
.with_level(true)
.with_filter(throttled_level_filter);
if let Err(e) = tracing_subscriber::registry()
.with(filter)
.with(unthrottled_fmt_layer)
.with(throttled_fmt_layer)
.with(tracing_error::ErrorLayer::default())
.try_init()
{
eprintln!("Failed to set global tracing subscriber: {e} !!");
}
}
},
Err(e) => {
eprintln!(
"Failed to create tracing throttle policy: {e}; falling back to unthrottled logging"
);
let throttled_fmt_layer = tracing_subscriber::fmt::layer()
.with_line_number(true)
.with_target(true)
.with_thread_ids(false)
.with_thread_names(true)
.with_level(true)
.with_filter(throttled_level_filter);
if let Err(e) = tracing_subscriber::registry()
.with(filter)
.with(unthrottled_fmt_layer)
.with(throttled_fmt_layer)
.with(tracing_error::ErrorLayer::default())
.try_init()
{
eprintln!("Failed to set global tracing subscriber: {e} !!");
}
Comment thread tracectl/src/control.rs
Comment on lines 453 to +463
}
pub fn init_with_rate_limit(rate_limit_config: Option<TracingRateLimitConfig>) {
let mut initialized = false;
let has_rate_limit_config = rate_limit_config.is_some();
let _ = TRACING_CTL.get_or_init(|| {
initialized = true;
TracingControl::new(rate_limit_config)
});
if has_rate_limit_config && !initialized {
warn!("TracingControl already initialized; ignoring provided rate-limit config");
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment can be ignored

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is it to write a test to cover this instead of telling copilot to go away?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(And can AI write the test with some guidance?)

@sergeymatov sergeymatov force-pushed the pr/smatov/log-rate-limit branch 6 times, most recently from 6e32425 to b83c1bc Compare April 15, 2026 09:35
Introduce --tracing-rate-limit BURST:REPLENISH_PER_SECOND.
if omitted, logging is unchanged and no throttling is applied.
Initialize tracing explicitly from main() so CLI-provided
throttle settings are applied before startup logs.

Signed-off-by: Sergey Matov <sergey.matov@githedgehog.com>
@sergeymatov sergeymatov force-pushed the pr/smatov/log-rate-limit branch from b83c1bc to d7eee76 Compare April 15, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants