toad-eye 2.6.1 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,323 @@
1
+ {
2
+ "annotations": {
3
+ "list": []
4
+ },
5
+ "editable": true,
6
+ "fiscalYearStartMonth": 0,
7
+ "graphTooltip": 1,
8
+ "id": null,
9
+ "links": [],
10
+ "panels": [
11
+ {
12
+ "title": "Total Request Rate",
13
+ "description": "Combined rate of MCP client + server operations",
14
+ "type": "stat",
15
+ "gridPos": { "h": 4, "w": 6, "x": 0, "y": 0 },
16
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
17
+ "targets": [
18
+ {
19
+ "expr": "sum(rate(gen_ai_mcp_tool_calls_total[5m])) + sum(rate(gen_ai_client_requests_total[5m])) or vector(0)",
20
+ "refId": "A"
21
+ }
22
+ ],
23
+ "fieldConfig": {
24
+ "defaults": {
25
+ "unit": "reqps",
26
+ "decimals": 2,
27
+ "thresholds": {
28
+ "steps": [
29
+ { "color": "green", "value": null },
30
+ { "color": "yellow", "value": 50 },
31
+ { "color": "red", "value": 100 }
32
+ ]
33
+ }
34
+ },
35
+ "overrides": []
36
+ }
37
+ },
38
+ {
39
+ "title": "LLM Avg Latency",
40
+ "description": "Average LLM call duration (client-side)",
41
+ "type": "stat",
42
+ "gridPos": { "h": 4, "w": 6, "x": 6, "y": 0 },
43
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
44
+ "targets": [
45
+ {
46
+ "expr": "sum(rate(gen_ai_client_operation_duration_sum[5m])) / sum(rate(gen_ai_client_operation_duration_count[5m])) or vector(0)",
47
+ "refId": "A"
48
+ }
49
+ ],
50
+ "fieldConfig": {
51
+ "defaults": {
52
+ "unit": "ms",
53
+ "decimals": 0,
54
+ "thresholds": {
55
+ "steps": [
56
+ { "color": "green", "value": null },
57
+ { "color": "yellow", "value": 1000 },
58
+ { "color": "red", "value": 5000 }
59
+ ]
60
+ }
61
+ },
62
+ "overrides": []
63
+ }
64
+ },
65
+ {
66
+ "title": "Tool Avg Latency",
67
+ "description": "Average MCP tool execution duration (server-side)",
68
+ "type": "stat",
69
+ "gridPos": { "h": 4, "w": 6, "x": 12, "y": 0 },
70
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
71
+ "targets": [
72
+ {
73
+ "expr": "sum(rate(gen_ai_mcp_tool_duration_sum[5m])) / sum(rate(gen_ai_mcp_tool_duration_count[5m])) or vector(0)",
74
+ "refId": "A"
75
+ }
76
+ ],
77
+ "fieldConfig": {
78
+ "defaults": {
79
+ "unit": "ms",
80
+ "decimals": 0,
81
+ "thresholds": {
82
+ "steps": [
83
+ { "color": "green", "value": null },
84
+ { "color": "yellow", "value": 500 },
85
+ { "color": "red", "value": 2000 }
86
+ ]
87
+ }
88
+ },
89
+ "overrides": []
90
+ }
91
+ },
92
+ {
93
+ "title": "End-to-End Error Rate",
94
+ "description": "Combined error rate across LLM + MCP",
95
+ "type": "stat",
96
+ "gridPos": { "h": 4, "w": 6, "x": 18, "y": 0 },
97
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
98
+ "targets": [
99
+ {
100
+ "expr": "(sum(rate(gen_ai_client_errors_total[5m])) + sum(rate(gen_ai_mcp_tool_errors_total[5m]))) / (sum(rate(gen_ai_client_requests_total[5m])) + sum(rate(gen_ai_mcp_tool_calls_total[5m]))) or vector(0)",
101
+ "refId": "A"
102
+ }
103
+ ],
104
+ "fieldConfig": {
105
+ "defaults": {
106
+ "unit": "percentunit",
107
+ "decimals": 2,
108
+ "thresholds": {
109
+ "steps": [
110
+ { "color": "green", "value": null },
111
+ { "color": "yellow", "value": 0.05 },
112
+ { "color": "red", "value": 0.1 }
113
+ ]
114
+ }
115
+ },
116
+ "overrides": []
117
+ }
118
+ },
119
+ {
120
+ "title": "Latency Breakdown: LLM vs Tool",
121
+ "description": "Compare LLM call latency vs MCP tool execution latency over time",
122
+ "type": "timeseries",
123
+ "gridPos": { "h": 8, "w": 12, "x": 0, "y": 4 },
124
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
125
+ "targets": [
126
+ {
127
+ "expr": "sum(rate(gen_ai_client_operation_duration_sum[5m])) / sum(rate(gen_ai_client_operation_duration_count[5m]))",
128
+ "legendFormat": "LLM Avg Latency",
129
+ "refId": "A"
130
+ },
131
+ {
132
+ "expr": "sum(rate(gen_ai_mcp_tool_duration_sum[5m])) / sum(rate(gen_ai_mcp_tool_duration_count[5m]))",
133
+ "legendFormat": "Tool Avg Latency",
134
+ "refId": "B"
135
+ }
136
+ ],
137
+ "fieldConfig": {
138
+ "defaults": {
139
+ "unit": "ms",
140
+ "custom": {
141
+ "drawStyle": "line",
142
+ "lineInterpolation": "smooth",
143
+ "fillOpacity": 20,
144
+ "pointSize": 5,
145
+ "showPoints": "auto"
146
+ }
147
+ },
148
+ "overrides": [
149
+ {
150
+ "matcher": { "id": "byName", "options": "LLM Avg Latency" },
151
+ "properties": [
152
+ {
153
+ "id": "color",
154
+ "value": { "fixedColor": "orange", "mode": "fixed" }
155
+ }
156
+ ]
157
+ },
158
+ {
159
+ "matcher": { "id": "byName", "options": "Tool Avg Latency" },
160
+ "properties": [
161
+ {
162
+ "id": "color",
163
+ "value": { "fixedColor": "blue", "mode": "fixed" }
164
+ }
165
+ ]
166
+ }
167
+ ]
168
+ },
169
+ "options": {
170
+ "legend": {
171
+ "displayMode": "table",
172
+ "placement": "bottom",
173
+ "calcs": ["mean", "max"]
174
+ },
175
+ "tooltip": { "mode": "multi" }
176
+ }
177
+ },
178
+ {
179
+ "title": "Tool Call Waterfall by Tool",
180
+ "description": "Duration per tool over time — identify slow tools",
181
+ "type": "timeseries",
182
+ "gridPos": { "h": 8, "w": 12, "x": 12, "y": 4 },
183
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
184
+ "targets": [
185
+ {
186
+ "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_duration_sum[5m])) / sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_duration_count[5m]))",
187
+ "legendFormat": "{{gen_ai_tool_name}}",
188
+ "refId": "A"
189
+ }
190
+ ],
191
+ "fieldConfig": {
192
+ "defaults": {
193
+ "unit": "ms",
194
+ "custom": {
195
+ "drawStyle": "bars",
196
+ "fillOpacity": 60,
197
+ "stacking": { "mode": "normal" }
198
+ },
199
+ "color": { "mode": "palette-classic" }
200
+ },
201
+ "overrides": []
202
+ },
203
+ "options": {
204
+ "legend": {
205
+ "displayMode": "table",
206
+ "placement": "bottom",
207
+ "calcs": ["mean", "sum"]
208
+ },
209
+ "tooltip": { "mode": "multi" }
210
+ }
211
+ },
212
+ {
213
+ "title": "Error Propagation: LLM vs Tool",
214
+ "description": "Error rates split by LLM errors and MCP tool errors",
215
+ "type": "timeseries",
216
+ "gridPos": { "h": 8, "w": 12, "x": 0, "y": 12 },
217
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
218
+ "targets": [
219
+ {
220
+ "expr": "sum(rate(gen_ai_client_errors_total[5m]))",
221
+ "legendFormat": "LLM Errors",
222
+ "refId": "A"
223
+ },
224
+ {
225
+ "expr": "sum(rate(gen_ai_mcp_tool_errors_total[5m]))",
226
+ "legendFormat": "Tool Errors",
227
+ "refId": "B"
228
+ }
229
+ ],
230
+ "fieldConfig": {
231
+ "defaults": {
232
+ "unit": "reqps",
233
+ "custom": {
234
+ "drawStyle": "line",
235
+ "lineInterpolation": "smooth",
236
+ "fillOpacity": 30,
237
+ "pointSize": 5,
238
+ "showPoints": "auto"
239
+ }
240
+ },
241
+ "overrides": [
242
+ {
243
+ "matcher": { "id": "byName", "options": "LLM Errors" },
244
+ "properties": [
245
+ {
246
+ "id": "color",
247
+ "value": { "fixedColor": "red", "mode": "fixed" }
248
+ }
249
+ ]
250
+ },
251
+ {
252
+ "matcher": { "id": "byName", "options": "Tool Errors" },
253
+ "properties": [
254
+ {
255
+ "id": "color",
256
+ "value": { "fixedColor": "purple", "mode": "fixed" }
257
+ }
258
+ ]
259
+ }
260
+ ]
261
+ },
262
+ "options": {
263
+ "legend": {
264
+ "displayMode": "table",
265
+ "placement": "bottom",
266
+ "calcs": ["sum"]
267
+ },
268
+ "tooltip": { "mode": "multi" }
269
+ }
270
+ },
271
+ {
272
+ "title": "Cost: LLM Calls",
273
+ "description": "Total LLM cost over time — visible when tools call LLMs via sampling",
274
+ "type": "timeseries",
275
+ "gridPos": { "h": 8, "w": 12, "x": 12, "y": 12 },
276
+ "datasource": { "type": "prometheus", "uid": "prometheus" },
277
+ "targets": [
278
+ {
279
+ "expr": "sum by (gen_ai_request_model) (rate(gen_ai_client_request_cost_USD_sum[5m]))",
280
+ "legendFormat": "{{gen_ai_request_model}}",
281
+ "refId": "A"
282
+ }
283
+ ],
284
+ "fieldConfig": {
285
+ "defaults": {
286
+ "unit": "currencyUSD",
287
+ "decimals": 6,
288
+ "custom": {
289
+ "drawStyle": "line",
290
+ "lineInterpolation": "smooth",
291
+ "fillOpacity": 15,
292
+ "pointSize": 5,
293
+ "showPoints": "auto"
294
+ },
295
+ "color": { "mode": "palette-classic" }
296
+ },
297
+ "overrides": []
298
+ },
299
+ "options": {
300
+ "legend": {
301
+ "displayMode": "table",
302
+ "placement": "bottom",
303
+ "calcs": ["sum"]
304
+ },
305
+ "tooltip": { "mode": "multi" }
306
+ }
307
+ }
308
+ ],
309
+ "schemaVersion": 39,
310
+ "tags": ["toad-eye", "mcp", "e2e", "distributed-tracing"],
311
+ "templating": {
312
+ "list": []
313
+ },
314
+ "time": {
315
+ "from": "now-1h",
316
+ "to": "now"
317
+ },
318
+ "timepicker": {},
319
+ "timezone": "browser",
320
+ "title": "MCP End-to-End",
321
+ "uid": "toad-eye-mcp-e2e",
322
+ "version": 1
323
+ }
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "targets": [
25
25
  {
26
- "expr": "sum(rate(gen_ai_mcp_tool_calls_total[5m]))",
26
+ "expr": "sum(rate(gen_ai_mcp_tool_calls_total{gen_ai_tool_name=~\"$tool_name\"}[5m]))",
27
27
  "refId": "A"
28
28
  }
29
29
  ],
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "targets": [
68
68
  {
69
- "expr": "sum(rate(gen_ai_mcp_tool_duration_sum[5m])) / sum(rate(gen_ai_mcp_tool_duration_count[5m])) or vector(0)",
69
+ "expr": "sum(rate(gen_ai_mcp_tool_duration_sum{gen_ai_tool_name=~\"$tool_name\"}[5m])) / sum(rate(gen_ai_mcp_tool_duration_count{gen_ai_tool_name=~\"$tool_name\"}[5m])) or vector(0)",
70
70
  "refId": "A"
71
71
  }
72
72
  ],
@@ -109,7 +109,7 @@
109
109
  },
110
110
  "targets": [
111
111
  {
112
- "expr": "sum(rate(gen_ai_mcp_tool_errors_total[5m])) / sum(rate(gen_ai_mcp_tool_calls_total[5m])) or vector(0)",
112
+ "expr": "sum(rate(gen_ai_mcp_tool_errors_total{gen_ai_tool_name=~\"$tool_name\"}[5m])) / sum(rate(gen_ai_mcp_tool_calls_total{gen_ai_tool_name=~\"$tool_name\"}[5m])) or vector(0)",
113
113
  "refId": "A"
114
114
  }
115
115
  ],
@@ -187,7 +187,7 @@
187
187
  },
188
188
  "targets": [
189
189
  {
190
- "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_calls_total[5m]))",
190
+ "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_calls_total{gen_ai_tool_name=~\"$tool_name\"}[5m]))",
191
191
  "legendFormat": "{{gen_ai_tool_name}}",
192
192
  "refId": "A"
193
193
  }
@@ -231,12 +231,12 @@
231
231
  },
232
232
  "targets": [
233
233
  {
234
- "expr": "histogram_quantile(0.50, sum by (gen_ai_tool_name, le) (rate(gen_ai_mcp_tool_duration_bucket[5m])))",
234
+ "expr": "histogram_quantile(0.50, sum by (gen_ai_tool_name, le) (rate(gen_ai_mcp_tool_duration_bucket{gen_ai_tool_name=~\"$tool_name\"}[5m])))",
235
235
  "legendFormat": "p50 {{gen_ai_tool_name}}",
236
236
  "refId": "A"
237
237
  },
238
238
  {
239
- "expr": "histogram_quantile(0.95, sum by (gen_ai_tool_name, le) (rate(gen_ai_mcp_tool_duration_bucket[5m])))",
239
+ "expr": "histogram_quantile(0.95, sum by (gen_ai_tool_name, le) (rate(gen_ai_mcp_tool_duration_bucket{gen_ai_tool_name=~\"$tool_name\"}[5m])))",
240
240
  "legendFormat": "p95 {{gen_ai_tool_name}}",
241
241
  "refId": "B"
242
242
  }
@@ -280,7 +280,7 @@
280
280
  },
281
281
  "targets": [
282
282
  {
283
- "expr": "sum by (gen_ai_tool_name, error_type) (rate(gen_ai_mcp_tool_errors_total[5m]))",
283
+ "expr": "sum by (gen_ai_tool_name, error_type) (rate(gen_ai_mcp_tool_errors_total{gen_ai_tool_name=~\"$tool_name\"}[5m]))",
284
284
  "legendFormat": "{{gen_ai_tool_name}} ({{error_type}})",
285
285
  "refId": "A"
286
286
  }
@@ -371,28 +371,28 @@
371
371
  },
372
372
  "targets": [
373
373
  {
374
- "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_calls_total[5m]))",
374
+ "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_calls_total{gen_ai_tool_name=~\"$tool_name\"}[5m]))",
375
375
  "legendFormat": "",
376
376
  "refId": "calls",
377
377
  "format": "table",
378
378
  "instant": true
379
379
  },
380
380
  {
381
- "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_duration_sum[5m])) / sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_duration_count[5m]))",
381
+ "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_duration_sum{gen_ai_tool_name=~\"$tool_name\"}[5m])) / sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_duration_count{gen_ai_tool_name=~\"$tool_name\"}[5m]))",
382
382
  "legendFormat": "",
383
383
  "refId": "avg_duration",
384
384
  "format": "table",
385
385
  "instant": true
386
386
  },
387
387
  {
388
- "expr": "histogram_quantile(0.95, sum by (gen_ai_tool_name, le) (rate(gen_ai_mcp_tool_duration_bucket[5m])))",
388
+ "expr": "histogram_quantile(0.95, sum by (gen_ai_tool_name, le) (rate(gen_ai_mcp_tool_duration_bucket{gen_ai_tool_name=~\"$tool_name\"}[5m])))",
389
389
  "legendFormat": "",
390
390
  "refId": "p95_duration",
391
391
  "format": "table",
392
392
  "instant": true
393
393
  },
394
394
  {
395
- "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_errors_total[5m])) / sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_calls_total[5m]))",
395
+ "expr": "sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_errors_total{gen_ai_tool_name=~\"$tool_name\"}[5m])) / sum by (gen_ai_tool_name) (rate(gen_ai_mcp_tool_calls_total{gen_ai_tool_name=~\"$tool_name\"}[5m]))",
396
396
  "legendFormat": "",
397
397
  "refId": "error_rate",
398
398
  "format": "table",
@@ -505,7 +505,27 @@
505
505
  "schemaVersion": 39,
506
506
  "tags": ["toad-eye", "mcp", "llm"],
507
507
  "templating": {
508
- "list": []
508
+ "list": [
509
+ {
510
+ "name": "tool_name",
511
+ "label": "Tool",
512
+ "type": "query",
513
+ "datasource": {
514
+ "type": "prometheus",
515
+ "uid": "prometheus"
516
+ },
517
+ "query": "label_values(gen_ai_mcp_tool_calls_total, gen_ai_tool_name)",
518
+ "refresh": 2,
519
+ "includeAll": true,
520
+ "allValue": ".*",
521
+ "current": {
522
+ "text": "All",
523
+ "value": "$__all"
524
+ },
525
+ "multi": true,
526
+ "sort": 1
527
+ }
528
+ ]
509
529
  },
510
530
  "time": {
511
531
  "from": "now-1h",
@@ -31,7 +31,7 @@ processors:
31
31
  sampling_percentage: 100
32
32
 
33
33
  exporters:
34
- otlp_http/jaeger:
34
+ otlphttp/jaeger:
35
35
  endpoint: http://jaeger:4318
36
36
  tls:
37
37
  insecure: true
@@ -44,7 +44,7 @@ service:
44
44
  traces:
45
45
  receivers: [otlp]
46
46
  processors: [batch]
47
- exporters: [otlp_http/jaeger]
47
+ exporters: [otlphttp/jaeger]
48
48
  metrics:
49
49
  receivers: [otlp]
50
50
  processors: [batch]