@@ -17,6 +17,7 @@ import (
1717 "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
1818 "go.opentelemetry.io/otel"
1919 "go.opentelemetry.io/otel/metric"
20+ metricnoop "go.opentelemetry.io/otel/metric/noop"
2021
2122 "github.com/getlantern/broflake/common"
2223 "github.com/getlantern/telemetry"
@@ -291,7 +292,17 @@ func NewListener(ctx context.Context, ll net.Listener, tlsConfig *tls.Config) (n
291292 // panic on duplicate `/ws` registration, which broke tests, graceful
292293 // restarts, and any host that embeds multiple egress listeners.
293294 mux := http .NewServeMux ()
294- mux .Handle ("/ws" , otelhttp .NewHandler (http .HandlerFunc (l .handleWebsocket ), "/ws" ))
295+ // Wrap the handler for span propagation only — explicitly attach a noop
296+ // MeterProvider so otelhttp does NOT emit http.server.* histograms here.
297+ // The default attribute set on those histograms includes net.sock.peer.addr,
298+ // net.sock.peer.port and http.user_agent, which together create a fresh
299+ // time series for every WebSocket connection (~thousands/day on a single
300+ // egress) and blow up SigNoz cardinality. The four ObservableUpDownCounters
301+ // above already cover the only useful signals (concurrent ws/quic/streams,
302+ // ingress bytes); per-request HTTP metrics on a single upgrade endpoint
303+ // add no information.
304+ mux .Handle ("/ws" , otelhttp .NewHandler (http .HandlerFunc (l .handleWebsocket ), "/ws" ,
305+ otelhttp .WithMeterProvider (metricnoop .NewMeterProvider ())))
295306
296307 srv := & http.Server {
297308 Handler : mux ,
0 commit comments