Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions grafana-alertcheck/.changeset/v0.1.6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- A no-match now states that datasource-managed alert rules cannot be observed and are not supported, and the rule count names its scope (`N grafana-managed rules available`). The Grafana-managed ruler endpoint this tool queries does not return datasource-managed rules, so a bare `no rule matched` previously read as "no such rule exists".
4 changes: 2 additions & 2 deletions grafana-alertcheck/docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ Alert names take one of four forms:
| `Platform/api/HighErrorRate` | Folder + group + title (may still be ambiguous; use `uid:` for guaranteed uniqueness) |
| `uid:abc123` | Exact uid (present on both endpoints) |

Datasource-managed and recording rules are refused with a specific error. A name matching multiple rules errors listing every candidate with the copyable `Folder/Group/Title` and its `uid:` form. A no-match errors with case-insensitive substring suggestions and points at `list`. Duplicate names that resolve to the same uid collapse to one (a note, not an error).
Recording rules are refused with a specific error. Datasource-managed rules never reach resolution at all: the Grafana-managed ruler endpoint this tool queries does not return them. A no-match errors with case-insensitive substring suggestions and points at `list`, and states that datasource-managed rules cannot be observed and are not supported. A name matching multiple rules errors listing every candidate with the copyable `Folder/Group/Title` and its `uid:` form. Duplicate names that resolve to the same uid collapse to one (a note, not an error).

## Selecting alerts by labels

Expand All @@ -118,7 +118,7 @@ grafana-alertcheck check --to "$finished_at" --include-labels team=bcm --exclude

`--include-labels` takes comma-separated exact-match `key=value` pairs; a rule must carry **all** of them. `--exclude-labels` is optional and drops any rule carrying **one** of its pairs. A rule that does not carry the label is never dropped, only never included. Values cannot contain commas; `key=` matches only rules that carry the label with an empty value.

The label flags cannot be combined with `--alerts` or `--folder`, and they are refused with `--in` — the recorded log names its own alert set. A selection that matches no rules, whose matches are all excluded, or that matches a datasource-managed or recording rule exits `2`: an empty watch set must never pass.
The label flags cannot be combined with `--alerts` or `--folder`, and they are refused with `--in` — the recorded log names its own alert set. A selection that matches no rules, whose matches are all excluded, or that matches a recording rule exits `2`: an empty watch set must never pass.

## Output and exit codes

Expand Down
9 changes: 6 additions & 3 deletions grafana-alertcheck/internal/gate/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ func refuseUnsupportedKind(name string, d Definition) (Definition, error) {
}
}

// noMatchError reports a no-match with the count of rules the gate could see
// and case-insensitive substring matches as suggestions.
// noMatchError reports a no-match with the count of grafana-managed rules and
// case-insensitive substring suggestions. The trailing disclaimer covers rules
// the ruler response omits entirely, namely datasource-managed ones.
func noMatchError(defs []Definition, name, wantTitle string) error {
msg := fmt.Sprintf("no rule matched %q (%d rules available; run 'grafana-alertcheck list' to see titles)", name, len(defs))
msg := fmt.Sprintf("no rule matched %q (%d grafana-managed rules available; run 'grafana-alertcheck list' to see titles)",
name, len(defs))

needle := strings.ToLower(wantTitle)
var subs []string
Expand All @@ -189,6 +191,7 @@ func noMatchError(defs []Definition, name, wantTitle string) error {
sort.Strings(subs)
msg += fmt.Sprintf("; did you mean: %s", strings.Join(subs, ", "))
}
msg += "; datasource-managed alert rules cannot be observed and are not supported"
return fmt.Errorf("%s", msg)
}

Expand Down
3 changes: 2 additions & 1 deletion grafana-alertcheck/internal/gate/resolve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func TestResolve_NoMatch(t *testing.T) {
require.Error(t, err)
require.Contains(t, err.Error(), "no rule matched")
require.Contains(t, err.Error(), "list")
require.Contains(t, err.Error(), "datasource-managed alert rules cannot be observed")
}

func TestResolve_NoMatchSubstringSuggestion(t *testing.T) {
Expand Down Expand Up @@ -123,7 +124,7 @@ func TestResolve_UnsupportedKindsExcludedFromNoMatchSurfaces(t *testing.T) {
_, _, err = Resolve(combined, []string{"Example"}, "")
require.Error(t, err, "want a no-match error for a name matching no title exactly")

wantCount := fmt.Sprintf("(%d rules available", len(supported))
wantCount := fmt.Sprintf("(%d grafana-managed rules available", len(supported))
require.Contains(t, err.Error(), wantCount)
require.NotContains(t, err.Error(), "ExampleTargetDown")
require.NotContains(t, err.Error(), "example:recorded_metric:rate5m")
Expand Down
Loading