Describe the bug
Enabling Data Saver with:
GRAFANA_OTEL_APPLICATION_OBSERVABILITY_METRICS=true
causes http.server.request.duration to be aggregated with high-cardinality HTTP attributes, including network.peer.port, url.query, and user_agent.original.
With the flag disabled, the same instrument uses the expected filtered attribute set.
After normal application traffic, the Java SDK reaches the default per-instrument cardinality limit:
[otel.javaagent 2026-07-20 06:48:51:261 +0000] [http-nio-8081-exec-5] WARN io.opentelemetry.sdk.metrics.internal.state.DefaultSynchronousMetricStorage - Instrument http.server.request.duration has exceeded the maximum allowed cardinality (1999).
Data Saver reduces the number of metric names, but for this retained instrument it substantially increases the number of time series.
Steps to reproduce
-
Run a Spring Boot/Tomcat application with grafana-opentelemetry-java.jar v2.29.0.
-
Enable console metric export to inspect the metric datapoints:
OTEL_METRICS_EXPORTER=otlp,console
OTEL_METRIC_EXPORT_INTERVAL=10000
-
Start once with:
GRAFANA_OTEL_APPLICATION_OBSERVABILITY_METRICS=false
-
Send HTTP requests and inspect http.server.request.duration.
-
Restart with:
GRAFANA_OTEL_APPLICATION_OBSERVABILITY_METRICS=true
-
Send the same traffic and inspect the metric again.
-
With sustained traffic/new client connections, observe the cardinality warning at 1999 series.
Flag disabled
A representative datapoint contains only the bounded HTTP attributes:
name=http.server.request.duration
instrumentationScope=io.opentelemetry.tomcat-10.0
attributes=FilteredAttributes{
http.request.method=POST,
http.response.status_code=204,
http.route=/login/impersonate,
network.protocol.version=1.1,
url.scheme=http
}
Across the observed requests, the available/expected dimensions are:
http.request.method
http.response.status_code
http.route
error.type
network.protocol.name
network.protocol.version
url.scheme
Flag enabled
The same instrument contains the full HTTP request attribute set:
name=http.server.request.duration
instrumentationScope=io.opentelemetry.tomcat-10.0
attributes={
client.address=<redacted>,
http.request.method=POST,
http.response.status_code=204,
http.route=/login/impersonate,
network.peer.address=<redacted>,
network.peer.port=50390,
network.protocol.version=1.1,
server.address=<redacted>,
server.port=8081,
url.path=/login/impersonate,
url.query=<redacted>,
url.scheme=http,
user_agent.original=<redacted>
}
In particular:
network.peer.port changes for client TCP connections.
url.query may change per request and may contain sensitive values.
user_agent.original, client addresses, and peer addresses add further dimensions.
Expected behavior
Data Saver should reduce the set of exported metric instruments without broadening the attribute set of retained instruments.
http.server.request.duration should continue to use the upstream instrumentation's bounded attribute advice:
http.request.method
http.response.status_code
http.route
error.type
network.protocol.name
network.protocol.version
url.scheme
Enabling Data Saver should not cause the application to reach the SDK's 2000-series cardinality limit.
Actual behavior
With Data Saver disabled, the console exporter prints FilteredAttributes containing the bounded HTTP attributes.
With Data Saver enabled, the console exporter prints an unfiltered attribute map containing ephemeral peer ports, query strings, user agents, and addresses. This creates thousands of distinct series for http.server.request.duration and eventually produces:
Instrument http.server.request.duration has exceeded the maximum allowed cardinality (1999).
Environment
JDK: OpenJDK 25.0.2
OS: macOS 26.5.1, aarch64
Framework: Spring Boot 4.1.0, Spring Framework 7.0.8
Server: embedded Tomcat 11.0.22
Grafana Java agent: v2.29.0
Describe the bug
Enabling Data Saver with:
causes
http.server.request.durationto be aggregated with high-cardinality HTTP attributes, includingnetwork.peer.port,url.query, anduser_agent.original.With the flag disabled, the same instrument uses the expected filtered attribute set.
After normal application traffic, the Java SDK reaches the default per-instrument cardinality limit:
Data Saver reduces the number of metric names, but for this retained instrument it substantially increases the number of time series.
Steps to reproduce
Run a Spring Boot/Tomcat application with
grafana-opentelemetry-java.jarv2.29.0.Enable console metric export to inspect the metric datapoints:
Start once with:
Send HTTP requests and inspect
http.server.request.duration.Restart with:
Send the same traffic and inspect the metric again.
With sustained traffic/new client connections, observe the cardinality warning at 1999 series.
Flag disabled
A representative datapoint contains only the bounded HTTP attributes:
Across the observed requests, the available/expected dimensions are:
Flag enabled
The same instrument contains the full HTTP request attribute set:
In particular:
network.peer.portchanges for client TCP connections.url.querymay change per request and may contain sensitive values.user_agent.original, client addresses, and peer addresses add further dimensions.Expected behavior
Data Saver should reduce the set of exported metric instruments without broadening the attribute set of retained instruments.
http.server.request.durationshould continue to use the upstream instrumentation's bounded attribute advice:Enabling Data Saver should not cause the application to reach the SDK's 2000-series cardinality limit.
Actual behavior
With Data Saver disabled, the console exporter prints
FilteredAttributescontaining the bounded HTTP attributes.With Data Saver enabled, the console exporter prints an unfiltered attribute map containing ephemeral peer ports, query strings, user agents, and addresses. This creates thousands of distinct series for
http.server.request.durationand eventually produces:Environment
JDK: OpenJDK 25.0.2
OS: macOS 26.5.1, aarch64
Framework: Spring Boot 4.1.0, Spring Framework 7.0.8
Server: embedded Tomcat 11.0.22
Grafana Java agent: v2.29.0