Skip to content

Commit 9852112

Browse files
committed
support metric queries for loki
1 parent 839fe2e commit 9852112

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This provides access to your Grafana instance and the surrounding ecosystem.
1212
- [x] Prometheus
1313
- [x] Loki
1414
- [x] Log queries
15-
- [ ] Metric queries
15+
- [x] Metric queries
1616
- [ ] Tempo
1717
- [ ] Pyroscope
1818
- [x] Query Prometheus metadata

tools/loki.go

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"io"
99
"net/http"
1010
"net/url"
11+
"strconv"
1112
"strings"
1213
"time"
1314

@@ -246,8 +247,8 @@ var ListLokiLabelValues = mcpgrafana.MustTool(
246247

247248
// LogStream represents a stream of log entries from Loki
248249
type LogStream struct {
249-
Stream map[string]string `json:"stream"`
250-
Values [][]string `json:"values"` // [timestamp, log line]
250+
Stream map[string]string `json:"stream"`
251+
Values [][]json.RawMessage `json:"values"` // [timestamp, value] where value can be string or number
251252
}
252253

253254
// QueryRangeResponse represents the response from Loki's query_range API
@@ -341,10 +342,11 @@ type QueryLokiLogsParams struct {
341342
Direction string `json:"direction,omitempty" jsonschema:"description=Optionally, the direction of the query: 'forward' (oldest first) or 'backward' (newest first, default)"`
342343
}
343344

344-
// LogEntry represents a single log entry with metadata
345+
// LogEntry represents a single log entry or metric sample with metadata
345346
type LogEntry struct {
346347
Timestamp string `json:"timestamp"`
347-
Line string `json:"line"`
348+
Line string `json:"line,omitempty"` // For log queries
349+
Value *float64 `json:"value,omitempty"` // For metric queries
348350
Labels map[string]string `json:"labels"`
349351
}
350352

@@ -394,10 +396,42 @@ func queryLokiLogs(ctx context.Context, args QueryLokiLogsParams) ([]LogEntry, e
394396
for _, value := range stream.Values {
395397
if len(value) >= 2 {
396398
entry := LogEntry{
397-
Timestamp: value[0],
398-
Line: value[1],
399+
Timestamp: string(value[0]),
399400
Labels: stream.Stream,
400401
}
402+
403+
// Handle metric queries (numeric values) vs log queries
404+
if stream.Stream["__type__"] == "metrics" {
405+
// For metric queries, parse the value as a number
406+
var numStr string
407+
if err := json.Unmarshal(value[1], &numStr); err == nil {
408+
if v, err := strconv.ParseFloat(numStr, 64); err == nil {
409+
entry.Value = &v
410+
} else {
411+
// Skip invalid numeric values
412+
continue
413+
}
414+
} else {
415+
// Try direct number parsing if string parsing fails
416+
var v float64
417+
if err := json.Unmarshal(value[1], &v); err == nil {
418+
entry.Value = &v
419+
} else {
420+
// Skip invalid values
421+
continue
422+
}
423+
}
424+
} else {
425+
// For log queries, parse the value as a string
426+
var logLine string
427+
if err := json.Unmarshal(value[1], &logLine); err == nil {
428+
entry.Line = logLine
429+
} else {
430+
// Skip invalid log lines
431+
continue
432+
}
433+
}
434+
401435
entries = append(entries, entry)
402436
}
403437
}
@@ -414,7 +448,7 @@ func queryLokiLogs(ctx context.Context, args QueryLokiLogsParams) ([]LogEntry, e
414448
// QueryLokiLogs is a tool for querying logs from Loki
415449
var QueryLokiLogs = mcpgrafana.MustTool(
416450
"query_loki_logs",
417-
"Query and retrieve log entries from a Loki datasource using LogQL. Returns log lines with timestamps and labels. Use query_loki_stats first to check stream size, then list_loki_label_names/values to verify labels exist. Supports full LogQL syntax including filters and expressions.",
451+
"Query and retrieve log entries or metric values from a Loki datasource using LogQL. Returns either log lines or numeric values with timestamps and labels. Use query_loki_stats first to check stream size, then list_loki_label_names/values to verify labels exist. Supports full LogQL syntax including both log queries and metric queries (e.g., rate, count_over_time).",
418452
queryLokiLogs,
419453
)
420454

0 commit comments

Comments
 (0)