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.ContextKey;
import io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
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. */
public final class ServerSpanNaming {
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() {
return (context, request, startAttributes) -> {
@ -27,9 +29,7 @@ public final class ServerSpanNaming {
}
private volatile Source updatedBySource;
// Length of the currently set name. This is used when setting name from a servlet filter
// to pick the most descriptive (longest) name.
private volatile int nameLength;
@Nullable private volatile String route;
private ServerSpanNaming(Source initialSource) {
this.updatedBySource = initialSource;
@ -78,7 +78,7 @@ public final class ServerSpanNaming {
if (serverSpanNaming == null) {
String name = serverSpanName.get(context, arg1, arg2);
if (name != null && !name.isEmpty()) {
serverSpan.updateName(name);
updateSpanData(serverSpan, name);
}
return;
}
@ -91,15 +91,33 @@ public final class ServerSpanNaming {
if (name != null
&& !name.isEmpty()
&& (!onlyIfBetterName || serverSpanNaming.isBetterName(name))) {
serverSpan.updateName(name);
updateSpanData(serverSpan, name);
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) {
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 {

View File

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

View File

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

View File

@ -5,8 +5,6 @@
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.RetryOnAddressAlreadyInUseTrait
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.INTERNAL
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 {
@ -100,6 +99,8 @@ class RestCamelTest extends AgentInstrumentationSpecification implements RetryOn
"$SemanticAttributes.NET_PEER_PORT" Long
"$SemanticAttributes.HTTP_SERVER_NAME" String
"$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) {

View File

@ -5,8 +5,6 @@
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.RetryOnAddressAlreadyInUseTrait
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.INTERNAL
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 {
@ -136,6 +135,8 @@ class TwoServicesWithDirectClientCamelTest extends AgentInstrumentationSpecifica
"$SemanticAttributes.HTTP_SERVER_NAME" String
"$SemanticAttributes.NET_TRANSPORT" IP_TCP
"$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) {

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.EXCEPTION
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.QUERY_PARAM
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)
@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
List<AttributeKey<?>> extraAttributes() {
[
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
SemanticAttributes.HTTP_ROUTE,
SemanticAttributes.HTTP_SERVER_NAME,
SemanticAttributes.NET_PEER_NAME,
SemanticAttributes.NET_TRANSPORT

View File

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

View File

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

View File

@ -3,9 +3,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
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.FilterChain
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.IdleTimeoutFilter
import java.nio.charset.StandardCharsets
import java.util.concurrent.Executors
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED
@ -61,6 +63,18 @@ class GrizzlyFilterchainServerTest extends HttpServerTest<HttpServer> implements
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
boolean testException() {
// 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
*/
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
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.HttpServer
import org.glassfish.grizzly.http.server.Request
@ -42,6 +44,18 @@ class GrizzlyTest extends HttpServerTest<HttpServer> implements AgentTestTrait {
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
void stopServer(HttpServer server) {
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 {
@Override

View File

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

View File

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

View File

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

View File

@ -3,8 +3,6 @@
* 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.instrumentation.test.AgentTestTrait
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.PATH_PARAM
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 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.NET_TRANSPORT" IP_TCP
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } // Optional
"$SemanticAttributes.HTTP_ROUTE" path
if (fullUrl.getPath().endsWith(ServerEndpoint.CAPTURE_HEADERS.getPath())) {
"http.request.header.x_test_request" { it == ["test"] }
"http.response.header.x_test_response" { it == ["test"] }

View File

@ -36,6 +36,7 @@ abstract class JaxrsAnnotationsInstrumentationTest extends AgentInstrumentationS
kind SERVER
hasNoParent()
attributes {
"$SemanticAttributes.HTTP_ROUTE" paramName
}
}
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
String expectedServerSpanName(ServerEndpoint endpoint) {
"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
String expectedServerSpanName(ServerEndpoint endpoint) {
"HTTP GET"

View File

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

View File

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

View File

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

View File

@ -3,8 +3,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.jboss.netty.bootstrap.ServerBootstrap
import org.jboss.netty.buffer.ChannelBuffer
import org.jboss.netty.buffer.ChannelBuffers
@ -159,6 +161,13 @@ class Netty38ServerTest extends HttpServerTest<ServerBootstrap> implements Agent
server?.shutdown()
}
@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"

View File

@ -24,8 +24,10 @@ import io.netty.handler.codec.http.QueryStringDecoder
import io.netty.handler.logging.LogLevel
import io.netty.handler.logging.LoggingHandler
import io.netty.util.CharsetUtil
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
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_TYPE
@ -128,6 +130,13 @@ class Netty40ServerTest extends HttpServerTest<EventLoopGroup> implements AgentT
server?.shutdownGracefully()
}
@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"

View File

@ -23,8 +23,10 @@ import io.netty.handler.codec.http.QueryStringDecoder
import io.netty.handler.logging.LogLevel
import io.netty.handler.logging.LoggingHandler
import io.netty.util.CharsetUtil
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
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_TYPE
@ -127,6 +129,13 @@ class Netty41ServerTest extends HttpServerTest<EventLoopGroup> implements AgentT
server?.shutdownGracefully()
}
@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"

View File

@ -5,12 +5,13 @@
package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import play.mvc.Results
import play.routing.RoutingDsl
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
String expectedServerSpanName(ServerEndpoint endpoint) {
return "HTTP GET"

View File

@ -5,11 +5,13 @@
package server
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import play.BuiltInComponents
import play.Mode
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
String expectedServerSpanName(ServerEndpoint endpoint) {
return "akka.request"

View File

@ -152,7 +152,7 @@ abstract class AbstractRatpackHttpServerTest extends HttpServerTest<RatpackServe
}
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
String expectedHttpRoute(ServerEndpoint endpoint) {
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)) {
"$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)) {
"$SemanticAttributes.HTTP_SERVER_NAME" String
}
"$SemanticAttributes.HTTP_ROUTE" "/$route"
}
}
if (hasHandlerSpan()) {

View File

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

View File

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

View File

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

View File

@ -178,14 +178,14 @@ abstract class AbstractRestletServerTest extends HttpServerTest<Server> {
}
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case PATH_PARAM:
return getContextPath() + "/path/{id}/param"
case NOT_FOUND:
return getContextPath() + "/*"
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/")
}
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override
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.EXCEPTION
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.REDIRECT
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)
}
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return getContextPath() + "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override
List<AttributeKey<?>> extraAttributes() {
[

View File

@ -3,7 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.api.common.AttributeKey
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.handler.ErrorHandler
import org.eclipse.jetty.servlet.ServletHandler
@ -38,6 +40,13 @@ class JettyServletHandlerTest extends AbstractServlet3Test<Server, ServletHandle
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
String expectedServerSpanName(ServerEndpoint endpoint) {
if (endpoint == ServerEndpoint.CAPTURE_PARAMETERS) {

View File

@ -3,8 +3,6 @@
* 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.instrumentation.test.AgentTestTrait
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.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.EXCEPTION
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.REDIRECT
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS
@ -69,6 +69,16 @@ abstract class AbstractServlet5Test<SERVER, CONTEXT> extends HttpServerTest<SERV
true
}
@Override
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return getContextPath() + "/*"
default:
return super.expectedHttpRoute(endpoint)
}
}
@Override
List<AttributeKey<?>> extraAttributes() {
[

View File

@ -3,6 +3,8 @@
* 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.ServletException
import jakarta.servlet.http.HttpServletRequest
@ -14,6 +16,13 @@ import spock.lang.IgnoreIf
@IgnoreIf({ !jvm.java11Compatible })
class JettyServletHandlerTest extends AbstractServlet5Test<Object, Object> {
@Override
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
def attributes = super.httpAttributes(endpoint)
attributes.remove(SemanticAttributes.HTTP_ROUTE)
attributes
}
@Override
String expectedServerSpanName(ServerEndpoint endpoint) {
if (ServerEndpoint.CAPTURE_PARAMETERS == endpoint) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,6 +96,13 @@ class UndertowServerDispatchTest extends HttpServerTest<Undertow> implements Age
undertow.stop()
}
@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"

View File

@ -105,6 +105,13 @@ class UndertowServerTest extends HttpServerTest<Undertow> implements AgentTestTr
undertow.stop()
}
@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"

View File

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

View File

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

View File

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

View File

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

View File

@ -36,11 +36,11 @@ class AttributesAssert {
assertedAttributes.add(name)
def value = attributes.get(name)
if (expected instanceof Pattern) {
assert value =~ expected
assert value =~ expected, "value '$value' does not match regex '$expected'"
} 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) {
assert ((Closure) expected).call(value)
assert ((Closure) expected).call(value), "value '$value' fails the passed predicate"
} else {
assert value == expected
}

View File

@ -66,11 +66,16 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
}
String expectedServerSpanName(ServerEndpoint endpoint) {
def route = expectedHttpRoute(endpoint)
return route == null ? getContextPath() + "/*" : route
}
String expectedHttpRoute(ServerEndpoint endpoint) {
switch (endpoint) {
case NOT_FOUND:
return null
case PATH_PARAM:
return getContextPath() + "/path/:id/param"
case NOT_FOUND:
return getContextPath() + "/*"
default:
return endpoint.resolvePath(address).path
}
@ -152,6 +157,12 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
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() {
[]
}
@ -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)
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) {
name expectedServerSpanName(endpoint)
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 {
if (extraAttributes.contains(SemanticAttributes.NET_TRANSPORT)) {
if (httpAttributes.contains(SemanticAttributes.NET_TRANSPORT)) {
"$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
@ -692,26 +703,25 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
"$SemanticAttributes.HTTP_SCHEME" "http"
"$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
} else {
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional
}
if (extraAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
if (httpAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
} else {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional
}
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 (httpAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) {
"$SemanticAttributes.HTTP_SERVER_NAME" String
}
if (httpAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
"$SemanticAttributes.HTTP_ROUTE" { it == expectedHttpRoute(endpoint) }
}
if (endpoint == CAPTURE_HEADERS) {
"http.request.header.x_test_request" { 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) {
def extraAttributes = extraAttributes()
ServerEndpoint endpoint = INDEXED_CHILD
def httpAttributes = extraAttributes() + this.httpAttributes(endpoint)
trace.span(1) {
name expectedServerSpanName(endpoint)
kind SpanKind.SERVER // can't use static import because of SERVER type parameter
childOf((SpanData) parent)
attributes {
if (extraAttributes.contains(SemanticAttributes.NET_TRANSPORT)) {
if (httpAttributes.contains(SemanticAttributes.NET_TRANSPORT)) {
"$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
@ -749,26 +759,29 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
"$SemanticAttributes.HTTP_SCHEME" "http"
"$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
} else {
"$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional
}
if (extraAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
if (httpAttributes.contains(SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH)) {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
} else {
"$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long }
// Optional
}
if (extraAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
if (httpAttributes.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 (httpAttributes.contains(SemanticAttributes.HTTP_SERVER_NAME)) {
"$SemanticAttributes.HTTP_SERVER_NAME" String
}
if (httpAttributes.contains(SemanticAttributes.HTTP_ROUTE)) {
"$SemanticAttributes.HTTP_ROUTE" { it == expectedHttpRoute(endpoint) }
}
}
}
}