diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecorator.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecorator.java index d4b57da9808..22a74e3a344 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecorator.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecorator.java @@ -626,7 +626,12 @@ public ResponseHeaderTagClassifier(AgentSpan span, Map headerTag public boolean accept(String key, String value) { String mappedKey = headerTags.get(key.toLowerCase(Locale.ROOT)); if (mappedKey != null) { - span.setTag(mappedKey, value); + Object existing_val = span.getTag(mappedKey); + if (existing_val == null) { + span.setTag(mappedKey, value); + } else { + span.setTag(mappedKey, existing_val.toString() + value); + } } return true; } diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy index 22d8dd0028e..1b8b1f255df 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy @@ -702,6 +702,44 @@ abstract class HttpServerTest extends WithHttpServer { 'GET' | null | 'x-datadog-test-request-header' | 'bar' | [ 'request_header_tag': 'bar' ] } + def "test response header tag mapping"() { + setup: + assumeTrue(testResponseHeadersMapping() && testEncodedQuery()) + def endpoint = QUERY_ENCODED_BOTH + def method = 'GET' + def body = null + def header = 'response_header_tag' + def mapping = 'mapped_response_header_tag' + def tags = ['mapped_response_header_tag': 'response_header_value' ] + def more_tags = ['mapped_response_header_tag': "another_response_header_value" ] + + injectSysConfig(HTTP_SERVER_TAG_QUERY_STRING, "true") + injectSysConfig(RESPONSE_HEADER_TAGS, "$header:$mapping") + def request = request(endpoint, method, body) + .build() + def response = client.newCall(request).execute() + + expect: + response.code() == endpoint.status + response.body().string() == endpoint.body + + and: + assertTraces(1) { + trace(spanCount(endpoint)) { + sortSpansByStart() + serverSpan(it, null, null, method, endpoint, tags) + serverSpan(it, null, null, method, endpoint, more_tags) // ... + if (hasHandlerSpan()) { + handlerSpan(it, endpoint) + } + controllerSpan(it) + if (hasResponseSpan(endpoint)) { + responseSpan(it, endpoint) + } + } + } + } + @Flaky(value = "https://github.com/DataDog/dd-trace-java/issues/4690", suites = ["MuleHttpServerForkedTest"]) def "test QUERY_ENCODED_BOTH with response header x-ig-response-header tag mapping"() { setup: