Skip to content

[confighttp] otelhttp-generated span names may have high cardinality #12468

Open
@axw

Description

@axw

Component(s)

No response

What happened?

Describe the bug

The otelhttp instrumentation in confighttp uses the URL path for span names:

otelhttp.WithSpanNameFormatter(func(_ string, r *http.Request) string {
return r.URL.Path
}),

According to https://opentelemetry.io/docs/specs/semconv/http/http-spans/#name:

HTTP span names SHOULD be {method} {target} if there is a (low-cardinality) target available. If there is no (low-cardinality) {target} available, HTTP span names SHOULD be {method}.

I realise it's a SHOULD and not a MUST, but I would expect OpenTelemetry Collector to be setting an example and following documented recommendations. Producing high cardinality span names can be problematic for certain pipelines, e.g. when aggregating spans by name.

Steps to reproduce

  1. Add trace telemetry to examples/local/otel-config.yaml:
$ git diff
diff --git a/examples/local/otel-config.yaml b/examples/local/otel-config.yaml
index 168a1631a..3e6266e70 100644
--- a/examples/local/otel-config.yaml
+++ b/examples/local/otel-config.yaml
@@ -39,3 +39,10 @@ service:
       exporters: [debug]
 
   extensions: [zpages]
+  telemetry:
+    traces:
+      level: basic
+      processors:
+        - batch:
+            exporter:
+              console: {}
  1. make run
  2. curl http://localhost:4318/foo/bar

What did you expect to see?

I would expect to see a span logged with the name GET, or something low-cardinality but more descriptive like GET unknown route.

What did you see instead?

A span is logged with the name /foo/bar:

{                                                                                                                                                                                                                                                       
        "Name": "/foo/bar",                                                                                                                                                                                                                             
        "SpanContext": {                                                                                                                                                                                                                                
                "TraceID": "9a023a975a32440d01b47c6f8f7a60c7",                                                                                                                                                                                          
                "SpanID": "aa890cf63d51904a",                                                                                                                                                                                                           
                "TraceFlags": "01",                                                                                                                                                                                                                     
                "TraceState": "",                                                                                                                                                                                                                       
                "Remote": false                                                                                                                                                                                                                         
        },
...

Collector version

2b5fa0e

Environment information

Environment

OS: Ubuntu 24.04
Compiler: go 1.24.0

OpenTelemetry Collector configuration

extensions:
  zpages:
    endpoint: localhost:55679

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: localhost:4317
      http:
        endpoint: localhost:4318

processors:
  batch:
  memory_limiter:
    # 75% of maximum memory up to 2G
    limit_mib: 1536
    # 25% of limit up to 2G
    spike_limit_mib: 512
    check_interval: 5s

exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [debug]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [debug]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [debug]

  extensions: [zpages]
  telemetry:
    traces:
      level: basic
      processors:
        - batch:
            exporter:
              console: {}

Log output

{
	"Name": "/foo/bar",
	"SpanContext": {
		"TraceID": "ca846f88686dc369615aa615b163a9cb",
		"SpanID": "23a71a43a538f482",
		"TraceFlags": "01",
		"TraceState": "",
		"Remote": false
	},
	"Parent": {
		"TraceID": "00000000000000000000000000000000",
		"SpanID": "0000000000000000",
		"TraceFlags": "00",
		"TraceState": "",
		"Remote": false
	},
	"SpanKind": 2,
	"StartTime": "2025-02-25T11:15:43.641507607+08:00",
	"EndTime": "2025-02-25T11:15:43.641723584+08:00",
	"Attributes": [
		{
			"Key": "http.method",
			"Value": {
				"Type": "STRING",
				"Value": "GET"
			}
		},
		{
			"Key": "http.scheme",
			"Value": {
				"Type": "STRING",
				"Value": "http"
			}
		},
		{
			"Key": "net.host.name",
			"Value": {
				"Type": "STRING",
				"Value": "localhost"
			}
		},
		{
			"Key": "net.host.port",
			"Value": {
				"Type": "INT64",
				"Value": 4318
			}
		},
		{
			"Key": "net.sock.peer.addr",
			"Value": {
				"Type": "STRING",
				"Value": "127.0.0.1"
			}
		},
		{
			"Key": "net.sock.peer.port",
			"Value": {
				"Type": "INT64",
				"Value": 47346
			}
		},
		{
			"Key": "user_agent.original",
			"Value": {
				"Type": "STRING",
				"Value": "curl/8.5.0"
			}
		},
		{
			"Key": "http.target",
			"Value": {
				"Type": "STRING",
				"Value": "/foo/bar"
			}
		},
		{
			"Key": "net.protocol.version",
			"Value": {
				"Type": "STRING",
				"Value": "1.1"
			}
		},
		{
			"Key": "http.response_content_length",
			"Value": {
				"Type": "INT64",
				"Value": 19
			}
		},
		{
			"Key": "http.status_code",
			"Value": {
				"Type": "INT64",
				"Value": 404
			}
		}
	],
	"Events": null,
	"Links": null,
	"Status": {
		"Code": "Unset",
		"Description": ""
	},
	"DroppedAttributes": 0,
	"DroppedEvents": 0,
	"DroppedLinks": 0,
	"ChildSpanCount": 0,
	"Resource": [
		{
			"Key": "service.instance.id",
			"Value": {
				"Type": "STRING",
				"Value": "1dd05082-b413-4990-af89-04751084d903"
			}
		},
		{
			"Key": "service.name",
			"Value": {
				"Type": "STRING",
				"Value": "otelcorecol"
			}
		},
		{
			"Key": "service.version",
			"Value": {
				"Type": "STRING",
				"Value": "0.120.0-dev"
			}
		}
	],
	"InstrumentationScope": {
		"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
		"Version": "0.59.0",
		"SchemaURL": "",
		"Attributes": null
	},
	"InstrumentationLibrary": {
		"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
		"Version": "0.59.0",
		"SchemaURL": "",
		"Attributes": null
	}
}

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions