MCPcopy Index your code
hub / github.com/modelcontextprotocol/registry / MetricTelemetryMiddleware

Function MetricTelemetryMiddleware

internal/api/router/router.go:48–112  ·  view source on GitHub ↗
(metrics *telemetry.Metrics, options ...MiddlewareOption)

Source from the content-addressed store, hash-verified

46}
47
48func MetricTelemetryMiddleware(metrics *telemetry.Metrics, options ...MiddlewareOption) func(huma.Context, func(huma.Context)) {
49 config := &middlewareConfig{
50 skipPaths: make(map[string]bool),
51 }
52
53 for _, opt := range options {
54 opt(config)
55 }
56
57 return func(ctx huma.Context, next func(huma.Context)) {
58 path := ctx.URL().Path
59
60 // Skip instrumentation for specified paths
61 // extract the last part of the path to match against skipPaths
62 pathParts := strings.Split(path, "/")
63 pathToMatch := "/" + pathParts[len(pathParts)-1]
64 if config.skipPaths[pathToMatch] || config.skipPaths[path] {
65 next(ctx)
66 return
67 }
68
69 start := time.Now()
70 method := ctx.Method()
71 routePath := getRoutePath(ctx)
72
73 next(ctx)
74
75 duration := time.Since(start).Seconds()
76 statusCode := ctx.Status()
77
78 // If the client disconnected before the handler finished, the handler
79 // likely converted the resulting context.Canceled into a huma 5xx and
80 // tried to write a response to a closed socket. NGINX records that
81 // case as a 499 (client closed). Without this remap we count it as a
82 // server error: a single ServiceNow-style burst that times out a
83 // few thousand list-servers requests inflates http_errors_total even
84 // though no client ever saw a 5xx, and the availability alert fires
85 // on what is effectively just slow responses.
86 //
87 // Only context.Canceled is remapped — context.DeadlineExceeded would
88 // indicate a server-side timeout we set ourselves and should still
89 // count as a server error if/when we add per-request deadlines.
90 if reqErr := ctx.Context().Err(); reqErr != nil && errors.Is(reqErr, context.Canceled) {
91 statusCode = statusClientClosed
92 }
93
94 // Combine common and custom attributes
95 attrs := []attribute.KeyValue{
96 attribute.String("method", method),
97 attribute.String("path", routePath),
98 attribute.Int("status_code", statusCode),
99 }
100
101 // Record metrics
102 metrics.Requests.Add(ctx.Context(), 1, metric.WithAttributes(attrs...))
103
104 // Skip the error counter for client-closed requests so the availability
105 // metric reflects server-visible errors only.

Callers 3

TestPrometheusHandlerFunction · 0.92
NewHumaAPIFunction · 0.85

Calls 2

getRoutePathFunction · 0.85
StringMethod · 0.45

Used in the wild real call sites across dependent graphs

searching dependent graphs…