Mediabot v3 continues its 3.4 development cycle with a new observability round for the external script bridge.
The bridge was already capable of running commands, reacting to channel events, carrying route-specific configuration and scheduling delayed callbacks.
This pass makes that activity visible.
Prometheus can now count it.
Grafana can display it.
A new reference script shows how an event, a timer and per-route configuration work together in one practical example.
The script bridge now exposes four Prometheus metric families:
mediabot_scriptbridge_runs_total
mediabot_scriptbridge_events_total
mediabot_scriptbridge_timers_total
mediabot_scriptbridge_pending_timers
Together, they answer the questions an operator actually asks:
The metric labels are deliberately bounded.
Event names come from the bridge whitelist, and unknown values are grouped safely instead of becoming attacker-controlled Prometheus labels.
If the global Metrics system is unavailable, the bridge continues exactly as before. Observability remains best-effort and must never become a new runtime dependency.
In Hogwarts terms: the clock records every spell, but the castle does not stop when the clockmaker takes the day off. 🕰️
A ready-to-import Grafana dashboard now ships with Mediabot:
contrib/grafana/grafana_mediabot_scriptbridge_v1.json
It includes panels for:
The dashboard uses the existing DS_PROMETHEUS variable and does not hard-code a datasource UID.
It is also tested against the code.
Every metric referenced by the dashboard must exist in the plugin, and every script-bridge metric declared by the plugin must appear somewhere in the dashboard.
That means a future metric rename should break CI before it breaks a production dashboard on a Sunday evening.
A proper Trophy Room should display real trophies, not painted cardboard. 🏆
The final review caught several edge cases that mattered precisely because this is monitoring code.
The pending-timer gauge is now initialized to zero when the plugin registers, so a quiet bot reports 0 instead of ambiguous No data.
When an expired timer releases its slot, the gauge is updated immediately—even when the delayed callback is skipped because the plugin changed mode, a runner disappeared or the callback failed.
Incomplete event contexts and unavailable runners are also counted under the bounded other outcome instead of silently disappearing from Prometheus.
The timer metric description now lists only outcomes that are actually emitted:
armed
delivered
cancelled
And the Grafana timer panel no longer mixes a per-second counter rate with an absolute pending-timer gauge on the same axis.
The Great Clock now tells the truth even when the corridors are dark. 🛡️
A new reference script combines three major bridge features in one example:
plugins/scripts/examples/topicreminder.pl
It can be routed as an alternative handler for topic events:
EVENTS=topic=examples/topicreminder.pl
CONFIG_topic=remind_after=900
When the channel topic changes, the script stays silent and arms a timer.
When the timer expires, it posts a reminder containing the original topic and the nick that set it:
topic reminder: <topic> (set by <nick>)
The delayed callback receives the original event data and the route configuration snapshot captured when the timer was armed.
A cleared topic does not create a reminder.
The example deliberately teaches an important timer rule.
The timer name is derived from the channel, so only one topic reminder can be pending for that channel.
If another topic change arrives while the first reminder is still armed, the second timer request is rejected and the original reminder remains intact.
The final hardening also adds a stable digest suffix to the readable timer name.
That prevents two channels that sanitize to the same text—or two long channel names that differ only after truncation—from accidentally sharing a timer slot.
The Pensieve keeps one memory per room, but it no longer confuses two rooms with similar names. 🧠
The cookbook and example contracts continue to enforce the rule established throughout the plugin arc:
documented → shipped
shipped → documented
Adding topicreminder.pl required the cookbook to mention it and update the real example count.
The new example is therefore not just dropped into a directory. Its behavior, limitations and relationships with timers, events and configuration are tested.
The Claude rounds completed with:
10610/10610 tests passed — Prometheus metrics
10636/10636 tests passed — Grafana dashboard
10660/10660 tests passed — topicreminder example
The final review adds dedicated regression coverage for:
No database schema change.
No mandatory live configuration change.
No additional Metrics dependency for installations that do not enable it.
This round gives the external script bridge a proper observability layer:
topicreminder.pl demonstrates events, timers and route config together;Mediabot’s script bridge no longer performs its magic behind a closed curtain.
The Great Clock counts it, the Trophy Room displays it, and the Pensieve remembers exactly what happened in each channel. ⏳📊🧠🪄
You must be logged in to reply.