Repository navigation
Allow applications to provide their own alert rules #8100
Description
NethServer 8 applications can provide monitoring data and Grafana dashboards, but they cannot provide their own Prometheus alert rules through a supported integration.
Application-specific rules must currently be maintained in the Metrics module or added manually to generated configuration files. This ties application changes to Metrics updates, and manual changes can be lost when configuration files are regenerated.
Applications should be able to provide and maintain the alert rules needed to monitor their own services.
Proposed solution
Allow each application instance to publish its alert rules and notify Metrics when they change. Metrics should load these rules into Prometheus and automatically apply additions, updates, and removals. A published source may contain one alert or a grouped rule file.
The integration should meet these requirements:
- Each application's rules evaluate only monitoring data belonging to that instance.
- Invalid rule content does not interrupt monitoring or affect rules from other applications. If an update is invalid, the previous valid rules remain active.
- Removed rules are cleaned up without affecting other applications.
- Each published source is validated and replaces its generated file in one operation. Updates to different sources are independent.
- Metrics checks that Prometheus has loaded the resulting configuration successfully.
- Existing built-in rules, custom alerts, and alert delivery continue to work.
If Prometheus rejects a reload and verification does not recover, Metrics reports an error and leaves the running service in place. Reload-command failures or inconclusive verification use a checked restart fallback.
If the infrastructure needed to prepare application rules fails, Metrics logs a warning and lets monitoring start or reload with the rules available at that point. Some application rules may be stale or incomplete. Files already replaced are not rolled back.
Alternative solutions
Maintain all application-specific rules in Metrics. This requires updating Metrics whenever an application needs to change its rules.
Use the existing custom_alerts mechanism or edit generated configuration files manually. Custom alerts are managed locally by Metrics and do not provide an integration for other applications. Manual file changes can be overwritten during configuration regeneration.
Additional context
Applications would publish rules through Redis, as they already do for other monitoring resources. Metrics would identify the publishing instance from its Redis key and enforce that identity when processing monitoring data, rules, and alerts.
Application-provided rules would be managed separately from built-in rules and existing custom alerts. Prometheus sends alerts directly to the local Alertmanager and also to my Mimir when the enterprise subscription provides the required settings. Critical email notifications remain handled by the local Alertmanager when configured.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsIn Progress
Activity
[-]Allow modules to provision alert rules[/-][+]Allow applications to provide their own alert rules[/+]Amygos commentedon Oct 13, 2026
Manual QA: module-provided alert rules
The examples target the ns8-traefik module instance, normally
traefik1. Reuse the same rules throughout the sequence.Prepare the QA session
Use a designated QA cluster upgraded to the candidate Metrics version, with Grafana enabled. Record the previous and candidate versions and image digest. Before adding fixtures, confirm that existing Grafana dashboards, built-in rules, and any existing custom alerts still work after the upgrade.
Run the commands as root on the cluster leader in the same Bash session. List the installed modules and set
QA_METRICSto the actual Metrics instance ID. The assignment below usesmetrics1as an example. Discover the cluster's default ns8-traefik instance rather than assuming its ID.Confirm both module IDs before continuing. If Traefik discovery returns an empty value or
(nil), resolve the actual instance ID first.In Grafana Explore, select the local Prometheus data source and verify that this query returns samples, substituting the discovered Traefik ID:
The second-module isolation check also requires another test module with scraped
upseries. SetQA_OTHERto its actual ID when reaching that check.Use Grafana's Alert rules view with the local Prometheus data source to observe the rules. Prometheus-managed rules are read-only there, so all changes below use Redis and the module event. See the Grafana Prometheus alerting documentation.
Keep Traefik running because it also provides access to Grafana. The fixtures use real
upselectors with deliberately false comparisons. Changing the comparison makes an alert fire without stopping the application. Metrics adds the publishing instance'smodule_idmatcher and alert label automatically.Each Redis hash field holds one complete YAML document. One file below contains a single rule, and the other contains two grouped rules. The unique run marker keeps their names and Redis fields separate from existing configuration.
Create the rule fixtures
Single-rule source: R1
Grouped source: R2 and R3
The
upmetric is non-negative, so these rules start non-firing. A comparison of>= 0fires as long as the publishing module has scrapedupseries.Define this convenience function once in the same shell:
Its arguments are publisher module ID, Redis field name, and YAML file.
HSETstores the document andPUBLISHannounces the change. AnHSETreply of0is normal when replacing an existing field. Redis replies do not prove that Prometheus loaded the rules, so use the observations below to judge each case. Allow up to three minutes for reload, evaluation, and Grafana refresh before investigating an unexpected result.Test 1: publish the three rules
Publish the two source files:
Filter Grafana's rule list by the run marker printed during preparation.
Expected: R1, R2, and R3 appear. R1 has its own generated group, while R2 and R3 share a group. Their names retain their spelling, and their effective expressions and labels identify the actual ns8-traefik instance. All three are initially non-firing, and existing monitoring remains available. No manual Prometheus or Grafana restart is needed.
Test 2: edit existing rules
Edit
single.yml, changing its description to version 2. Ingroup.yml, change only R2's description to version 2. Keep the expressions non-firing until Test 4 and preserve the files as the current valid versions.Republish using the same Redis fields:
Expected: the new descriptions appear automatically without duplicate rules. R3 remains at version 1, and existing monitoring continues working.
Test 3: reject a bad update and recover
Add a new source containing invalid YAML:
redis-cli HSET \ "module/$QA_TRAEFIK/metrics_alert_rules" \ "$QA_BAD" 'groups: [' redis-cli PUBLISH \ "module/$QA_TRAEFIK/event/metrics-alert-rules-changed" '{}'Expected: no additional rule appears, and the three valid rules remain.
Make a separate invalid copy of the current grouped source:
In
group-invalid.yml, change R2's expression toexpr: 'up{'and R3's description toThis change must not appear. Publish the invalid copy under the existing group field:While the group is invalid, change R1's description in the valid
single.ymlto version 3 and publish it:Expected: both grouped rules retain their previous valid versions. R3's proposed description does not appear, while R1's version 3 update does. The module journal identifies the rejected sources, and monitoring remains available.
Recover by editing the valid
group.ymlso R2's description is version 3, keeping both expressions valid and R3's description at version 1. Remove the new malformed source and republish the corrected group:redis-cli HDEL \ "module/$QA_TRAEFIK/metrics_alert_rules" "$QA_BAD" qa_publish "$QA_TRAEFIK" "$QA_GROUP" "$QA_DIR/group.yml"Expected: R2 now shows version 3 and R3 remains at version 1. The visible revision proves that corrected updates load again.
Test 4: raise and resolve alerts independently
Create a firing version of R1 while keeping
single.ymlas the valid, non-firing version:For the isolation check, set
QA_OTHERto another monitored NS8 module's actual ID. Enter it in the same interactive shell:Verify in Grafana Explore that
up{module_id="<that ID>"}returns samples and that it is a different module fromQA_TRAEFIK. The same YAML file can be reused because Metrics scopes it to the publisher's own series.Run the reference publication only when that prerequisite is met:
Raise the Traefik alert:
Expected: both modules have firing alerts with the same name and distinct
module_idlabels. R2 and R3 remain non-firing.Resolve only Traefik's alert:
Expected: Traefik's alert becomes non-firing while the reference alert remains firing. The rule definitions stay listed after recovery.
If the reference rule was published, resolve it too:
If the second module is unavailable, record the Traefik firing/recovery observation and mark the isolation part as BLOCKED, rather than passing the complete case.
When notification delivery is included in the QA run, check actual firing and recovery receipt at the configured test destination. For email, set
severity: criticalin the firing copy before publication and use a configured QA recipient. The default warning fixtures do not exercise critical-alert email delivery. Allow the configured notification intervals. Record delivery as untested if no suitable receiver is available.Test 5: verify persistence after restart
With all sources valid, restart Prometheus once:
runagent -m "$QA_METRICS" \ systemctl --user restart prometheus.serviceWait for readiness and refresh Grafana without republishing any rules.
Expected: the three Traefik rules and, if published, the reference rule load automatically with their latest valid definitions. Existing built-in and custom rules remain available. This intentional restart is separate from the earlier publication and editing checks.
Test 6: remove rules and clean up
First, remove R2's complete rule entry from
group.yml, leaving R3 in the group, and republish:Expected: only R2 disappears. R1, R3, and the reference module's rule remain.
Withdraw the Traefik QA sources:
redis-cli HDEL \ "module/$QA_TRAEFIK/metrics_alert_rules" \ "$QA_SINGLE" "$QA_GROUP" "$QA_BAD" redis-cli PUBLISH \ "module/$QA_TRAEFIK/event/metrics-alert-rules-changed" '{}'Expected: no Traefik QA rule definitions remain, while the reference rule and existing monitoring are unaffected.
If the reference module was selected, remove only its QA field:
Confirm that no rule carrying this run marker remains in Grafana, that any QA alerts have cleared, and that the original dashboards and rules still work. Use these withdrawal commands even when an earlier case fails. Remove only the QA fields, not the complete Redis hashes. Retain the local files in
QA_DIRuntil evidence has been collected, then remove that run's temporary directory.