Add `http.route` to the server span when `ServerSpanNaming` is updated (#5086)

* Add `http.route` to the server span when `ServerSpanNaming` is updated

* fix camel tests

* fix test compilation failure

* assert route in camel instrumentation
This commit is contained in:
Mateusz Rzeszutek 2022-01-14 22:52:06 +01:00 committed by GitHub
parent 40ce04028a
commit 872c6c7d80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 419 additions and 132 deletions

View File

@ -9,13 +9,15 @@ import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.context.ContextKey; import io.opentelemetry.context.ContextKey;
import io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer; import io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import javax.annotation.Nullable; import javax.annotation.Nullable;
// TODO: move to ...instrumenter.http and rename to HttpRouteHolder (?)
/** Helper container for tracking whether instrumentation should update server span name or not. */ /** Helper container for tracking whether instrumentation should update server span name or not. */
public final class ServerSpanNaming { public final class ServerSpanNaming {
private static final ContextKey<ServerSpanNaming> CONTEXT_KEY = private static final ContextKey<ServerSpanNaming> CONTEXT_KEY =
ContextKey.named("opentelemetry-servlet-span-naming-key"); ContextKey.named("opentelemetry-http-server-route-key");
public static <REQUEST> ContextCustomizer<REQUEST> get() { public static <REQUEST> ContextCustomizer<REQUEST> get() {
return (context, request, startAttributes) -> { return (context, request, startAttributes) -> {
@ -27,9 +29,7 @@ public final class ServerSpanNaming {
} }
private volatile Source updatedBySource; private volatile Source updatedBySource;
// Length of the currently set name. This is used when setting name from a servlet filter @Nullable private volatile String route;
// to pick the most descriptive (longest) name.
private volatile int nameLength;
private ServerSpanNaming(Source initialSource) { private ServerSpanNaming(Source initialSource) {
this.updatedBySource = initialSource; this.updatedBySource = initialSource;
@ -78,7 +78,7 @@ public final class ServerSpanNaming {
if (serverSpanNaming == null) { if (serverSpanNaming == null) {
String name = serverSpanName.get(context, arg1, arg2); String name = serverSpanName.get(context, arg1, arg2);
if (name != null && !name.isEmpty()) { if (name != null && !name.isEmpty()) {
serverSpan.updateName(name); updateSpanData(serverSpan, name);
} }
return; return;
} }
@ -91,15 +91,33 @@ public final class ServerSpanNaming {
if (name != null if (name != null
&& !name.isEmpty() && !name.isEmpty()
&& (!onlyIfBetterName || serverSpanNaming.isBetterName(name))) { && (!onlyIfBetterName || serverSpanNaming.isBetterName(name))) {
serverSpan.updateName(name); updateSpanData(serverSpan, name);
serverSpanNaming.updatedBySource = source; serverSpanNaming.updatedBySource = source;
serverSpanNaming.nameLength = name.length(); serverSpanNaming.route = name;
} }
} }
} }
// TODO: instead of calling setAttribute() consider storing the route in context end retrieving it
// in the AttributesExtractor
private static void updateSpanData(Span serverSpan, String route) {
serverSpan.updateName(route);
serverSpan.setAttribute(SemanticAttributes.HTTP_ROUTE, route);
}
// This is used when setting name from a servlet filter to pick the most descriptive (longest)
// route.
private boolean isBetterName(String name) { private boolean isBetterName(String name) {
return name.length() > nameLength; String route = this.route;
int routeLength = route == null ? 0 : route.length();
return name.length() > routeLength;
}
// TODO: use that in HttpServerMetrics
@Nullable
public static String getRoute(Context context) {
ServerSpanNaming serverSpanNaming = context.get(CONTEXT_KEY);
return serverSpanNaming == null ? null : serverSpanNaming.route;
} }
public enum Source { public enum Source {

View File

@ -3,8 +3,10 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest<Object> implements AgentTestTrait { abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest<Object> implements AgentTestTrait {
@ -28,6 +30,13 @@ abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest<Object>
boolean testCapturedHttpHeaders() { boolean testCapturedHttpHeaders() {
false false
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
} }
class AkkaHttpServerInstrumentationTestSync extends AkkaHttpServerInstrumentationTest { class AkkaHttpServerInstrumentationTestSync extends AkkaHttpServerInstrumentationTest {

View File

@ -121,6 +121,7 @@ class HttpSpanDecorator extends BaseSpanDecorator {
private void updateServerSpanName(Span serverSpan, Exchange exchange, Endpoint endpoint) { private void updateServerSpanName(Span serverSpan, Exchange exchange, Endpoint endpoint) {
String path = getPath(exchange, endpoint); String path = getPath(exchange, endpoint);
if (path != null) { if (path != null) {
// TODO should update SERVER span name/route using ServerSpanNaming
serverSpan.updateName(path); serverSpan.updateName(path);
} }
} }

View File

@ -5,8 +5,6 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel package io.opentelemetry.javaagent.instrumentation.apachecamel
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.instrumentation.test.RetryOnAddressAlreadyInUseTrait import io.opentelemetry.instrumentation.test.RetryOnAddressAlreadyInUseTrait
import io.opentelemetry.instrumentation.test.utils.PortUtils import io.opentelemetry.instrumentation.test.utils.PortUtils
@ -20,6 +18,7 @@ import spock.lang.Shared
import static io.opentelemetry.api.trace.SpanKind.CLIENT import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.SpanKind.INTERNAL import static io.opentelemetry.api.trace.SpanKind.INTERNAL
import static io.opentelemetry.api.trace.SpanKind.SERVER import static io.opentelemetry.api.trace.SpanKind.SERVER
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
class RestCamelTest extends AgentInstrumentationSpecification implements RetryOnAddressAlreadyInUseTrait { class RestCamelTest extends AgentInstrumentationSpecification implements RetryOnAddressAlreadyInUseTrait {
@ -100,6 +99,8 @@ class RestCamelTest extends AgentInstrumentationSpecification implements RetryOn
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
// TODO: camel instrumentation does not use ServerSpanNaming to update the route, so the matched route is provided by the servlet instrumentation
"$SemanticAttributes.HTTP_ROUTE" "/*"
} }
} }
it.span(3) { it.span(3) {

View File

@ -5,8 +5,6 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel package io.opentelemetry.javaagent.instrumentation.apachecamel
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.instrumentation.test.RetryOnAddressAlreadyInUseTrait import io.opentelemetry.instrumentation.test.RetryOnAddressAlreadyInUseTrait
import io.opentelemetry.instrumentation.test.utils.PortUtils import io.opentelemetry.instrumentation.test.utils.PortUtils
@ -22,6 +20,7 @@ import spock.lang.Shared
import static io.opentelemetry.api.trace.SpanKind.CLIENT import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.SpanKind.INTERNAL import static io.opentelemetry.api.trace.SpanKind.INTERNAL
import static io.opentelemetry.api.trace.SpanKind.SERVER import static io.opentelemetry.api.trace.SpanKind.SERVER
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
class TwoServicesWithDirectClientCamelTest extends AgentInstrumentationSpecification implements RetryOnAddressAlreadyInUseTrait { class TwoServicesWithDirectClientCamelTest extends AgentInstrumentationSpecification implements RetryOnAddressAlreadyInUseTrait {
@ -136,6 +135,8 @@ class TwoServicesWithDirectClientCamelTest extends AgentInstrumentationSpecifica
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
// TODO: camel instrumentation does not use ServerSpanNaming to update the route, so the matched route is provided by the servlet instrumentation
"$SemanticAttributes.HTTP_ROUTE" "/*"
} }
} }
it.span(5) { it.span(5) {

View File

@ -29,6 +29,7 @@ import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEn
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.INDEXED_CHILD import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.INDEXED_CHILD
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT
@ -38,12 +39,23 @@ abstract class AbstractArmeriaHttpServerTest extends HttpServerTest<Server> {
abstract ServerBuilder configureServer(ServerBuilder serverBuilder) abstract ServerBuilder configureServer(ServerBuilder serverBuilder)
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
// TODO(anuraaga): Revisit this when applying instrumenters to more libraries, Armeria
// currently reports '/*' which is a fallback route.
return "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[ [
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH, SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
SemanticAttributes.HTTP_ROUTE,
SemanticAttributes.HTTP_SERVER_NAME, SemanticAttributes.HTTP_SERVER_NAME,
SemanticAttributes.NET_PEER_NAME, SemanticAttributes.NET_PEER_NAME,
SemanticAttributes.NET_TRANSPORT SemanticAttributes.NET_TRANSPORT

View File

@ -93,14 +93,14 @@ class DropwizardTest extends HttpServerTest<DropwizardTestSupport> implements Ag
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM:
return "/path/{id}/param"
case NOT_FOUND: case NOT_FOUND:
return "/*" return getContextPath() + "/*"
case PATH_PARAM:
return getContextPath() + "/path/{id}/param"
default: default:
return endpoint.resolvePath(address).path return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -66,7 +66,7 @@ class GrailsTest extends HttpServerTest<ConfigurableApplicationContext> implemen
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
if (endpoint == PATH_PARAM) { if (endpoint == PATH_PARAM) {
return getContextPath() + "/test/path" return getContextPath() + "/test/path"
} else if (endpoint == QUERY_PARAM) { } else if (endpoint == QUERY_PARAM) {

View File

@ -3,9 +3,10 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import java.nio.charset.StandardCharsets import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.glassfish.grizzly.filterchain.BaseFilter import org.glassfish.grizzly.filterchain.BaseFilter
import org.glassfish.grizzly.filterchain.FilterChain import org.glassfish.grizzly.filterchain.FilterChain
import org.glassfish.grizzly.filterchain.FilterChainBuilder import org.glassfish.grizzly.filterchain.FilterChainBuilder
@ -25,6 +26,7 @@ import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder
import org.glassfish.grizzly.utils.DelayedExecutor import org.glassfish.grizzly.utils.DelayedExecutor
import org.glassfish.grizzly.utils.IdleTimeoutFilter import org.glassfish.grizzly.utils.IdleTimeoutFilter
import java.nio.charset.StandardCharsets
import java.util.concurrent.Executors import java.util.concurrent.Executors
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED
@ -61,6 +63,18 @@ class GrizzlyFilterchainServerTest extends HttpServerTest<HttpServer> implements
transport.shutdownNow() transport.shutdownNow()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET"
}
@Override @Override
boolean testException() { boolean testException() {
// justification: grizzly async closes the channel which // justification: grizzly async closes the channel which
@ -230,9 +244,4 @@ class GrizzlyFilterchainServerTest extends HttpServerTest<HttpServer> implements
} }
} }
} }
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET"
}
} }

View File

@ -3,8 +3,10 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.glassfish.grizzly.http.server.HttpHandler import org.glassfish.grizzly.http.server.HttpHandler
import org.glassfish.grizzly.http.server.HttpServer import org.glassfish.grizzly.http.server.HttpServer
import org.glassfish.grizzly.http.server.Request import org.glassfish.grizzly.http.server.Request
@ -42,6 +44,18 @@ class GrizzlyTest extends HttpServerTest<HttpServer> implements AgentTestTrait {
return server return server
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET"
}
@Override @Override
void stopServer(HttpServer server) { void stopServer(HttpServer server) {
server.stop() server.stop()
@ -108,11 +122,6 @@ class GrizzlyTest extends HttpServerTest<HttpServer> implements AgentTestTrait {
} }
} }
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET"
}
static class ExceptionHttpHandler extends HttpHandler { static class ExceptionHttpHandler extends HttpHandler {
@Override @Override

View File

@ -36,6 +36,7 @@ class JaxRsAnnotations1InstrumentationTest extends AgentInstrumentationSpecifica
kind SERVER kind SERVER
hasNoParent() hasNoParent()
attributes { attributes {
"$SemanticAttributes.HTTP_ROUTE" paramName
} }
} }
span(1) { span(1) {

View File

@ -38,9 +38,10 @@ class JerseyTest extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 2) { trace(0, 2) {
span(0) { span(0) {
name expectedSpanName name expectedRoute
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.HTTP_ROUTE" expectedRoute
} }
} }
@ -56,7 +57,7 @@ class JerseyTest extends AgentInstrumentationSpecification {
} }
where: where:
resource | expectedSpanName | controllerName | expectedResponse resource | expectedRoute | controllerName | expectedResponse
"/test/hello/bob" | "/test/hello/{name}" | "Test1.hello" | "Test1 bob!" "/test/hello/bob" | "/test/hello/{name}" | "Test1.hello" | "Test1 bob!"
"/test2/hello/bob" | "/test2/hello/{name}" | "Test2.hello" | "Test2 bob!" "/test2/hello/bob" | "/test2/hello/{name}" | "Test2.hello" | "Test2 bob!"
"/test3/hi/bob" | "/test3/hi/{name}" | "Test3.hello" | "Test3 bob!" "/test3/hi/bob" | "/test3/hi/{name}" | "Test3.hello" | "Test3 bob!"
@ -76,9 +77,10 @@ class JerseyTest extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 2) { trace(0, 2) {
span(0) { span(0) {
name expectedSpanName name expectedRoute
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.HTTP_ROUTE" expectedRoute
} }
} }
span(1) { span(1) {
@ -94,7 +96,7 @@ class JerseyTest extends AgentInstrumentationSpecification {
} }
where: where:
resource | expectedSpanName | controller1Name | expectedResponse resource | expectedRoute | controller1Name | expectedResponse
"/test3/nested" | "/test3/nested" | "Test3.nested" | "Test3 nested!" "/test3/nested" | "/test3/nested" | "Test3.nested" | "Test3 nested!"
} }
} }

View File

@ -135,6 +135,7 @@ abstract class JaxRsFilterTest extends AgentInstrumentationSpecification {
kind SERVER kind SERVER
if (!runsOnServer()) { if (!runsOnServer()) {
attributes { attributes {
"$SemanticAttributes.HTTP_ROUTE" parentResourceName
} }
} }
} }

View File

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.asserts.TraceAssert
@ -20,6 +18,7 @@ import static io.opentelemetry.api.trace.StatusCode.ERROR
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
import static java.util.concurrent.TimeUnit.SECONDS import static java.util.concurrent.TimeUnit.SECONDS
import static org.junit.jupiter.api.Assumptions.assumeTrue import static org.junit.jupiter.api.Assumptions.assumeTrue
@ -287,6 +286,7 @@ abstract class JaxRsHttpServerTest<S> extends HttpServerTest<S> implements Agent
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } // Optional "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } // Optional
"$SemanticAttributes.HTTP_ROUTE" path
if (fullUrl.getPath().endsWith(ServerEndpoint.CAPTURE_HEADERS.getPath())) { if (fullUrl.getPath().endsWith(ServerEndpoint.CAPTURE_HEADERS.getPath())) {
"http.request.header.x_test_request" { it == ["test"] } "http.request.header.x_test_request" { it == ["test"] }
"http.response.header.x_test_response" { it == ["test"] } "http.response.header.x_test_response" { it == ["test"] }

View File

@ -36,6 +36,7 @@ abstract class JaxrsAnnotationsInstrumentationTest extends AgentInstrumentationS
kind SERVER kind SERVER
hasNoParent() hasNoParent()
attributes { attributes {
"$SemanticAttributes.HTTP_ROUTE" paramName
} }
} }
span(1) { span(1) {

View File

@ -141,6 +141,13 @@ class JettyHandlerTest extends HttpServerTest<Server> implements AgentTestTrait
} }
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
"HTTP GET" "HTTP GET"

View File

@ -142,6 +142,13 @@ class JettyHandlerTest extends HttpServerTest<Server> implements AgentTestTrait
} }
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
"HTTP GET" "HTTP GET"

View File

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.instrumentation.test.utils.PortUtils import io.opentelemetry.instrumentation.test.utils.PortUtils
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
@ -23,6 +21,7 @@ import java.nio.file.Files
import static io.opentelemetry.api.trace.SpanKind.SERVER import static io.opentelemetry.api.trace.SpanKind.SERVER
import static io.opentelemetry.api.trace.StatusCode.ERROR import static io.opentelemetry.api.trace.StatusCode.ERROR
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
//TODO should this be HttpServerTest? //TODO should this be HttpServerTest?
class JspInstrumentationBasicTests extends AgentInstrumentationSpecification { class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
@ -85,15 +84,17 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 3) { trace(0, 3) {
span(0) { span(0) {
def route = "/$jspWebappContext/$jspFileName"
hasNoParent() hasNoParent()
name "/$jspWebappContext/$jspFileName" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/$jspFileName" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
@ -101,6 +102,7 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } // Optional "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } // Optional
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -140,21 +142,24 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 3) { trace(0, 3) {
span(0) { span(0) {
def route = "/$jspWebappContext/getQuery.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/getQuery.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/getQuery.jsp?$queryString" "$SemanticAttributes.HTTP_TARGET" "$route?$queryString"
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -190,15 +195,17 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 3) { trace(0, 3) {
span(0) { span(0) {
def route = "/$jspWebappContext/post.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/post.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/post.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "POST" "$SemanticAttributes.HTTP_METHOD" "POST"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
@ -206,6 +213,7 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -237,8 +245,10 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 3) { trace(0, 3) {
span(0) { span(0) {
def route = "/$jspWebappContext/$jspFileName"
hasNoParent() hasNoParent()
name "/$jspWebappContext/$jspFileName" name route
kind SERVER kind SERVER
status ERROR status ERROR
event(0) { event(0) {
@ -258,13 +268,14 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/$jspFileName" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 500 "$SemanticAttributes.HTTP_STATUS_CODE" 500
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -314,21 +325,24 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 3) { trace(0, 3) {
span(0) { span(0) {
def route = "/$jspWebappContext/includes/includeHtml.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/includes/includeHtml.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/includes/includeHtml.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -359,21 +373,24 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 7) { trace(0, 7) {
span(0) { span(0) {
def route = "/$jspWebappContext/includes/includeMulti.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/includes/includeMulti.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/includes/includeMulti.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -434,8 +451,10 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 2) { trace(0, 2) {
span(0) { span(0) {
def route = "/$jspWebappContext/$jspFileName"
hasNoParent() hasNoParent()
name "/$jspWebappContext/$jspFileName" name route
kind SERVER kind SERVER
status ERROR status ERROR
errorEvent(JasperException, String) errorEvent(JasperException, String)
@ -444,13 +463,14 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/$jspFileName" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 500 "$SemanticAttributes.HTTP_STATUS_CODE" 500
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -482,8 +502,10 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 1) { trace(0, 1) {
span(0) { span(0) {
def route = "/$jspWebappContext/*"
hasNoParent() hasNoParent()
name "/$jspWebappContext/*" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
@ -497,6 +519,7 @@ class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
} }

View File

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.instrumentation.test.utils.PortUtils import io.opentelemetry.instrumentation.test.utils.PortUtils
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
@ -21,6 +19,7 @@ import java.nio.file.Files
import static io.opentelemetry.api.trace.SpanKind.SERVER import static io.opentelemetry.api.trace.SpanKind.SERVER
import static io.opentelemetry.api.trace.StatusCode.ERROR import static io.opentelemetry.api.trace.StatusCode.ERROR
import static io.opentelemetry.api.trace.StatusCode.UNSET import static io.opentelemetry.api.trace.StatusCode.UNSET
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
class JspInstrumentationForwardTests extends AgentInstrumentationSpecification { class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
@ -83,21 +82,24 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 5) { trace(0, 5) {
span(0) { span(0) {
def route = "/$jspWebappContext/$forwardFromFileName"
hasNoParent() hasNoParent()
name "/$jspWebappContext/$forwardFromFileName" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/$forwardFromFileName" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -149,21 +151,24 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 3) { trace(0, 3) {
span(0) { span(0) {
def route = "/$jspWebappContext/forwards/forwardToHtml.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/forwards/forwardToHtml.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/forwards/forwardToHtml.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -194,21 +199,24 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 9) { trace(0, 9) {
span(0) { span(0) {
def route = "/$jspWebappContext/forwards/forwardToIncludeMulti.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/forwards/forwardToIncludeMulti.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/forwards/forwardToIncludeMulti.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -287,21 +295,24 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 7) { trace(0, 7) {
span(0) { span(0) {
def route = "/$jspWebappContext/forwards/forwardToJspForward.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/forwards/forwardToJspForward.jsp" name route
kind SERVER kind SERVER
attributes { attributes {
"$SemanticAttributes.NET_PEER_IP" "127.0.0.1" "$SemanticAttributes.NET_PEER_IP" "127.0.0.1"
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/forwards/forwardToJspForward.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 200 "$SemanticAttributes.HTTP_STATUS_CODE" 200
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -364,8 +375,10 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 4) { trace(0, 4) {
span(0) { span(0) {
def route = "/$jspWebappContext/forwards/forwardToCompileError.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/forwards/forwardToCompileError.jsp" name route
kind SERVER kind SERVER
status ERROR status ERROR
errorEvent(JasperException, String) errorEvent(JasperException, String)
@ -374,13 +387,14 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/forwards/forwardToCompileError.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 500 "$SemanticAttributes.HTTP_STATUS_CODE" 500
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {
@ -423,8 +437,10 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
assertTraces(1) { assertTraces(1) {
trace(0, 4) { trace(0, 4) {
span(0) { span(0) {
def route = "/$jspWebappContext/forwards/forwardToNonExistent.jsp"
hasNoParent() hasNoParent()
name "/$jspWebappContext/forwards/forwardToNonExistent.jsp" name route
kind SERVER kind SERVER
status UNSET status UNSET
attributes { attributes {
@ -432,13 +448,14 @@ class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
"$SemanticAttributes.NET_PEER_PORT" Long "$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_HOST" "localhost:$port" "$SemanticAttributes.HTTP_HOST" "localhost:$port"
"$SemanticAttributes.HTTP_TARGET" "/$jspWebappContext/forwards/forwardToNonExistent.jsp" "$SemanticAttributes.HTTP_TARGET" route
"$SemanticAttributes.HTTP_METHOD" "GET" "$SemanticAttributes.HTTP_METHOD" "GET"
"$SemanticAttributes.HTTP_STATUS_CODE" 404 "$SemanticAttributes.HTTP_STATUS_CODE" 404
"$SemanticAttributes.HTTP_FLAVOR" "1.1" "$SemanticAttributes.HTTP_FLAVOR" "1.1"
"$SemanticAttributes.HTTP_USER_AGENT" String "$SemanticAttributes.HTTP_USER_AGENT" String
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_ROUTE" route
} }
} }
span(1) { span(1) {

View File

@ -13,7 +13,7 @@ import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM
class KtorHttpServerTest extends HttpServerTest<ApplicationEngine> implements LibraryTestTrait { class KtorHttpServerTest extends HttpServerTest<ApplicationEngine> implements LibraryTestTrait {
@ -34,13 +34,24 @@ class KtorHttpServerTest extends HttpServerTest<ApplicationEngine> implements Li
return false return false
} }
@Override
boolean testPathParam() {
true
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
def route = expectedHttpRoute(endpoint)
return route == null ? "HTTP GET" : route
}
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case NOT_FOUND: case PATH_PARAM:
return "HTTP GET" return getContextPath() + "/path/{id}/param"
default: default:
return endpoint.resolvePath(address).path return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -3,8 +3,10 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.jboss.netty.bootstrap.ServerBootstrap import org.jboss.netty.bootstrap.ServerBootstrap
import org.jboss.netty.buffer.ChannelBuffer import org.jboss.netty.buffer.ChannelBuffer
import org.jboss.netty.buffer.ChannelBuffers import org.jboss.netty.buffer.ChannelBuffers
@ -159,6 +161,13 @@ class Netty38ServerTest extends HttpServerTest<ServerBootstrap> implements Agent
server?.shutdown() server?.shutdown()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET" return "HTTP GET"

View File

@ -24,8 +24,10 @@ import io.netty.handler.codec.http.QueryStringDecoder
import io.netty.handler.logging.LogLevel import io.netty.handler.logging.LogLevel
import io.netty.handler.logging.LoggingHandler import io.netty.handler.logging.LoggingHandler
import io.netty.util.CharsetUtil import io.netty.util.CharsetUtil
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE
@ -128,6 +130,13 @@ class Netty40ServerTest extends HttpServerTest<EventLoopGroup> implements AgentT
server?.shutdownGracefully() server?.shutdownGracefully()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET" return "HTTP GET"

View File

@ -23,8 +23,10 @@ import io.netty.handler.codec.http.QueryStringDecoder
import io.netty.handler.logging.LogLevel import io.netty.handler.logging.LogLevel
import io.netty.handler.logging.LoggingHandler import io.netty.handler.logging.LoggingHandler
import io.netty.util.CharsetUtil import io.netty.util.CharsetUtil
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE
@ -127,6 +129,13 @@ class Netty41ServerTest extends HttpServerTest<EventLoopGroup> implements AgentT
server?.shutdownGracefully() server?.shutdownGracefully()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET" return "HTTP GET"

View File

@ -5,12 +5,13 @@
package server package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.trace.StatusCode import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.sdk.trace.data.SpanData import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import play.mvc.Results import play.mvc.Results
import play.routing.RoutingDsl import play.routing.RoutingDsl
import play.server.Server import play.server.Server
@ -102,6 +103,13 @@ class PlayServerTest extends HttpServerTest<Server> implements AgentTestTrait {
} }
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET" return "HTTP GET"

View File

@ -5,11 +5,13 @@
package server package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.trace.StatusCode import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.sdk.trace.data.SpanData import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import play.BuiltInComponents import play.BuiltInComponents
import play.Mode import play.Mode
import play.mvc.Controller import play.mvc.Controller
@ -99,6 +101,13 @@ class PlayServerTest extends HttpServerTest<Server> implements AgentTestTrait {
} }
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "akka.request" return "akka.request"

View File

@ -152,7 +152,7 @@ abstract class AbstractRatpackHttpServerTest extends HttpServerTest<RatpackServe
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
return endpoint.status == 404 ? "/" : endpoint == PATH_PARAM ? "/path/:id/param" : endpoint.path return endpoint.status == 404 ? "/" : endpoint == PATH_PARAM ? "/path/:id/param" : endpoint.path
} }
} }

View File

@ -128,14 +128,10 @@ abstract class AbstractRatpackRoutesTest extends InstrumentationSpecification {
if (extraAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) { if (extraAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
} }
if (extraAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
// TODO(anuraaga): Revisit this when applying instrumenters to more libraries, Armeria
// currently reports '/*' which is a fallback route.
"$SemanticAttributes.HTTP_ROUTE" String
}
if (extraAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) { if (extraAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) {
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
} }
"$SemanticAttributes.HTTP_ROUTE" "/$route"
} }
} }
if (hasHandlerSpan()) { if (hasHandlerSpan()) {

View File

@ -28,7 +28,6 @@ class RatpackRoutesTest extends AbstractRatpackRoutesTest implements LibraryTest
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
return [ return [
SemanticAttributes.HTTP_ROUTE,
SemanticAttributes.NET_TRANSPORT SemanticAttributes.NET_TRANSPORT
] ]
} }

View File

@ -165,14 +165,14 @@ abstract class AbstractRestletServerTest extends HttpServerTest<Server> {
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/{id}/param" return getContextPath() + "/path/{id}/param"
case NOT_FOUND: case NOT_FOUND:
return getContextPath() + "/*" return getContextPath() + "/*"
default: default:
return endpoint.resolvePath(address).path return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -71,18 +71,17 @@ abstract class AbstractServletServerTest extends HttpServerTest<Server> {
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/{id}/param" return getContextPath() + "/path/{id}/param"
case NOT_FOUND: case NOT_FOUND:
return getContextPath() + "/*" return getContextPath() + "/*"
default: default:
return endpoint.resolvePath(address).path return super.expectedHttpRoute(endpoint)
} }
} }
static class TestApp extends Application { static class TestApp extends Application {
@Override @Override

View File

@ -178,14 +178,14 @@ abstract class AbstractRestletServerTest extends HttpServerTest<Server> {
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/{id}/param" return getContextPath() + "/path/{id}/param"
case NOT_FOUND: case NOT_FOUND:
return getContextPath() + "/*" return getContextPath() + "/*"
default: default:
return endpoint.resolvePath(address).path return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -71,6 +71,13 @@ class JettyServlet2Test extends HttpServerTest<Server> implements AgentTestTrait
return new URI("http://localhost:$port/$CONTEXT/") return new URI("http://localhost:$port/$CONTEXT/")
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[ [

View File

@ -18,6 +18,7 @@ import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEn
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.INDEXED_CHILD import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.INDEXED_CHILD
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS
@ -60,6 +61,16 @@ abstract class AbstractServlet3Test<SERVER, CONTEXT> extends HttpServerTest<SERV
super.request(uri, method) super.request(uri, method)
} }
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return getContextPath() + "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[ [

View File

@ -3,7 +3,9 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.eclipse.jetty.server.Server import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.handler.ErrorHandler import org.eclipse.jetty.server.handler.ErrorHandler
import org.eclipse.jetty.servlet.ServletHandler import org.eclipse.jetty.servlet.ServletHandler
@ -38,6 +40,13 @@ class JettyServletHandlerTest extends AbstractServlet3Test<Server, ServletHandle
super.responseSpan(trace, index, controllerSpan, handlerSpan, method, endpoint) super.responseSpan(trace, index, controllerSpan, handlerSpan, method, endpoint)
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
if (endpoint == ServerEndpoint.CAPTURE_PARAMETERS) { if (endpoint == ServerEndpoint.CAPTURE_PARAMETERS) {

View File

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.CAPTURE_PARAMETERS
import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.asserts.TraceAssert
@ -15,9 +13,11 @@ import jakarta.servlet.Servlet
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.CAPTURE_HEADERS import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.CAPTURE_HEADERS
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.CAPTURE_PARAMETERS
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.INDEXED_CHILD import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.INDEXED_CHILD
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS
@ -69,6 +69,16 @@ abstract class AbstractServlet5Test<SERVER, CONTEXT> extends HttpServerTest<SERV
true true
} }
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return getContextPath() + "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[ [

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import jakarta.servlet.Servlet import jakarta.servlet.Servlet
import jakarta.servlet.ServletException import jakarta.servlet.ServletException
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
@ -14,6 +16,13 @@ import spock.lang.IgnoreIf
@IgnoreIf({ !jvm.java11Compatible }) @IgnoreIf({ !jvm.java11Compatible })
class JettyServletHandlerTest extends AbstractServlet5Test<Object, Object> { class JettyServletHandlerTest extends AbstractServlet5Test<Object, Object> {
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
if (ServerEndpoint.CAPTURE_PARAMETERS == endpoint) { if (ServerEndpoint.CAPTURE_PARAMETERS == endpoint) {

View File

@ -43,6 +43,7 @@ public class RoutesInstrumentation implements TypeInstrumentation {
Span span = Java8BytecodeBridge.currentSpan(); Span span = Java8BytecodeBridge.currentSpan();
if (span != null && routeMatch != null) { if (span != null && routeMatch != null) {
// TODO should update SERVER span name/route using ServerSpanNaming
span.updateName(routeMatch.getMatchUri()); span.updateName(routeMatch.getMatchUri());
} }
} }

View File

@ -5,9 +5,10 @@
package server.base package server.base
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.springframework.boot.SpringApplication import org.springframework.boot.SpringApplication
import org.springframework.context.ConfigurableApplicationContext import org.springframework.context.ConfigurableApplicationContext
@ -34,6 +35,13 @@ abstract class SpringWebFluxServerTest extends HttpServerTest<ConfigurableApplic
ctx.close() ctx.close()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {

View File

@ -88,7 +88,7 @@ class SpringBootBasedTest extends HttpServerTest<ConfigurableApplicationContext>
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/{id}/param" return getContextPath() + "/path/{id}/param"
@ -97,7 +97,7 @@ class SpringBootBasedTest extends HttpServerTest<ConfigurableApplicationContext>
case LOGIN: case LOGIN:
return getContextPath() + "/*" return getContextPath() + "/*"
default: default:
return super.expectedServerSpanName(endpoint) return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -90,14 +90,14 @@ class ServletFilterTest extends HttpServerTest<ConfigurableApplicationContext> i
} }
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/{id}/param" return getContextPath() + "/path/{id}/param"
case NOT_FOUND: case NOT_FOUND:
return getContextPath() + "/**" return getContextPath() + "/**"
default: default:
return super.expectedServerSpanName(endpoint) return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -71,14 +71,14 @@ class Struts2ActionSpanTest extends HttpServerTest<Server> implements AgentTestT
} }
} }
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/{id}/param" return getContextPath() + "/path/{id}/param"
case NOT_FOUND: case NOT_FOUND:
return getContextPath() + "/*" return getContextPath() + "/*"
default: default:
return endpoint.resolvePath(address).path return super.expectedHttpRoute(endpoint)
} }
} }

View File

@ -99,6 +99,16 @@ class TomcatAsyncTest extends HttpServerTest<Tomcat> implements AgentTestTrait {
AsyncServlet AsyncServlet
} }
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return getContextPath() + "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[ [

View File

@ -35,12 +35,8 @@ class TomcatHandlerTest extends HttpServerTest<Tomcat> implements AgentTestTrait
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
switch (endpoint) { def route = expectedHttpRoute(endpoint)
case NOT_FOUND: return route == null ? "HTTP GET" : route
return "HTTP GET"
default:
return endpoint.resolvePath(address).path
}
} }
@Override @Override

View File

@ -99,6 +99,16 @@ class TomcatAsyncTest extends HttpServerTest<Tomcat> implements AgentTestTrait {
AsyncServlet AsyncServlet
} }
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return getContextPath() + "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override @Override
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[ [

View File

@ -35,12 +35,8 @@ class TomcatHandlerTest extends HttpServerTest<Tomcat> implements AgentTestTrait
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
switch (endpoint) { def route = expectedHttpRoute(endpoint)
case NOT_FOUND: return route == null ? "HTTP GET" : route
return "HTTP GET"
default:
return endpoint.resolvePath(address).path
}
} }
@Override @Override

View File

@ -96,6 +96,13 @@ class UndertowServerDispatchTest extends HttpServerTest<Undertow> implements Age
undertow.stop() undertow.stop()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET" return "HTTP GET"

View File

@ -105,6 +105,13 @@ class UndertowServerTest extends HttpServerTest<Undertow> implements AgentTestTr
undertow.stop() undertow.stop()
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET" return "HTTP GET"

View File

@ -5,8 +5,10 @@
package server package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.vertx.core.DeploymentOptions import io.vertx.core.DeploymentOptions
import io.vertx.core.Promise import io.vertx.core.Promise
import io.vertx.core.Vertx import io.vertx.core.Vertx
@ -62,6 +64,13 @@ class VertxRxHttpServerTest extends HttpServerTest<Vertx> implements AgentTestTr
return true return true
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {

View File

@ -5,9 +5,10 @@
package server package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.vertx.core.DeploymentOptions import io.vertx.core.DeploymentOptions
import io.vertx.core.Future import io.vertx.core.Future
import io.vertx.core.Vertx import io.vertx.core.Vertx
@ -63,6 +64,13 @@ class VertxRxHttpServerTest extends HttpServerTest<Vertx> implements AgentTestTr
return true return true
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {

View File

@ -33,8 +33,7 @@ public final class RoutingContextHandlerWrapper implements Handler<RoutingContex
Span serverSpan = ServerSpan.fromContextOrNull(Context.current()); Span serverSpan = ServerSpan.fromContextOrNull(Context.current());
try { try {
if (serverSpan != null) { if (serverSpan != null) {
// TODO should update only SERVER span using // TODO should update SERVER span name/route using ServerSpanNaming
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/465
serverSpan.updateName(context.currentRoute().getPath()); serverSpan.updateName(context.currentRoute().getPath());
} }
} catch (RuntimeException ex) { } catch (RuntimeException ex) {

View File

@ -5,8 +5,10 @@
package server package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.vertx.core.AbstractVerticle import io.vertx.core.AbstractVerticle
import io.vertx.core.DeploymentOptions import io.vertx.core.DeploymentOptions
import io.vertx.core.Vertx import io.vertx.core.Vertx
@ -59,6 +61,13 @@ abstract class AbstractVertxHttpServerTest extends HttpServerTest<Vertx> impleme
return false return false
} }
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override @Override
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {

View File

@ -36,11 +36,11 @@ class AttributesAssert {
assertedAttributes.add(name) assertedAttributes.add(name)
def value = attributes.get(name) def value = attributes.get(name)
if (expected instanceof Pattern) { if (expected instanceof Pattern) {
assert value =~ expected assert value =~ expected, "value '$value' does not match regex '$expected'"
} else if (expected instanceof Class) { } else if (expected instanceof Class) {
assert ((Class) expected).isInstance(value) assert ((Class) expected).isInstance(value), "value '$value' is not an instance of $expected.name"
} else if (expected instanceof Closure) { } else if (expected instanceof Closure) {
assert ((Closure) expected).call(value) assert ((Closure) expected).call(value), "value '$value' fails the passed predicate"
} else { } else {
assert value == expected assert value == expected
} }

View File

@ -66,11 +66,16 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
} }
String expectedServerSpanName(ServerEndpoint endpoint) { String expectedServerSpanName(ServerEndpoint endpoint) {
def route = expectedHttpRoute(endpoint)
return route == null ? getContextPath() + "/*" : route
}
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) { switch (endpoint) {
case NOT_FOUND:
return null
case PATH_PARAM: case PATH_PARAM:
return getContextPath() + "/path/:id/param" return getContextPath() + "/path/:id/param"
case NOT_FOUND:
return getContextPath() + "/*"
default: default:
return endpoint.resolvePath(address).path return endpoint.resolvePath(address).path
} }
@ -152,6 +157,12 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
return true return true
} }
/** A list of additional HTTP server span attributes extracted by the instrumentation per URI. */
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
[SemanticAttributes.HTTP_ROUTE] as Set
}
// TODO: remove that method and use httpAttributes everywhere; similar to HttpClientTest
List<AttributeKey<?>> extraAttributes() { List<AttributeKey<?>> extraAttributes() {
[] []
} }
@ -650,7 +661,7 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
// parent span must be cast otherwise it breaks debugging classloading (junit loads it early) // parent span must be cast otherwise it breaks debugging classloading (junit loads it early)
void serverSpan(TraceAssert trace, int index, String traceID = null, String parentID = null, String method = "GET", Long responseContentLength = null, ServerEndpoint endpoint = SUCCESS) { void serverSpan(TraceAssert trace, int index, String traceID = null, String parentID = null, String method = "GET", Long responseContentLength = null, ServerEndpoint endpoint = SUCCESS) {
def extraAttributes = extraAttributes() def httpAttributes = extraAttributes() + this.httpAttributes(endpoint)
trace.span(index) { trace.span(index) {
name expectedServerSpanName(endpoint) name expectedServerSpanName(endpoint)
kind SpanKind.SERVER // can't use static import because of SERVER type parameter kind SpanKind.SERVER // can't use static import because of SERVER type parameter
@ -674,7 +685,7 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
} }
} }
attributes { attributes {
if (extraAttributes.contains(SemanticAttributes.NET_TRANSPORT)) { if (httpAttributes.contains(SemanticAttributes.NET_TRANSPORT)) {
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
} }
// net.peer.name resolves to "127.0.0.1" on windows which is same as net.peer.ip so then not captured // net.peer.name resolves to "127.0.0.1" on windows which is same as net.peer.ip so then not captured
@ -692,26 +703,25 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_TARGET" endpoint.resolvePath(address).getPath() + "${endpoint == QUERY_PARAM ? "?${endpoint.body}" : ""}" "$SemanticAttributes.HTTP_TARGET" endpoint.resolvePath(address).getPath() + "${endpoint == QUERY_PARAM ? "?${endpoint.body}" : ""}"
if (extraAttributes.contains(SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH)) { if (httpAttributes.contains(SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
} else { } else {
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional // Optional
} }
if (extraAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) { if (httpAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
} else { } else {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional // Optional
} }
if (extraAttributes.contains(SemanticAttributes.HTTP_ROUTE)) { if (httpAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) {
// TODO(anuraaga): Revisit this when applying instrumenters to more libraries, Armeria
// currently reports '/*' which is a fallback route.
"$SemanticAttributes.HTTP_ROUTE" String
}
if (extraAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) {
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
} }
if (httpAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
"$SemanticAttributes.HTTP_ROUTE" { it == expectedHttpRoute(endpoint) }
}
if (endpoint == CAPTURE_HEADERS) { if (endpoint == CAPTURE_HEADERS) {
"http.request.header.x_test_request" { it == ["test"] } "http.request.header.x_test_request" { it == ["test"] }
"http.response.header.x_test_response" { it == ["test"] } "http.response.header.x_test_response" { it == ["test"] }
@ -724,14 +734,14 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
} }
void indexedServerSpan(TraceAssert trace, Object parent, int requestId) { void indexedServerSpan(TraceAssert trace, Object parent, int requestId) {
def extraAttributes = extraAttributes()
ServerEndpoint endpoint = INDEXED_CHILD ServerEndpoint endpoint = INDEXED_CHILD
def httpAttributes = extraAttributes() + this.httpAttributes(endpoint)
trace.span(1) { trace.span(1) {
name expectedServerSpanName(endpoint) name expectedServerSpanName(endpoint)
kind SpanKind.SERVER // can't use static import because of SERVER type parameter kind SpanKind.SERVER // can't use static import because of SERVER type parameter
childOf((SpanData) parent) childOf((SpanData) parent)
attributes { attributes {
if (extraAttributes.contains(SemanticAttributes.NET_TRANSPORT)) { if (httpAttributes.contains(SemanticAttributes.NET_TRANSPORT)) {
"$SemanticAttributes.NET_TRANSPORT" IP_TCP "$SemanticAttributes.NET_TRANSPORT" IP_TCP
} }
// net.peer.name resolves to "127.0.0.1" on windows which is same as net.peer.ip so then not captured // net.peer.name resolves to "127.0.0.1" on windows which is same as net.peer.ip so then not captured
@ -749,26 +759,29 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
"$SemanticAttributes.HTTP_SCHEME" "http" "$SemanticAttributes.HTTP_SCHEME" "http"
"$SemanticAttributes.HTTP_TARGET" endpoint.resolvePath(address).getPath() + "?id=$requestId" "$SemanticAttributes.HTTP_TARGET" endpoint.resolvePath(address).getPath() + "?id=$requestId"
if (extraAttributes.contains(SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH)) { if (httpAttributes.contains(SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
} else { } else {
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional // Optional
} }
if (extraAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) { if (httpAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
} else { } else {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional // Optional
} }
if (extraAttributes.contains(SemanticAttributes.HTTP_ROUTE)) { if (httpAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
// TODO(anuraaga): Revisit this when applying instrumenters to more libraries, Armeria // TODO(anuraaga): Revisit this when applying instrumenters to more libraries, Armeria
// currently reports '/*' which is a fallback route. // currently reports '/*' which is a fallback route.
"$SemanticAttributes.HTTP_ROUTE" String "$SemanticAttributes.HTTP_ROUTE" String
} }
if (extraAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) { if (httpAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) {
"$SemanticAttributes.HTTP_SERVER_NAME" String "$SemanticAttributes.HTTP_SERVER_NAME" String
} }
if (httpAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
"$SemanticAttributes.HTTP_ROUTE" { it == expectedHttpRoute(endpoint) }
}
} }
} }
} }