@cryptotaxi247 / kubo / commits / a78991e45

fix: replace deprecated otelhttp.WithMetricAttributesFn (#11257)

Use request-scoped otelhttp.Labeler instead, which is the recommended replacement per upstream otelhttp v0.67.0. - add withMetricLabels helper wrapping inner handler - migrate all 4 call sites in commands.go and gateway.go

Marcin Rataj committed Mar 29, 2026 at 17:33 UTC a78991e450f8ee7b17a4202ae2dc2a022e4d0868
2 files changed +20 -13
core/corehttp/commands.go
+1 -3
@@ -146,9 +146,7 @@ func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption {
146 cmdHandler = withAuthSecrets(authorizations, cmdHandler)
147 }
148
149 - cmdHandler = otelhttp.NewHandler(cmdHandler, "corehttp.cmdsHandler",
150 - otelhttp.WithMetricAttributesFn(staticServerDomainAttrFn("api")),
151 - )
149 + cmdHandler = otelhttp.NewHandler(withMetricLabels(cmdHandler, staticServerDomainAttrFn("api")), "corehttp.cmdsHandler")
150 mux.Handle(APIPath+"/", cmdHandler)
151 return mux, nil
152 }
core/corehttp/gateway.go
+19 -10
@@ -44,11 +44,10 @@ func GatewayOption(paths ...string) ServeOption {
44
45 handler := gateway.NewHandler(config, backend)
46 handler = gateway.NewHeaders(headers).ApplyCors().Wrap(handler)
47 - var otelOpts []otelhttp.Option
47 if fn := newServerDomainAttrFn(n); fn != nil {
49 - otelOpts = append(otelOpts, otelhttp.WithMetricAttributesFn(fn))
48 + handler = withMetricLabels(handler, fn)
49 }
51 - handler = otelhttp.NewHandler(handler, "Gateway", otelOpts...)
50 + handler = otelhttp.NewHandler(handler, "Gateway")
51
52 for _, p := range paths {
53 mux.Handle(p+"/", handler)
@@ -75,11 +74,10 @@ func HostnameOption() ServeOption {
74 var handler http.Handler
75 handler = gateway.NewHostnameHandler(config, backend, childMux)
76 handler = gateway.NewHeaders(headers).ApplyCors().Wrap(handler)
78 - var otelOpts []otelhttp.Option
77 if fn := newServerDomainAttrFn(n); fn != nil {
80 - otelOpts = append(otelOpts, otelhttp.WithMetricAttributesFn(fn))
78 + handler = withMetricLabels(handler, fn)
79 }
82 - handler = otelhttp.NewHandler(handler, "HostnameGateway", otelOpts...)
80 + handler = otelhttp.NewHandler(handler, "HostnameGateway")
81
82 mux.Handle("/", handler)
83 return childMux, nil
@@ -131,9 +129,7 @@ func Libp2pGatewayOption() ServeOption {
129 }
130
131 handler := gateway.NewHandler(gwConfig, &offlineGatewayErrWrapper{gwimpl: backend})
134 - handler = otelhttp.NewHandler(handler, "Libp2p-Gateway",
135 - otelhttp.WithMetricAttributesFn(staticServerDomainAttrFn("libp2p")),
136 - )
132 + handler = otelhttp.NewHandler(withMetricLabels(handler, staticServerDomainAttrFn("libp2p")), "Libp2p-Gateway")
133
134 mux.Handle("/ipfs/", handler)
135
@@ -272,6 +268,19 @@ var defaultPaths = []string{"/ipfs/", "/ipns/", "/p2p/"}
268 // or "other".
269 var serverDomainAttrKey = attribute.Key("server.domain")
270
271 +// withMetricLabels wraps a handler so that otelhttp metric attributes are
272 +// added via the request-scoped [otelhttp.Labeler] instead of the deprecated
273 +// [otelhttp.WithMetricAttributesFn] option. The wrapper must run inside
274 +// [otelhttp.NewHandler] (which injects the labeler into the context).
275 +func withMetricLabels(next http.Handler, fn func(*http.Request) []attribute.KeyValue) http.Handler {
276 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
277 + if l, ok := otelhttp.LabelerFromContext(r.Context()); ok {
278 + l.Add(fn(r)...)
279 + }
280 + next.ServeHTTP(w, r)
281 + })
282 +}
283 +
284 // staticServerDomainAttrFn returns a MetricAttributesFn that always returns
285 // a fixed server.domain value. Use for handlers where the domain is known
286 // statically (e.g. "api", "libp2p") to keep the label set consistent across
@@ -281,7 +290,7 @@ func staticServerDomainAttrFn(domain string) func(*http.Request) []attribute.Key
290 return func(*http.Request) []attribute.KeyValue { return attrs }
291 }
292
284 -// newServerDomainAttrFn returns an otelhttp.WithMetricAttributesFn callback
293 +// newServerDomainAttrFn returns an attribute callback for [withMetricLabels]
294 // that adds a server.domain attribute grouping requests by their matching
295 // Gateway.PublicGateways hostname suffix (e.g. "dweb.link", "ipfs.io").
296 // Requests that don't match any configured gateway get "other".