Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4b01190
issues: classify each Issue by symptom category + group
nadaverell May 27, 2026
dbe6995
issues: resolve owner + deterministic grouping identity (Phase 2a)
nadaverell May 27, 2026
acf930a
issues: fold flat rows into the grouped issue model (Phase 2b)
nadaverell May 27, 2026
a74d76c
k8s-ui: shared IssuesView — grouped live-issue triage queue
nadaverell May 28, 2026
cad50c6
k8s-ui(issues): group/namespace optional to match omitempty wire
nadaverell May 29, 2026
766b022
k8s-ui(issues): onset age column (chronic-vs-acute triage signal)
nadaverell May 29, 2026
18a878b
feat(subject): unified subject+overlay resolver; consume it from issu…
nadaverell May 29, 2026
f529101
fix(issues): GA-blockers — monotonic crashloop, double-row, unknown-g…
nadaverell May 29, 2026
86fbab9
fix(issues): Bugbot review — affected-total off-by-one, restart-count…
nadaverell May 29, 2026
c873b8c
feat(issues): per-cluster Issues view in radar OSS (hidden /issues ro…
nadaverell May 29, 2026
3887477
fix(issues): don't over-flag recovered-crash pods as error; keep Unkn…
nadaverell May 29, 2026
6472241
fix(issues): PR review — completed-init false-positive, comment hygie…
nadaverell May 30, 2026
7463eb7
fix(issues): classifier precision/recall from the multi-cluster audit
nadaverell May 30, 2026
5c27d95
fix(issues): tighten the public contract from PR review
nadaverell May 30, 2026
47501bf
fix(issues): review follow-ups — missing-ref owner grouping + consist…
nadaverell May 30, 2026
e0f611f
fix(issues): Bugbot — normalize member refs + don't suppress genuine …
nadaverell May 30, 2026
cefeddf
refactor(issues): vocabulary + dedup nits (review batch 1)
nadaverell May 30, 2026
0a94ec5
refactor(issues): depure types.go — move Filters/CELFilter to options.go
nadaverell May 30, 2026
f97c955
refactor(issues): rename detector output type Problem → Detection
nadaverell May 30, 2026
4476ee9
refactor: extract neutral pkg/resourceid (ResourceKey + Kind→Group)
nadaverell May 30, 2026
be63dd9
refactor: extract neutral pkg/conditions; consolidate transient-reaso…
nadaverell May 30, 2026
7050a8e
refactor(issues): one shared condition reader (pkg/conditions.FindFal…
nadaverell May 30, 2026
322573a
refactor(k8s): frame + split the detector layer (was problems.go)
nadaverell May 30, 2026
ed7cb8e
refactor(issues): split the issues.go god-file by concern
nadaverell May 30, 2026
5798ced
refactor(web): extract navigateToResourceList — dedupe Audit/Issues n…
nadaverell May 30, 2026
3bfba05
chore: remove accidental main-page.png screenshot artifact
nadaverell May 30, 2026
9185d4e
refactor: finish moving identity/status ownership to neutral leaves
nadaverell May 30, 2026
264d360
refactor(issues): align queue order, narrow GitOps classification, fi…
nadaverell May 30, 2026
267bb91
feat(issues): close detection/classification gaps from review
nadaverell May 30, 2026
fcff6a2
fix(issues): Argo severity ordering + error-type allowlist + Count docs
nadaverell May 30, 2026
9135af0
revert(issues): drop DaemonSet available-vs-desired check
nadaverell May 30, 2026
6a14326
refactor(k8s): detect_ prefix on the issue-detector files
nadaverell May 30, 2026
b94d0d8
refactor(k8s): split health.go grab-bag into focused files
nadaverell May 30, 2026
20d4243
fix(issues): surface the decisive detail inline (image/config msg, re…
nadaverell May 31, 2026
dcc0191
feat(issues-ui): normalize verbose image-pull messages for display, k…
nadaverell May 31, 2026
ec44e32
harden(subject): controller-only OwnerResolver contract, deterministi…
nadaverell May 31, 2026
2b16a5e
harden(subject): make controller-only contract enforced, not just doc…
nadaverell May 31, 2026
8c58969
fix(issues): don't flag WaitForFirstConsumer PVCs as pvc_pending
nadaverell May 31, 2026
3bfc65a
harden(issues): stable cause fingerprint, namespace-scoped curated de…
nadaverell May 31, 2026
6be0738
fix(issues): taxonomy accuracy, GitOps severity alignment, source-nat…
nadaverell May 31, 2026
b9cac99
fix(issues): shared response DTO, truncation honesty, resource deep-l…
nadaverell May 31, 2026
f003355
feat(mcp): align resource drill-down with grouped issues + richer age…
nadaverell May 31, 2026
7aaf152
fix(issues): CAPI group-qualified discovery, HPA cause split, visibil…
nadaverell May 31, 2026
ef851a6
fix(issues): owner-aware, uncapped per-resource issue lookup (the rea…
nadaverell May 31, 2026
d4152cd
fix(issues): Service cause split + remove the dead cluster CEL binding
nadaverell May 31, 2026
ee4fffc
fix(issues): forbid explicit namespace denial; align backend/frontend…
nadaverell May 31, 2026
888b3ef
fix(issues): clear recovered crashloops faster, name multi-replica RW…
nadaverell May 31, 2026
ce38988
feat(issues): detect eviction-blocking PDBs; name RWO+RollingUpdate r…
nadaverell May 31, 2026
e3a659a
fix(issues): PR review — bound image-pull regex, drop dead key helper…
nadaverell May 31, 2026
03c18ee
fix(issues): review findings — rollout/degraded dedup, desired-replic…
nadaverell May 31, 2026
518e8d4
fix(issues): address final review findings
nadaverell May 31, 2026
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
32 changes: 22 additions & 10 deletions internal/filter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
//
// Two compile entry points:
//
// CompileObjectFilter — bindings shaped to a K8s object:
// kind, apiVersion, metadata, spec, status, labels, annotations
// CompileObjectFilter — bindings shaped to a K8s object:
// kind, apiVersion, metadata, spec, status, labels, annotations
//
// CompileIssueFilter — bindings shaped to an issues.Issue:
// severity, source, kind, group, namespace, name, reason, message,
// count, last_seen, cluster
// CompileIssueFilter — bindings shaped to an issues.Issue:
// severity, source, category, category_group, kind, group, ns,
// name, reason, message, count, first_seen, last_seen, grouping_scope,
// restart_count, last_terminated_reason
//
// Both return a Filter whose Match(activation) yields (bool, error).
// Compile errors are returned verbatim (CEL's parser produces
Expand Down Expand Up @@ -96,18 +97,30 @@ var envObject = mustNewEnv(
var envIssue = mustNewEnv(
cel.Variable("severity", cel.StringType),
cel.Variable("source", cel.StringType),
cel.Variable("category", cel.StringType),
cel.Variable("category_group", cel.StringType),
cel.Variable("kind", cel.StringType),
cel.Variable("group", cel.StringType),
cel.Variable("ns", cel.StringType),
cel.Variable("name", cel.StringType),
cel.Variable("reason", cel.StringType),
cel.Variable("message", cel.StringType),
cel.Variable("count", cel.IntType),
cel.Variable("cluster", cel.StringType),
// last_seen is provided as an int unix-second timestamp so the
// agent can write `last_seen > timestamp("2025-01-01T00:00:00Z")`
// or compare against a "now - 1h" delta passed by the caller.
// No `cluster` binding: a single Radar is one cluster. Cross-cluster scoping
// is the hub's `clusters=`/target mechanism (applied at fan-out), not a
// per-issue CEL predicate — Issue.Cluster was always empty here, so a
// forwarded `cluster == "x"` matched nothing.
// first_seen/last_seen are int unix-second timestamps so the agent can
// write `first_seen > timestamp("2025-01-01T00:00:00Z")` or compare
// against a "now - 1h" delta. Prefer first_seen for "issues older
// than…": last_seen churns to compose-time on every poll.
cel.Variable("first_seen", cel.IntType),
cel.Variable("last_seen", cel.IntType),
// grouping_scope (node|workload|…) slices node-level vs workload issues;
// restart_count + last_terminated_reason are the chronic-vs-acute fields.
cel.Variable("grouping_scope", cel.StringType),
cel.Variable("restart_count", cel.IntType),
cel.Variable("last_terminated_reason", cel.StringType),
)

func mustNewEnv(opts ...cel.EnvOption) *cel.Env {
Expand Down Expand Up @@ -264,4 +277,3 @@ func CachedIssueFilter(expr string) (*Filter, error) {
defaultCache.put(key, f)
return f, nil
}

35 changes: 23 additions & 12 deletions internal/issues/activation.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,35 @@ package issues
// `last_seen > timestamp("2025-01-01T00:00:00Z").getSeconds()` —
// CEL's int domain is the lowest-friction lingua franca.
func issueToActivation(i Issue) map[string]any {
var lastSeen int64
var lastSeen, firstSeen int64
if !i.LastSeen.IsZero() {
lastSeen = i.LastSeen.Unix()
}
if !i.FirstSeen.IsZero() {
firstSeen = i.FirstSeen.Unix()
}
return map[string]any{
"severity": string(i.Severity),
"source": string(i.Source),
"kind": i.Kind,
"group": i.Group,
"severity": string(i.Severity),
"source": string(i.Source),
"category": string(i.Category),
"category_group": string(i.CategoryGroup),
"kind": i.Kind,
"group": i.Group,
// `ns` rather than `namespace` — `namespace` is a CEL reserved
// identifier and bare references fail at parse time. See
// internal/filter.envIssue for the rationale.
"ns": i.Namespace,
"name": i.Name,
"reason": i.Reason,
"message": i.Message,
"count": int64(i.Count),
"cluster": i.Cluster,
"last_seen": lastSeen,
"ns": i.Namespace,
"name": i.Name,
"reason": i.Reason,
"message": i.Message,
"count": int64(i.Count),
// first_seen is the onset (the axis the queue sorts on); last_seen
// churns to compose-time every poll, so `last_seen > X` ("older
// than…") is near-useless. Both are int unix seconds.
"first_seen": firstSeen,
"last_seen": lastSeen,
"grouping_scope": string(i.GroupingScope),
"restart_count": int64(i.RestartCount),
"last_terminated_reason": i.LastTerminatedReason,
}
}
Loading
Loading