Skip to content

Add the Custom-rules alert notebook template (#4223) - #4433

Merged
erikdarlingdata merged 2 commits into
devfrom
fix/4223-notebook-custom-rules
Sep 26, 2026
Merged

erikdarlingdata merged 2 commits into
devfrom
fix/4223-notebook-custom-rules

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Refs #4223.

Why

A custom alert rule fires as Custom:<id>, and until now that metric name fell through to the mechanical notebook conversion — no chart of the rule's own measure, no threshold or band shown against the window that fired it.

What changes

Registers a Custom: prefix row (AuthoredContextKind.CustomRule) in the endpoint's authored-template table, which was empty. Adds a new file, AlertNotebookEndpoint.Templates.CustomRules.cs, with the template's cell builder.

Cell Contents
Header Standard header (metric, server, incident info)
Status Standard status
Panel (normal path) One composed panel: the SAME source/measure-or-ratio/aggregate/filters as the rule's stored plan, forced to timeBucket: "hour" (the rule's own plan is always Scalar), absolute range over the alert window, and up to 4 thresholds reference-line values carrying the rule's warn/critical (scalar op) or lower/upper bound plus optional critical band (range op)
Markdown note (deleted rule) "This custom rule no longer exists; it may have been deleted after this alert fired." — never an error, per #2710
Markdown note (unparseable definition) "This custom rule's definition could not be read; it may reference a measure that no longer exists." — never a throw

The panel's thresholds key is the same render-only reference-line array a composed panel already accepts; there is no separate "band" key on that schema, so a range rule's bounds ride in that same array (checked against ComposeSpec and DarlingWebEndpoints.ValidateNotebookDefinition).

Test plan

New file Darling/Darling.Tests/AlertNotebookTemplateCustomRulesTests.cs, 11 pins:

  • Exact-vs-prefix routing (Custom:42 routes to authored/custom-rule; an exact-name metric still wins; Custom with no colon stays mechanical).
  • A scalar rule (gt, warn 80 / critical 95): panel's source/measure/aggregate identical to the stored plan, timeBucket set, thresholds [80, 95], and it passes ValidateNotebookDefinition.
  • A range rule (between, 10/90): thresholds [10, 90], and it passes ValidateNotebookDefinition.
  • A deleted rule (CustomRuleMissing = true): note cell, 3 cells total (header/status/note), passes validation.
  • An unparseable definition (bad JSON, and separately a definition referencing a measure that no longer exists): note cell, no throw.
  • One fabricated-context theory covering the Custom: prefix family, since the shared AllAuthoredMetrics theories in AlertNotebookAuthoredTemplateTests only walk the exact-name table.

Run results (this Mac, in-process xunit v3 runner, Microsoft.WindowsDesktop.App framework entry stripped from the runtimeconfig per the repo's macOS test recipe):

  • AlertNotebookTemplateCustomRulesTests: 11/11 pass.
  • AlertNotebookAuthoredTemplateTests: 128/128 pass.
  • AlertNotebookEndpointTests: 29/29 pass.
  • DocCommentHygieneTests: 77/77 pass.
  • AlertNotebookAuthoredContextTests: 26/26 on a live rig. Its ProductionPrefixTable_IsEmptyInThisStep became ProductionPrefixTable_HoldsExactlyTheRegisteredContextFamilies, which pins the single Custom: / CustomRule row this PR registers.

RED proven: copied the new test file onto pre-fix origin/dev (ef7e75df4) in a detached worktree, built clean (0/0), ran the same class: 9 of 11 fail (the two routing negatives that don't touch Custom: still pass), because s_authoredPrefixTemplates was empty there — ResolveAuthored("Custom:42") returned null.

Both Darling.Tests and Lite.Tests build 0 warnings-as-errors-relevant/0 errors (Lite.Tests is build-only here; it targets net10.0-windows and cannot run here).

CHANGELOG entry

SECTION: Added
ENTRY:

An alert fired by a custom rule (Custom:<id>) now opens an authored
notebook: header, status, and one composed panel built from the
rule's own plan (same source/measure/filters/aggregate), forced into
time-bucket mode over the alert window, with the rule's threshold
or band carried as reference-line values. A deleted rule or a
definition that no longer parses degrades to a note, never an error.

Refs #4223.
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 26, 2026 15:57
@erikdarlingdata
erikdarlingdata merged commit e0232a4 into dev Sep 26, 2026
17 of 20 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4223-notebook-custom-rules branch September 26, 2026 15:57
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