Show parsed log tables instead of raw lines
Raw lines are close to unreadable when the payload is JSON, and the Kong audit records are the worst case: a wall of braces where the interesting fields are status, route and latency. Each dashboard now leads with a table carrying one column per parsed field, sortable and filterable, with the unparsed record as the last column and the cell inspector enabled on every cell. The original logs panel moves into a collapsed row underneath rather than disappearing: a table cannot render ANSI colour, expand a record inline, tail live, or turn a trace id into a link to Tempo. Parsing is per-format since the five sources agree on nothing — nested JSON for Kong, JSON for Keycloak, NCSA access lines for the Django API, ANSI-coloured text for LibreChat, logfmt for the stack itself. The Kong and stack parsers name their fields explicitly rather than extracting everything: a bare `| json` on a Kong record yields around seventy columns, and a bare `| logfmt` explodes Loki's own query-metrics lines into dozens. Columns are selected by include-pattern rather than by excluding names, because the stream labels that ride along are not a fixed set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1522,9 +1522,9 @@
|
||||
"description": "Namespace-wide so the datastore's failures show up next to the application's."
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"type": "logs",
|
||||
"title": "Recent errors and warnings",
|
||||
"id": 27,
|
||||
"type": "table",
|
||||
"title": "Errors and warnings",
|
||||
"datasource": {
|
||||
"type": "loki",
|
||||
"uid": "loki"
|
||||
@@ -1542,21 +1542,216 @@
|
||||
"type": "loki",
|
||||
"uid": "loki"
|
||||
},
|
||||
"expr": "{namespace=\"librechat\"} | detected_level =~ \"error|critical|warn\"",
|
||||
"queryType": "range"
|
||||
"expr": "{namespace=\"librechat\", container=\"librechat\"} | detected_level =~ \"error|critical|warn\" | line_format `{{ regexReplaceAll \"\\\\x1b\\\\[[0-9;]*m\" __line__ \"\" }}` | pattern `<date> <time> <lvl>: <msg>`",
|
||||
"queryType": "range",
|
||||
"maxLines": 500
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"showTime": true,
|
||||
"showLabels": false,
|
||||
"showCommonLabels": false,
|
||||
"wrapLogMessage": true,
|
||||
"prettifyLogMessage": false,
|
||||
"sortOrder": "Descending",
|
||||
"dedupStrategy": "none",
|
||||
"enableLogDetails": true
|
||||
"transformations": [
|
||||
{
|
||||
"id": "extractFields",
|
||||
"options": {
|
||||
"source": "labels",
|
||||
"replace": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "filterFieldsByName",
|
||||
"options": {
|
||||
"include": {
|
||||
"pattern": "^(timestamp|body|lvl|msg)$"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {
|
||||
"excludeByName": {},
|
||||
"indexByName": {
|
||||
"Time": 0,
|
||||
"lvl": 1,
|
||||
"msg": 2,
|
||||
"body": 3
|
||||
},
|
||||
"renameByName": {
|
||||
"lvl": "Level",
|
||||
"msg": "Message",
|
||||
"body": "Raw record",
|
||||
"timestamp": "Time"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"cellOptions": {
|
||||
"type": "auto"
|
||||
},
|
||||
"inspect": true,
|
||||
"filterable": true
|
||||
},
|
||||
"mappings": []
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Level"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 90
|
||||
},
|
||||
{
|
||||
"id": "mappings",
|
||||
"value": [
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "(?i)^(fatal|critical)$",
|
||||
"result": {
|
||||
"color": "dark-red",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "(?i)^error$",
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "(?i)^warn(ing)?$",
|
||||
"result": {
|
||||
"color": "orange",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "(?i)^info$",
|
||||
"result": {
|
||||
"color": "green",
|
||||
"index": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "(?i)^debug$",
|
||||
"result": {
|
||||
"color": "blue",
|
||||
"index": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Raw record"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 260
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "Click a line to expand it. Where the line carries a trace_id, the Loki datasource's derived field opens the matching trace in Tempo."
|
||||
"options": {
|
||||
"showHeader": true,
|
||||
"cellHeight": "sm",
|
||||
"footer": {
|
||||
"show": false,
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"countRows": false,
|
||||
"fields": ""
|
||||
},
|
||||
"sortBy": [
|
||||
{
|
||||
"displayName": "Time",
|
||||
"desc": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "LibreChat writes colour-coded text rather than JSON, so the ANSI escapes are stripped first and the remainder split by pattern. The Raw column therefore holds the cleaned line; the collapsed panel below keeps the original with its colours."
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"type": "row",
|
||||
"title": "Raw log lines",
|
||||
"collapsed": true,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 60
|
||||
},
|
||||
"panels": [
|
||||
{
|
||||
"id": 22,
|
||||
"type": "logs",
|
||||
"title": "Raw log lines",
|
||||
"datasource": {
|
||||
"type": "loki",
|
||||
"uid": "loki"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 11,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 61
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "loki",
|
||||
"uid": "loki"
|
||||
},
|
||||
"expr": "{namespace=\"librechat\"} | detected_level =~ \"error|critical|warn\"",
|
||||
"queryType": "range"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"showTime": true,
|
||||
"showLabels": false,
|
||||
"showCommonLabels": false,
|
||||
"wrapLogMessage": true,
|
||||
"prettifyLogMessage": false,
|
||||
"sortOrder": "Descending",
|
||||
"dedupStrategy": "none",
|
||||
"enableLogDetails": true
|
||||
},
|
||||
"description": "Kept alongside the table: the logs panel renders ANSI colour, expands a record's detail inline, tails live, and turns a trace id into a link to Tempo — none of which a table can do. Collapsed so it stays out of the way until needed."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
@@ -1567,7 +1762,7 @@
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 60
|
||||
"y": 61
|
||||
},
|
||||
"panels": []
|
||||
},
|
||||
@@ -1583,7 +1778,7 @@
|
||||
"h": 7,
|
||||
"w": 8,
|
||||
"x": 0,
|
||||
"y": 61
|
||||
"y": 62
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
@@ -1649,7 +1844,7 @@
|
||||
"h": 7,
|
||||
"w": 8,
|
||||
"x": 8,
|
||||
"y": 61
|
||||
"y": 62
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
@@ -1714,7 +1909,7 @@
|
||||
"h": 7,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 61
|
||||
"y": 62
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user