Make the Keycloak identity events table actually render

The panel never displayed: its query combined `line_format` with `logfmt`, and
on this data that pairing is pathological. Measured on a 24h range, the stream
selector with its json filter answers in 0.7s, adding line_format alone 0.3s,
adding logfmt alone 0.2s — chained, 60s and a timeout. The bar panels above it
survived because an aggregation streams; the log query did not.

Replaced with one independent `regexp` per field, reading the key="value" pairs
straight out of the JSON message without reformatting the line. 0.1s, and the
raw record now stays raw since nothing rewrites it.

Independent stages also fix a correctness problem the single-regexp version
would have had: the field set differs per event type — LOGIN_ERROR carries
`error` and `grant_type`, USER_SESSION_DELETED carries neither — so one regexp
spanning them all would drop whole rows on a missing field. All four types
observed on this cluster now extract correctly.

Failed and successful logins widen from LOGIN_ERROR and LOGIN to the *_ERROR
and CODE_TO_TOKEN families: a failed refresh or code exchange is the same
signal, and TOKEN_EXCHANGE dominates this cluster's traffic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Stéphane Tailland
2026-08-25 19:05:50 +02:00
parent 7c416ce06f
commit a2f5d725a3
2 changed files with 35 additions and 27 deletions
+9 -1
View File
@@ -225,7 +225,15 @@ questions have nothing in common and a single view compromised on all of them.
| `obs-audit-logs` | Who authenticated, what changed, who called what? | Keycloak `org.keycloak.events`, Kong http-log records |
Each source keeps its own parser and they all emit the same field names, so the
frames merge into one table with consistent columns. Access logs converge on
frames merge into one table with consistent columns.
Keycloak's identity events are read with one independent `regexp` per field
rather than `line_format` piped into `logfmt`. Two reasons, both measured: that
combination is pathological on this data — each stage answers in 0.3s alone,
chained they time out at 60s and the table never renders — and the field set
differs per event type, so a single regexp spanning them would fail whole rows
on a missing field. Independent stages leave the absent field empty and keep the
row, and the query returns in 0.1s. Access logs converge on
method / path / status / client; application logs on level / message.
Three things this split fixes that a single consolidated view could not: