Skip to content

feat(observability): ordered structured log-level filtering (Loki detected_level + pino map) - #3

Merged
Afgan0r merged 1 commit into
masterfrom
feat/loki-structured-log-level
Jun 14, 2026
Merged

feat(observability): ordered structured log-level filtering (Loki detected_level + pino map)#3
Afgan0r merged 1 commit into
masterfrom
feat/loki-structured-log-level

Conversation

@Afgan0r

@Afgan0r Afgan0r commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Replaces the substring-regex stopgap Min level filter in the Logs (Loki) dashboard with a real ordered level, and makes server-2 (pino numeric levels) filterable instead of resolving to detected_level: unknown.

Change

  • k8s/observability/61-grafana-logs-dashboard.yaml: Min level variable now emits real LogQL label filters (| level=~"warn|error|fatal|critical" or detected_level=~"..."), panel exprs switched from |~ $level substring to $level. "All" = empty.
  • k8s/observability/80-alloy.yaml: in loki.process for {app="server-2"}, parse the pino JSON level, map numeric severity (10/20/30/40/50/60 → trace/debug/info/warn/error/fatal) and expose it as structured metadata level (not a label — preserves the 5-key allowlist + stream cardinality).

Validation

  • Offline: YAML + embedded dashboard JSON parse OK (uid solid-stats-logs), kubectl apply --dry-run=client OK. Alloy/LogQL syntax cross-checked against current docs (stage.template, stage.structured_metadata, LogQL or label filters).

Activation (staging, manual)

kubectl apply -f k8s/observability/80-alloy.yaml
kubectl apply -f k8s/observability/61-grafana-logs-dashboard.yaml
kubectl rollout restart daemonset/alloy -n monitoring

Caveat: structured-metadata level attaches only to logs ingested after Alloy reloads; historical server-2 lines stay unknown.

🤖 Generated with Claude Code

… + pino mapping

Replace the cross-format substring-regex Min-level stopgap in the Logs (Loki)
dashboard (uid solid-stats-logs) with a real ordered level filter. The
dropdown now emits LogQL label filters over the level / detected_level fields
instead of matching message substrings, so an info line containing the word
"error" no longer matches Warning+.

Loki 3.6.x already attaches a query-time detected_level for the text-format
apps (rabbitmq/postgres/glitchtip), but maps server-2's pino NUMERIC
"level":30/40/50 to detected_level: unknown, hiding our main app under any
level filter. Add an Alloy pipeline stage (80-alloy.yaml) scoped to
app="server-2" that parses the pino JSON level, maps the numeric severity to
a normalized text level (info/warn/error/fatal), and exposes it as STRUCTURED
METADATA named level — not a new stream label, so the Phase 15 5-key label
allowlist and stream cardinality are unchanged.

The dashboard filter ORs both fields (| level=~... or detected_level=~...) so a
single Min-level dropdown works across all apps. Closes the
logs-level-filtering-todo brief (option 1 detected_level + option 2 Alloy
mapping fallback for pino).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Afgan0r
Afgan0r merged commit e01c0c8 into master Jun 14, 2026
3 checks passed
@Afgan0r
Afgan0r deleted the feat/loki-structured-log-level branch June 14, 2026 16:53
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