Skip to content

Report runtime status so Cockpit can show what ACARSCOT is hearing - #1

Merged
ampledata merged 1 commit into
mainfrom
feat/status-surface
Aug 1, 2026
Merged

Report runtime status so Cockpit can show what ACARSCOT is hearing#1
ampledata merged 1 commit into
mainfrom
feat/status-surface

Conversation

@ampledata

Copy link
Copy Markdown
Contributor

The worker already counted received messages, positionless messages and emitted events. Those numbers went nowhere except a log line every hundredth message, so the only way to answer "is this thing working" was to read the journal.

This writes pytak's StatusWriter surface (snstac/pytak#107) to /run/acarscot/status.json, which the Cockpit plugin renders as a decode feed, rate, trend and health. Systemd already gives us RuntimeDirectory=acarscot, so no packaging change is needed.

Every message is recorded, not just the plotted ones

This matters more for ACARS than for any other gateway we run: 1829 of 1841 messages in a measured San Francisco capture carried no position. A feed showing only plotted aircraft would sit empty on a receiver working perfectly — which an operator reads as a fault.

The placed flag distinguishes "heard it, couldn't place it" from "put it on the map" without hiding either.

Startup write + 5s heartbeat

  • Without the startup write, a quiet band leaves the UI reporting "no status from this gateway" — indistinguishable from a gateway that failed to start — for minutes.
  • Without the heartbeat, silence on the band renders as a wedged service, because the UI judges freshness by whether the file keeps changing.

Graceful, visible degradation

A pytak without StatusWriter (anything before 7.4.0) degrades to a no-op rather than failing to import. Taking the gateway down over its telemetry helper would be exactly backwards.

The degradation is visible: with nothing writing the file, the plugin says so explicitly rather than rendering an empty feed as though the band were quiet. The requirement floor stays at pytak >= 7.3.0 for that reason.

Tests

Environment Result
pytak with StatusWriter 43 passed
pytak 7.3.14 (installed) 36 passed, 7 skipped

Both deployment states covered. Two things worth recording about the tests:

  • I first wrote these as bare async def tests. pytest-asyncio isn't installed, so pytest skipped all four while still counting them in the pass total — four tests that couldn't fail. They now drive the coroutine with asyncio.run().
  • test_rate_limiting_means_the_file_can_lag_briefly pins the deliberate 1s write rate limit, so nobody later "fixes" the lag into a per-message write and makes a busy gateway spend its time serialising JSON.

🤖 Generated with Claude Code

https://claude.ai/code/session_0197da7dhvcPoHxYKamrYqyM

The worker already counted received messages, positionless messages and
emitted events. Those numbers went nowhere except a log line every hundredth
message, so the only way to answer "is this thing working" was to read the
journal.

Writes pytak's StatusWriter surface to /run/acarscot/status.json, which the
Cockpit plugin renders as a decode feed, rate, trend and health. Systemd
already gives us RuntimeDirectory=acarscot, so no packaging change is needed.

EVERY message with a tail is recorded, not just the ones that place a marker.
This matters more for ACARS than for any other gateway we run: 1829 of 1841
messages in a measured San Francisco capture carried no position. A feed
showing only plotted aircraft would sit empty on a receiver that is working
perfectly, which an operator reads as a fault. The `placed` flag distinguishes
"heard it, could not place it" from "put it on the map" without hiding either.

The run loop now writes on a 5s heartbeat and once at startup before any
traffic. Without the startup write, a quiet band would leave the UI reporting
"no status from this gateway" -- indistinguishable from a gateway that failed
to start -- for minutes. Without the heartbeat, silence on the band would
render as a wedged service, because the UI judges freshness by whether the
file keeps changing.

A pytak without StatusWriter (anything before 7.4.0) degrades to a no-op
rather than failing to import. Taking the gateway down over its telemetry
helper would be exactly backwards, and the degradation is visible: with
nothing writing the file, the plugin says so explicitly instead of rendering
an empty feed as though the band were quiet. The requirement floor stays at
7.3.0 for that reason.

Tests: 43 pass against a pytak with StatusWriter; 36 pass and 7 skip against
the 7.3.14 currently installed, so both deployment states are covered.

Two things worth recording about the tests themselves:

  * I first wrote these as bare `async def` tests. pytest-asyncio is not
    installed, so pytest SKIPPED all four while still counting them as passing
    -- four tests that could not fail. They now drive the coroutine with
    asyncio.run().

  * test_rate_limiting_means_the_file_can_lag_briefly pins the deliberate 1s
    write rate limit, so nobody later "fixes" the lag into a per-message write
    and makes a busy gateway spend its time serialising JSON.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197da7dhvcPoHxYKamrYqyM
@ampledata
ampledata merged commit fff72fd into main Aug 1, 2026
2 checks passed
@ampledata
ampledata deleted the feat/status-surface branch August 1, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant