Class MailAnsweringSpendTracker
- Namespace
- MailFathom.Infrastructure.Observability
- Assembly
- MailFathom.Infrastructure.dll
Holds what answering has cost in the period currently running, admits a question against it, and publishes both as instruments.
public sealed class MailAnsweringSpendTracker : IMailAnsweringSpendLedger
- Inheritance
-
MailAnsweringSpendTracker
- Implements
- Inherited Members
Remarks
The period is the fixed window PeriodStartAt(DateTimeOffset) places, held as three numbers beside the start it currently counts under. The counts are dropped whenever a call notices that the clock has moved into a later window, rather than by a timer, so an idle deployment holds no callback and nothing here schedules work. Because the window is a function of the clock rather than of when the last reset happened, an instance that answered nothing for a day is not owed the windows that passed while it was idle.
Process-local, and this is where it diverges from IEmbeddingSpendLedger, which keeps its equivalent in a table so a crash-restart loop cannot begin every period again from zero. That reasoning applies here in kind and not in degree: an embedding sweep charges inside a transaction that was committing vectors anyway, while a question opens no write of its own, so making this durable would add a database write to the path of every provider call in every run. A restart therefore begins a new window with nothing spent, and an operator who needs the stronger guarantee needs the table rather than a longer period.
A refusal is counted as well as measured, because the two questions an operator asks are opposite: the counter says how often the ceiling was reached, and the gauges say how close the deployment is to reaching it now. A ceiling that is met constantly is a ceiling to raise or a client to look at, and neither is visible from a single number.
Only the first refusal of a period is written to the log, and that bound is the point rather than tidiness: a client that keeps asking is exactly what spends a period's allowance, so a line per refusal would put the log's volume on how enthusiastic that client is. The counter carries how often it happened; the line says that it started.
Nothing recorded here is mail or derived from it. The values are a run count and two token counts, and the one tag is an outcome from a closed set of two — which is a cardinality rule as much as a privacy one, since anything per caller or per question would open a time series that grows with use.
Constructors
- MailAnsweringSpendTracker(MailAnsweringPeriodBounds, TimeProvider, ILogger<MailAnsweringSpendTracker>)
Initializes a ledger whose first period begins now, and the instruments it publishes through.
Methods
- Read()
Reads what the current period has cost so far, rolling the window over first when the clock has left it.
- RecordSpend(ChatTokenUsage)
Adds what one provider call consumed to the current period.
- TryAdmitRun()
Takes an allowance for one run, if the current period has one left.