# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence. """What one command cost, split into the bot's own time and everybody else's. ``DOCS-latency.md`` found 72% of a ``!kot`` reply inside the signal-cli container and most of the rest on Commons -- none of it this repository's code. So "the bot is slow" needs a number that excludes both, or every measurement is a measurement of somebody else. ``own_ms`` is that number: the wall clock from the frame being read to the handler returning, minus every upstream request and every send. It is what ``/_selftest`` reports and what ``tool/latency.py`` holds to a budget. """ from __future__ import annotations from dataclasses import dataclass from typing import Final # The bot's own share of one reply, at the 95th percentile. The whole # reply is bounded by the container, and is reported, not budgeted. OWN_BUDGET_MS: Final = 100 @dataclass(frozen=True, slots=True) class Served: """The timings of one command attempt, in milliseconds.""" command: str outcome: str # Frame read to a slot free: the queue behind other people's frames. queue_ms: int # Slot to handler: parse, scope, tally, resolve, and this person's lock. dispatch_ms: int # The handler, wall clock, everything included. handler_ms: int # Of which: outbound sends to signal-cli... send_ms: int # ...and requests to Commons, the cat API, and the like. upstream_ms: int @property def own_ms(self) -> int: """Time spent in this repository's code, and nowhere else.""" return self.queue_ms + self.dispatch_ms + self.handler_ms - self.send_ms - self.upstream_ms def as_dict(self) -> dict[str, int | str]: """The shape ``/_selftest`` answers with.""" return { "command": self.command, "outcome": self.outcome, "queue_ms": self.queue_ms, "dispatch_ms": self.dispatch_ms, "handler_ms": self.handler_ms, "send_ms": self.send_ms, "upstream_ms": self.upstream_ms, "own_ms": self.own_ms, }