tocsin / benchmark report

What is actually worth waking someone for?

tocsin groups a log stream into patterns, asks TypeSafe's Jev about each pattern once, and routes every line to page, ticket or log. This is what it cost and how well it worked across 27.6 million lines of real supercomputer logs, in two datasets.

22.8M
lines triaged
11,812
patterns
$0.64
total judging cost
0
failed calls

Thunderbird sample, jev-1.13.0, priced at TypeSafe's published $0.042 per million input tokens.

How it works

Numbers, IPs, UUIDs, hex values and emails get masked. HTTP status codes keep their class, so GET /checkout 500 becomes GET /checkout <5xx> and never merges with a 200. Lines are then grouped with Drain, using the streaming engine from codag-drain. A pattern that repeats a million times is judged once.

Each new pattern goes to Jev in a single request carrying the paging policy and four typed questions.

The question battery, sent once per pattern
QuestionTypeWhat it asks
pageablenouldoes the policy say to page for this event?
detailnoulis this a stack frame, register dump or continuation line?
severityscore 0-3how bad is it
areachoicewhich part of the system

Code owns the decision, not the model: attention = pageable × (1 − detail). Above 0.75 it pages, above 0.5 it opens a ticket, everything else is kept as a log line. Pages reach a webhook once per pattern per cooldown, carrying the count since the last alert.

Cost and speed

Two separate things make it cheap, and they are worth keeping apart. Grouping decides how many questions get asked, and that is Drain's doing, not the model's. Choosing Jev to answer them decides what each question costs.

Every line, any model
$1,120
Once per pattern, a $3/M model
$46
Once per pattern, Jev
$0.64
22,833,750 Thunderbird lines, bars to scale. The middle bar is the same 13,080 calls and the same 15,274,299 input tokens, priced at $3 per million instead of Jev's $0.042. Nobody would run the top bar; it is there to show what grouping is worth.
Both datasets, cold runs
DatasetLinesPatternsJev callsCostAt $3/MEvery lineWall
BGL4,747,9631,1261,496$0.073$5.23$23255s
Thunderbird22,833,75011,81213,080$0.64$45.82$1,1206m 23s

Grouping runs at roughly 390k lines per second on one core of an M-series laptop. Jev answered in about 370 ms at the median and 450 ms at p95, called from India, with no failed calls in either run. Two independent cold runs routed 99.87% of BGL lines and 99.29% of Thunderbird lines the same way.

Accuracy, including the part that went badly

Both datasets ship with line level alert labels written by the administrators who ran those machines. The baseline is the rule most teams actually have: page on lines matching error and fatal keywords.

tocsin keyword rules
BGL · tocsin
0.941
BGL · keywords
0.348
Thunderbird · tocsin
0.122
Thunderbird · keywords
0.373
PR-AUC against the administrators' alert labels, higher is better. tocsin wins on the dataset it was designed against and loses on the one it had never seen.
Line level scores at the shipped threshold (page at 0.75)
DatasetRoleScorerPrecisionRecallF1PR-AUCROC-AUC
BGLdevelopmenttocsin0.9130.8130.8600.9410.995
BGLdevelopmentkeyword rules0.2541.0000.4060.3480.926
Thunderbirdheld outtocsin0.0000.0000.0000.1220.867
Thunderbirdheld outkeyword rules0.1230.9990.2200.3730.984

What happened on Thunderbird

99.7% of its alert lines come from one pattern:

kernel: <*> <*> failed, return code = -<NUM> (Fatal error (Local Catastrophic Error))

It scored 0.65, which lands in ticket, one notch below a page. The wildcards hide what actually failed, and the default policy had nothing to match on. Meanwhile the patterns it did page were these:

Top pages on Thunderbird, none of them labeled alerts
PatternAttentionLinesLabeled alerts
kernel: Out of Memory: Killed process <NUM> <*>0.907,5450
kernel: end_request: I/O error, dev sda, sector <NUM>0.896030
VFS: file-max limit <NUM> reached0.77168,2640
kernel: LustreError: ... No route to <NUM>-<IP>@vib0.8512,5240

Out of memory kills and disk I/O errors are things most on-call engineers would want to hear about. Thunderbird's administrators did not count them as alerts, and they were right for their machine. That is the finding: a public label set is one site's answer to a local question, so the policy has to be an input rather than something baked into the tool.

What was tuned where

The split matters more than the numbers, so here it is in full.

If you want to know whether this works for your logs, the answer is to label a sample of your own incidents and run tocsin eval against them. That path is the product.

Data and reproduction

scripts/fetch-loghub.sh && scripts/fetch-thunderbird-sample.sh
tocsin eval data/bgl.tsv --out results/bgl.json
tocsin eval data/tbird-sample.tsv --out results/thunderbird.json

Limits