Skip to content

feat(server): Add rejection counters and structured logging for all rejection mechanisms#364

Open
jan-auer wants to merge 1 commit intomainfrom
worktree-rejection-counters
Open

feat(server): Add rejection counters and structured logging for all rejection mechanisms#364
jan-auer wants to merge 1 commit intomainfrom
worktree-rejection-counters

Conversation

@jan-auer
Copy link
Member

@jan-auer jan-auer commented Mar 10, 2026

Before this change, only web and service concurrency rejections emitted a metric counter on rejection. Killswitches and throughput rate limits logged at DEBUG. Bandwidth rate limit rejections were completely silent.

Every rejection mechanism now emits a tracing::warn! and a metric counter on every rejected request:

  • Killswitches: server.request.killswitched counter; warn includes the full killswitch config via Debug formatting (usecase, scopes, service pattern)
  • Rate limits: server.request.rate_limited counter tagged with reason (one of bandwidth_global, bandwidth_usecase, bandwidth_scope, throughput_global, throughput_usecase, throughput_scope, throughput_rule); warn includes the reason field
  • Web concurrency: existing web.concurrency.rejected counter gains a tracing::warn!
  • Service concurrency: existing service.concurrency.rejected counter gains a tracing::warn!

The observability logic is colocated with the check itself — Killswitches::matches and RateLimiter::check emit their own counters and logs, keeping all call sites clean. A new Killswitches::find method returns the matching &Killswitch for callers that need to inspect it directly.

Closes #350
Closes FS-275

…ejection mechanisms

Before this change, only web and service concurrency rejections emitted a
metric counter. Killswitches and throughput rate limits logged at DEBUG.
Bandwidth rate limit rejections were completely silent.

Every rejection mechanism now emits a `tracing::warn!` and a metric counter:

- Killswitches: `server.request.killswitched` counter; warn includes the full
  killswitch config (usecase, scopes, service pattern) via Debug formatting
- Rate limits: `server.request.rate_limited` counter tagged with `reason`
  (one of bandwidth_global/usecase/scope, throughput_global/usecase/scope/rule);
  warn includes the reason field
- Web concurrency: existing `web.concurrency.rejected` counter + new warn
- Service concurrency: existing `service.concurrency.rejected` counter + new warn

The observability logic is colocated with the check itself — `Killswitches::matches`
and `RateLimiter::check` emit their own counters and logs, keeping call sites clean.
A new `Killswitches::find` method returns the matching `&Killswitch` for callers
that need to inspect it directly.

Co-Authored-By: Claude <noreply@anthropic.com>
@linear-code
Copy link

linear-code bot commented Mar 10, 2026

@jan-auer jan-auer marked this pull request as ready for review March 10, 2026 13:00
@jan-auer jan-auer requested a review from a team as a code owner March 10, 2026 13:00
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.

1 participant