Skip to content

Commit 7e91018

Browse files
adamwclaude
andcommitted
Remove url.full from default OpenTelemetry metrics attributes
The full URL is a high-cardinality attribute that can cause metric explosion. Remove it from the default request attributes while keeping it available via requestAttributesWithFullUrl for users who need it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 831b2e7 commit 7e91018

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryDefaults.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package sttp.client4.opentelemetry
33
import sttp.client4.GenericRequest
44
import io.opentelemetry.api.common.Attributes
55
import io.opentelemetry.semconv.HttpAttributes
6-
import sttp.client4.Response
76
import io.opentelemetry.semconv.UrlAttributes
87
import io.opentelemetry.semconv.ErrorAttributes
98
import io.opentelemetry.semconv.ServerAttributes
@@ -28,7 +27,6 @@ object OpenTelemetryDefaults {
2827
private def requestAttributesBuilder(request: GenericRequest[_, _]): AttributesBuilder =
2928
Attributes.builder
3029
.put(HttpAttributes.HTTP_REQUEST_METHOD, request.method.method)
31-
.put(UrlAttributes.URL_FULL, request.uri.toString())
3230
.put(ServerAttributes.SERVER_ADDRESS, request.uri.host.getOrElse("unknown"))
3331
.put(ServerAttributes.SERVER_PORT, request.uri.port.getOrElse(80))
3432

observability/opentelemetry-backend/src/test/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackendTest.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,42 @@ class OpenTelemetryMetricsBackendTest extends AnyFlatSpec with Matchers with Opt
276276
.find(_.getName.equals(name))
277277
.head
278278

279+
it should "not include url.full in default request attributes to avoid high cardinality" in {
280+
// given
281+
val reader = InMemoryMetricReader.create()
282+
val backend = OpenTelemetryMetricsBackend(stubAlwaysOk, spawnNewOpenTelemetry(reader))
283+
284+
// when
285+
basicRequest.get(uri"http://127.0.0.1/foo?bar=1").send(backend)
286+
287+
// then
288+
val metrics = reader.collectAllMetrics().asScala.toList
289+
val metric = metrics.find(_.getName == OpenTelemetryMetricsBackend.DefaultLatencyHistogramName).value
290+
metric.getHistogramData.getPoints.forEach { point =>
291+
point.getAttributes.get(AttributeKey.stringKey("url.full")) shouldBe null
292+
}
293+
}
294+
295+
it should "include url.full when using requestAttributesWithFullUrl" in {
296+
// given
297+
val reader = InMemoryMetricReader.create()
298+
val config = OpenTelemetryMetricsConfig(
299+
spawnNewOpenTelemetry(reader),
300+
requestAttributes = OpenTelemetryDefaults.requestAttributesWithFullUrl _
301+
)
302+
val backend = OpenTelemetryMetricsBackend(stubAlwaysOk, config)
303+
304+
// when
305+
basicRequest.get(uri"http://127.0.0.1/foo?bar=1").send(backend)
306+
307+
// then
308+
val metrics = reader.collectAllMetrics().asScala.toList
309+
val metric = metrics.find(_.getName == OpenTelemetryMetricsBackend.DefaultLatencyHistogramName).value
310+
metric.getHistogramData.getPoints.forEach { point =>
311+
point.getAttributes.get(AttributeKey.stringKey("url.full")) shouldBe "http://127.0.0.1/foo?bar=1"
312+
}
313+
}
314+
279315
private[this] def specTest(metrics: List[MetricData], expectedMetricName: String): Unit = {
280316
val metric = metrics.find(_.getName == expectedMetricName)
281317
assert(

0 commit comments

Comments
 (0)