Skip to content

blackbull.server.cap_log

blackbull.server.cap_log

Resource-cap refusal records on blackbull.caps.

Use log_cap_hit at enforcement sites. A bound CapHitCounter propagates to child tasks through context; flush suppressed-hit summaries at teardown. Threshold and interval flushes cover abnormal closes.

CapHitCounter

Per-connection state for cap-hit rate limiting.

Construct one instance per connection (typically in ConnectionActor), install it as the ambient counter for the duration of the connection via the bind context manager, and call flush once when the connection closes so a single summary record reports any suppressed hits.

Two dirty-flush triggers fire intermediate summaries even when flush is never called (e.g. RST close that skips the graceful path):

  • flush_threshold (default 100) — after this many suppressed hits on any single cap, emit and reset. Set to 0 to disable.
  • flush_interval (default 60.0 s) — an asyncio timer that emits and resets after this many seconds if any cap has suppressed hits. Set to 0 to disable.

connection_id property

Read-only access to the counter's connection id.

bind()

Context manager that installs self as the ambient counter.

Usage::

counter = CapHitCounter()
with counter.bind():
    ...                       # all log_cap_hit() in here uses *counter*
    # tasks created via asyncio.TaskGroup inherit it too

flush(*, peer=None, protocol=None, connection_id=None)

Emit one summary record per cap that had suppressed hits.

Caps with zero suppressed hits (fired exactly once, or already emitted via an intermediate summary) are omitted. Cancels the interval timer and clears all state — the counter is safe to reuse afterwards if the holder is pooled.

log_cap_hit(cap, requested, limit, *, counter=None, peer=None, scope_path=None, protocol=None, connection_id=None, advice=None)

Log a cap refusal with structured fields and operator advice.

Explicit counter and connection_id override ambient context. Without a counter, every call emits. With one, first hits emit and repeats accumulate until flush; the connection owner must flush at teardown.