Same shape as #234, one level over, and with worse consequences.
When maxReportsPerMinute bites, the pipeline writes a line saying how many reports it threw away:
if (storm.action() == StormLimiter.Action.STORM_LINE) {
writer.append(renderer.stormLine(storm.suppressed(), stormLimiter.maxPerWindow()));
writer.append and nothing else. With emitReportsToLogger=true the report blocks reach stacktale.reports and the storm line does not, so somebody watching stdout sees a couple of reports and no sign that six more were dropped. Silence that looks like health is worse than a missing count.
Measured: maxReportsPerMinute=2, eight distinct errors.
file ━ storm: 1 report(s) suppressed (rate limit 2/min) ━
━ storm: 5 report(s) suppressed (rate limit 2/min) ━
logger 2 events, both report blocks
0 storm events
close() has the same call again, for the count still outstanding at shutdown, and it is the same story there.
What to change
Emit the storm line the way #234 has reports and summaries emitted — if (settings.emitReportsToLogger()) host.emitReport(...), after the append and after stormLimiter.confirmStormLine, so a shipper that throws cannot clear a count that never shipped.
Then the README's emitReportsToLogger row has to say what now travels, since it is about to be right for the third time.
Wait for #237 before starting: it changes the arm directly above this one and you would be rebasing onto it.
The trap in writing the test
Eight new RuntimeException(...) thrown from the same line of a test method are one error as far as stacktale is concerned — the fingerprint comes from the culprit frame, not the message — so dedup answers and the rate limit never gets a turn. That is what my first probe did, and it produced a file with no storm line at all and no clue why.
Give each one its own frame:
e.setStackTrace(new StackTraceElement[]{
new StackTraceElement("com.acme.Service" + i, "call", "Service" + i + ".java", 10 + i),
});
StacktaleAppenderIntegrationTest has the fixture for attaching a listener to stacktale.reports.
How to check you got it right
- Delete the emission line again and watch the test fail on the storm event, not just on a count.
- Assert the event's text, not only that a second event arrived: an event carrying a report block would satisfy a count-only assertion and prove nothing.
- No golden file changes — this is what reaches the logger, not what is written to the file.
Say the word here and it's yours.
Same shape as #234, one level over, and with worse consequences.
When
maxReportsPerMinutebites, the pipeline writes a line saying how many reports it threw away:writer.appendand nothing else. WithemitReportsToLogger=truethe report blocks reachstacktale.reportsand the storm line does not, so somebody watching stdout sees a couple of reports and no sign that six more were dropped. Silence that looks like health is worse than a missing count.Measured:
maxReportsPerMinute=2, eight distinct errors.close()has the same call again, for the count still outstanding at shutdown, and it is the same story there.What to change
Emit the storm line the way #234 has reports and summaries emitted —
if (settings.emitReportsToLogger()) host.emitReport(...), after the append and afterstormLimiter.confirmStormLine, so a shipper that throws cannot clear a count that never shipped.Then the README's
emitReportsToLoggerrow has to say what now travels, since it is about to be right for the third time.Wait for #237 before starting: it changes the arm directly above this one and you would be rebasing onto it.
The trap in writing the test
Eight
new RuntimeException(...)thrown from the same line of a test method are one error as far as stacktale is concerned — the fingerprint comes from the culprit frame, not the message — so dedup answers and the rate limit never gets a turn. That is what my first probe did, and it produced a file with no storm line at all and no clue why.Give each one its own frame:
StacktaleAppenderIntegrationTesthas the fixture for attaching a listener tostacktale.reports.How to check you got it right
Say the word here and it's yours.