Merge pull request #320 from DataDog/tyler/servlet-context-naming
Name service based on servlet context
This commit is contained in:
commit
c011eb0fbd
|
@ -64,7 +64,7 @@ class ApacheHttpClientTest extends Specification {
|
||||||
final DDSpan localSpan = clientTrace.get(1)
|
final DDSpan localSpan = clientTrace.get(1)
|
||||||
localSpan.getType() == null
|
localSpan.getType() == null
|
||||||
localSpan.getTags()[Tags.COMPONENT.getKey()] == "apache-httpclient"
|
localSpan.getTags()[Tags.COMPONENT.getKey()] == "apache-httpclient"
|
||||||
localSpan.getOperationName() == "http.request"
|
localSpan.getOperationName() == "apache.http"
|
||||||
|
|
||||||
final DDSpan clientSpan = clientTrace.get(2)
|
final DDSpan clientSpan = clientTrace.get(2)
|
||||||
clientSpan.getOperationName() == "http.request"
|
clientSpan.getOperationName() == "http.request"
|
||||||
|
@ -109,7 +109,7 @@ class ApacheHttpClientTest extends Specification {
|
||||||
// our instrumentation makes 2 spans for apache-httpclient
|
// our instrumentation makes 2 spans for apache-httpclient
|
||||||
final DDSpan localSpan = clientTrace.get(1)
|
final DDSpan localSpan = clientTrace.get(1)
|
||||||
localSpan.getTags()[Tags.COMPONENT.getKey()] == "apache-httpclient"
|
localSpan.getTags()[Tags.COMPONENT.getKey()] == "apache-httpclient"
|
||||||
localSpan.getOperationName() == "http.request"
|
localSpan.getOperationName() == "apache.http"
|
||||||
|
|
||||||
final DDSpan clientSpan = clientTrace.get(2)
|
final DDSpan clientSpan = clientTrace.get(2)
|
||||||
clientSpan.getOperationName() == "http.request"
|
clientSpan.getOperationName() == "http.request"
|
||||||
|
|
|
@ -52,5 +52,13 @@ public interface Instrumenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract AgentBuilder apply(AgentBuilder agentBuilder);
|
protected abstract AgentBuilder apply(AgentBuilder agentBuilder);
|
||||||
|
|
||||||
|
protected static String getPropOrEnv(final String name) {
|
||||||
|
return System.getProperty(name, System.getenv(propToEnvName(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String propToEnvName(final String name) {
|
||||||
|
return name.toUpperCase().replace(".", "_");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,9 +100,9 @@ class AWSClientTest extends AgentTestRunner {
|
||||||
and: // span 0 - from apache-httpclient instrumentation
|
and: // span 0 - from apache-httpclient instrumentation
|
||||||
def span1 = trace[0]
|
def span1 = trace[0]
|
||||||
|
|
||||||
span1.context().operationName == "http.request"
|
span1.context().operationName == "apache.http"
|
||||||
span1.serviceName == "unnamed-java-app"
|
span1.serviceName == "unnamed-java-app"
|
||||||
span1.resourceName == "http.request"
|
span1.resourceName == "apache.http"
|
||||||
span1.type == null
|
span1.type == null
|
||||||
!span1.context().getErrorFlag()
|
!span1.context().getErrorFlag()
|
||||||
span1.context().parentId == 0
|
span1.context().parentId == 0
|
||||||
|
|
|
@ -58,7 +58,7 @@ class JaxRsClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
span.context().operationName == "jax-rs.client.call"
|
span.context().operationName == "jax-rs.client.call"
|
||||||
span.serviceName == "unnamed-java-app"
|
span.serviceName == "unnamed-java-app"
|
||||||
span.resourceName == "GET jax-rs.client.call"
|
span.resourceName == "GET /ping"
|
||||||
span.type == "http"
|
span.type == "http"
|
||||||
!span.context().getErrorFlag()
|
!span.context().getErrorFlag()
|
||||||
span.context().parentId == 0
|
span.context().parentId == 0
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import datadog.trace.agent.test.AgentTestRunner
|
import datadog.trace.agent.test.AgentTestRunner
|
||||||
|
import datadog.trace.api.DDSpanTypes
|
||||||
import datadog.trace.api.DDTags
|
import datadog.trace.api.DDTags
|
||||||
import io.opentracing.tag.Tags
|
import io.opentracing.tag.Tags
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -39,19 +40,20 @@ class OkHttp3Test extends AgentTestRunner {
|
||||||
and: // span 0
|
and: // span 0
|
||||||
def span1 = trace[0]
|
def span1 = trace[0]
|
||||||
|
|
||||||
span1.context().operationName == "http.request"
|
span1.context().operationName == "okhttp.http"
|
||||||
span1.serviceName == "unnamed-java-app"
|
span1.serviceName == "okhttp"
|
||||||
span1.resourceName == "http.request"
|
span1.resourceName == "okhttp.http"
|
||||||
span1.type == null
|
span1.type == DDSpanTypes.WEB_SERVLET
|
||||||
!span1.context().getErrorFlag()
|
!span1.context().getErrorFlag()
|
||||||
span1.context().parentId == 0
|
span1.context().parentId == 0
|
||||||
|
|
||||||
|
|
||||||
def tags1 = span1.context().tags
|
def tags1 = span1.context().tags
|
||||||
tags1["component"] == "okhttp"
|
tags1["component"] == "okhttp"
|
||||||
|
tags1["span.type"] == DDSpanTypes.WEB_SERVLET
|
||||||
tags1["thread.name"] != null
|
tags1["thread.name"] != null
|
||||||
tags1["thread.id"] != null
|
tags1["thread.id"] != null
|
||||||
tags1.size() == 3
|
tags1.size() == 4
|
||||||
|
|
||||||
and: // span 1
|
and: // span 1
|
||||||
def span2 = trace[1]
|
def span2 = trace[1]
|
||||||
|
|
|
@ -83,6 +83,7 @@ public final class FilterChain2Instrumentation extends Instrumenter.Configurable
|
||||||
.asChildOf(extractedContext)
|
.asChildOf(extractedContext)
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
||||||
|
.withTag("servlet.context", ((HttpServletRequest) req).getContextPath())
|
||||||
.startActive(true);
|
.startActive(true);
|
||||||
|
|
||||||
if (scope instanceof TraceScope) {
|
if (scope instanceof TraceScope) {
|
||||||
|
|
|
@ -85,6 +85,7 @@ public final class HttpServlet2Instrumentation extends Instrumenter.Configurable
|
||||||
.asChildOf(extractedContext)
|
.asChildOf(extractedContext)
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
||||||
|
.withTag("servlet.context", req.getContextPath())
|
||||||
.startActive(true);
|
.startActive(true);
|
||||||
|
|
||||||
if (scope instanceof TraceScope) {
|
if (scope instanceof TraceScope) {
|
||||||
|
|
|
@ -106,6 +106,7 @@ class JettyServlet2Test extends AgentTestRunner {
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" ""
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +144,7 @@ class JettyServlet2Test extends AgentTestRunner {
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" ""
|
||||||
errorTags(RuntimeException, "some $path error")
|
errorTags(RuntimeException, "some $path error")
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
|
@ -182,6 +184,7 @@ class JettyServlet2Test extends AgentTestRunner {
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" ""
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ public final class FilterChain3Instrumentation extends Instrumenter.Configurable
|
||||||
.asChildOf(extractedContext)
|
.asChildOf(extractedContext)
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
||||||
|
.withTag("servlet.context", ((HttpServletRequest) req).getContextPath())
|
||||||
.startActive(false);
|
.startActive(false);
|
||||||
|
|
||||||
if (scope instanceof TraceScope) {
|
if (scope instanceof TraceScope) {
|
||||||
|
|
|
@ -84,6 +84,7 @@ public final class HttpServlet3Instrumentation extends Instrumenter.Configurable
|
||||||
.asChildOf(extractedContext)
|
.asChildOf(extractedContext)
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.WEB_SERVLET)
|
||||||
|
.withTag("servlet.context", req.getContextPath())
|
||||||
.startActive(false);
|
.startActive(false);
|
||||||
|
|
||||||
if (scope instanceof TraceScope) {
|
if (scope instanceof TraceScope) {
|
||||||
|
|
|
@ -108,6 +108,7 @@ class JettyServlet3Test extends AgentTestRunner {
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" ""
|
||||||
"http.status_code" 200
|
"http.status_code" 200
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
|
@ -147,6 +148,7 @@ class JettyServlet3Test extends AgentTestRunner {
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" ""
|
||||||
"http.status_code" 500
|
"http.status_code" 500
|
||||||
errorTags(RuntimeException, "some $path error")
|
errorTags(RuntimeException, "some $path error")
|
||||||
defaultTags()
|
defaultTags()
|
||||||
|
@ -187,6 +189,7 @@ class JettyServlet3Test extends AgentTestRunner {
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" ""
|
||||||
"http.status_code" 500
|
"http.status_code" 500
|
||||||
"error" true
|
"error" true
|
||||||
defaultTags()
|
defaultTags()
|
||||||
|
|
|
@ -44,7 +44,7 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
if (!applicationDir.exists()) {
|
if (!applicationDir.exists()) {
|
||||||
applicationDir.mkdirs()
|
applicationDir.mkdirs()
|
||||||
}
|
}
|
||||||
appContext = tomcatServer.addWebapp("", applicationDir.getAbsolutePath())
|
appContext = tomcatServer.addWebapp("/my-context", applicationDir.getAbsolutePath())
|
||||||
// Speed up startup by disabling jar scanning:
|
// Speed up startup by disabling jar scanning:
|
||||||
appContext.getJarScanner().setJarScanFilter(new JarScanFilter() {
|
appContext.getJarScanner().setJarScanFilter(new JarScanFilter() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -84,7 +84,7 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
def "test #path servlet call"() {
|
def "test #path servlet call"() {
|
||||||
setup:
|
setup:
|
||||||
def request = new Request.Builder()
|
def request = new Request.Builder()
|
||||||
.url("http://localhost:$PORT/$path")
|
.url("http://localhost:$PORT/my-context/$path")
|
||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
def response = client.newCall(request).execute()
|
def response = client.newCall(request).execute()
|
||||||
|
@ -95,18 +95,19 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
assertTraces(writer, 1) {
|
assertTraces(writer, 1) {
|
||||||
trace(0, 1) {
|
trace(0, 1) {
|
||||||
span(0) {
|
span(0) {
|
||||||
serviceName "unnamed-java-app"
|
serviceName "my-context"
|
||||||
operationName "servlet.request"
|
operationName "servlet.request"
|
||||||
resourceName "GET /$path"
|
resourceName "GET /my-context/$path"
|
||||||
spanType DDSpanTypes.WEB_SERVLET
|
spanType DDSpanTypes.WEB_SERVLET
|
||||||
errored false
|
errored false
|
||||||
parent()
|
parent()
|
||||||
tags {
|
tags {
|
||||||
"http.url" "http://localhost:$PORT/$path"
|
"http.url" "http://localhost:$PORT/my-context/$path"
|
||||||
"http.method" "GET"
|
"http.method" "GET"
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" "/my-context"
|
||||||
"http.status_code" 200
|
"http.status_code" 200
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
|
@ -123,7 +124,7 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
def "test #path error servlet call"() {
|
def "test #path error servlet call"() {
|
||||||
setup:
|
setup:
|
||||||
def request = new Request.Builder()
|
def request = new Request.Builder()
|
||||||
.url("http://localhost:$PORT/$path?error=true")
|
.url("http://localhost:$PORT/my-context/$path?error=true")
|
||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
def response = client.newCall(request).execute()
|
def response = client.newCall(request).execute()
|
||||||
|
@ -134,18 +135,19 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
assertTraces(writer, 1) {
|
assertTraces(writer, 1) {
|
||||||
trace(0, 1) {
|
trace(0, 1) {
|
||||||
span(0) {
|
span(0) {
|
||||||
serviceName "unnamed-java-app"
|
serviceName "my-context"
|
||||||
operationName "servlet.request"
|
operationName "servlet.request"
|
||||||
resourceName "GET /$path"
|
resourceName "GET /my-context/$path"
|
||||||
spanType DDSpanTypes.WEB_SERVLET
|
spanType DDSpanTypes.WEB_SERVLET
|
||||||
errored true
|
errored true
|
||||||
parent()
|
parent()
|
||||||
tags {
|
tags {
|
||||||
"http.url" "http://localhost:$PORT/$path"
|
"http.url" "http://localhost:$PORT/my-context/$path"
|
||||||
"http.method" "GET"
|
"http.method" "GET"
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" "/my-context"
|
||||||
"http.status_code" 500
|
"http.status_code" 500
|
||||||
errorTags(RuntimeException, "some $path error")
|
errorTags(RuntimeException, "some $path error")
|
||||||
defaultTags()
|
defaultTags()
|
||||||
|
@ -163,7 +165,7 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
def "test #path error servlet call for non-throwing error"() {
|
def "test #path error servlet call for non-throwing error"() {
|
||||||
setup:
|
setup:
|
||||||
def request = new Request.Builder()
|
def request = new Request.Builder()
|
||||||
.url("http://localhost:$PORT/$path?non-throwing-error=true")
|
.url("http://localhost:$PORT/my-context/$path?non-throwing-error=true")
|
||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
def response = client.newCall(request).execute()
|
def response = client.newCall(request).execute()
|
||||||
|
@ -174,18 +176,19 @@ class TomcatServlet3Test extends AgentTestRunner {
|
||||||
assertTraces(writer, 1) {
|
assertTraces(writer, 1) {
|
||||||
trace(0, 1) {
|
trace(0, 1) {
|
||||||
span(0) {
|
span(0) {
|
||||||
serviceName "unnamed-java-app"
|
serviceName "my-context"
|
||||||
operationName "servlet.request"
|
operationName "servlet.request"
|
||||||
resourceName "GET /$path"
|
resourceName "GET /my-context/$path"
|
||||||
spanType DDSpanTypes.WEB_SERVLET
|
spanType DDSpanTypes.WEB_SERVLET
|
||||||
errored true
|
errored true
|
||||||
parent()
|
parent()
|
||||||
tags {
|
tags {
|
||||||
"http.url" "http://localhost:$PORT/$path"
|
"http.url" "http://localhost:$PORT/my-context/$path"
|
||||||
"http.method" "GET"
|
"http.method" "GET"
|
||||||
"span.kind" "server"
|
"span.kind" "server"
|
||||||
"component" "java-web-servlet"
|
"component" "java-web-servlet"
|
||||||
"span.type" DDSpanTypes.WEB_SERVLET
|
"span.type" DDSpanTypes.WEB_SERVLET
|
||||||
|
"servlet.context" "/my-context"
|
||||||
"http.status_code" 500
|
"http.status_code" 500
|
||||||
"error" true
|
"error" true
|
||||||
defaultTags()
|
defaultTags()
|
||||||
|
|
|
@ -49,10 +49,11 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span.context().tags["span.kind"] == "server"
|
span.context().tags["span.kind"] == "server"
|
||||||
span.context().tags["span.type"] == "web"
|
span.context().tags["span.type"] == "web"
|
||||||
span.context().tags["component"] == "java-web-servlet"
|
span.context().tags["component"] == "java-web-servlet"
|
||||||
|
span.context().tags["servlet.context"] == ""
|
||||||
span.context().tags["http.status_code"] == 200
|
span.context().tags["http.status_code"] == 200
|
||||||
span.context().tags["thread.name"] != null
|
span.context().tags["thread.name"] != null
|
||||||
span.context().tags["thread.id"] != null
|
span.context().tags["thread.id"] != null
|
||||||
span.context().tags.size() == 8
|
span.context().tags.size() == 9
|
||||||
}
|
}
|
||||||
|
|
||||||
def "generates 404 spans"() {
|
def "generates 404 spans"() {
|
||||||
|
@ -78,10 +79,11 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span0.context().tags["span.kind"] == "server"
|
span0.context().tags["span.kind"] == "server"
|
||||||
span0.context().tags["span.type"] == "web"
|
span0.context().tags["span.type"] == "web"
|
||||||
span0.context().tags["component"] == "java-web-servlet"
|
span0.context().tags["component"] == "java-web-servlet"
|
||||||
|
span0.context().tags["servlet.context"] == ""
|
||||||
span0.context().tags["http.status_code"] == 404
|
span0.context().tags["http.status_code"] == 404
|
||||||
span0.context().tags["thread.name"] != null
|
span0.context().tags["thread.name"] != null
|
||||||
span0.context().tags["thread.id"] != null
|
span0.context().tags["thread.id"] != null
|
||||||
span0.context().tags.size() == 8
|
span0.context().tags.size() == 9
|
||||||
|
|
||||||
and: // trace 1
|
and: // trace 1
|
||||||
def trace1 = TEST_WRITER.get(1)
|
def trace1 = TEST_WRITER.get(1)
|
||||||
|
@ -98,10 +100,11 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span1.context().tags["span.kind"] == "server"
|
span1.context().tags["span.kind"] == "server"
|
||||||
span1.context().tags["span.type"] == "web"
|
span1.context().tags["span.type"] == "web"
|
||||||
span1.context().tags["component"] == "java-web-servlet"
|
span1.context().tags["component"] == "java-web-servlet"
|
||||||
|
span1.context().tags["servlet.context"] == ""
|
||||||
span1.context().tags["http.status_code"] == 404
|
span1.context().tags["http.status_code"] == 404
|
||||||
span1.context().tags["thread.name"] != null
|
span1.context().tags["thread.name"] != null
|
||||||
span1.context().tags["thread.id"] != null
|
span1.context().tags["thread.id"] != null
|
||||||
span1.context().tags.size() == 8
|
span1.context().tags.size() == 9
|
||||||
}
|
}
|
||||||
|
|
||||||
def "generates error spans"() {
|
def "generates error spans"() {
|
||||||
|
@ -129,6 +132,7 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span0.context().tags["span.kind"] == "server"
|
span0.context().tags["span.kind"] == "server"
|
||||||
span0.context().tags["span.type"] == "web"
|
span0.context().tags["span.type"] == "web"
|
||||||
span0.context().tags["component"] == "java-web-servlet"
|
span0.context().tags["component"] == "java-web-servlet"
|
||||||
|
span0.context().tags["servlet.context"] == ""
|
||||||
span0.context().tags["http.status_code"] == 500
|
span0.context().tags["http.status_code"] == 500
|
||||||
span0.context().tags["thread.name"] != null
|
span0.context().tags["thread.name"] != null
|
||||||
span0.context().tags["thread.id"] != null
|
span0.context().tags["thread.id"] != null
|
||||||
|
@ -136,7 +140,7 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span0.context().tags["error.msg"] == "Request processing failed; nested exception is java.lang.RuntimeException: qwerty"
|
span0.context().tags["error.msg"] == "Request processing failed; nested exception is java.lang.RuntimeException: qwerty"
|
||||||
span0.context().tags["error.type"] == NestedServletException.getName()
|
span0.context().tags["error.type"] == NestedServletException.getName()
|
||||||
span0.context().tags["error.stack"] != null
|
span0.context().tags["error.stack"] != null
|
||||||
span0.context().tags.size() == 12
|
span0.context().tags.size() == 13
|
||||||
|
|
||||||
and: // trace 1
|
and: // trace 1
|
||||||
def trace1 = TEST_WRITER.get(1)
|
def trace1 = TEST_WRITER.get(1)
|
||||||
|
@ -152,11 +156,12 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span1.context().tags["span.kind"] == "server"
|
span1.context().tags["span.kind"] == "server"
|
||||||
span1.context().tags["span.type"] == "web"
|
span1.context().tags["span.type"] == "web"
|
||||||
span1.context().tags["component"] == "java-web-servlet"
|
span1.context().tags["component"] == "java-web-servlet"
|
||||||
|
span1.context().tags["servlet.context"] == ""
|
||||||
span1.context().tags["http.status_code"] == 500
|
span1.context().tags["http.status_code"] == 500
|
||||||
span1.context().getErrorFlag()
|
span1.context().getErrorFlag()
|
||||||
span1.context().tags["thread.name"] != null
|
span1.context().tags["thread.name"] != null
|
||||||
span1.context().tags["thread.id"] != null
|
span1.context().tags["thread.id"] != null
|
||||||
span1.context().tags.size() == 9
|
span1.context().tags.size() == 10
|
||||||
}
|
}
|
||||||
|
|
||||||
def "validated form"() {
|
def "validated form"() {
|
||||||
|
@ -179,10 +184,11 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span.context().tags["span.kind"] == "server"
|
span.context().tags["span.kind"] == "server"
|
||||||
span.context().tags["span.type"] == "web"
|
span.context().tags["span.type"] == "web"
|
||||||
span.context().tags["component"] == "java-web-servlet"
|
span.context().tags["component"] == "java-web-servlet"
|
||||||
|
span.context().tags["servlet.context"] == ""
|
||||||
span.context().tags["http.status_code"] == 200
|
span.context().tags["http.status_code"] == 200
|
||||||
span.context().tags["thread.name"] != null
|
span.context().tags["thread.name"] != null
|
||||||
span.context().tags["thread.id"] != null
|
span.context().tags["thread.id"] != null
|
||||||
span.context().tags.size() == 8
|
span.context().tags.size() == 9
|
||||||
}
|
}
|
||||||
|
|
||||||
def "invalid form"() {
|
def "invalid form"() {
|
||||||
|
@ -210,6 +216,7 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span0.context().tags["span.kind"] == "server"
|
span0.context().tags["span.kind"] == "server"
|
||||||
span0.context().tags["span.type"] == "web"
|
span0.context().tags["span.type"] == "web"
|
||||||
span0.context().tags["component"] == "java-web-servlet"
|
span0.context().tags["component"] == "java-web-servlet"
|
||||||
|
span0.context().tags["servlet.context"] == ""
|
||||||
span0.context().tags["http.status_code"] == 400
|
span0.context().tags["http.status_code"] == 400
|
||||||
span0.context().tags["thread.name"] != null
|
span0.context().tags["thread.name"] != null
|
||||||
span0.context().tags["thread.id"] != null
|
span0.context().tags["thread.id"] != null
|
||||||
|
@ -217,7 +224,7 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span0.context().tags["error.msg"].toString().startsWith("Validation failed")
|
span0.context().tags["error.msg"].toString().startsWith("Validation failed")
|
||||||
span0.context().tags["error.type"] == MethodArgumentNotValidException.getName()
|
span0.context().tags["error.type"] == MethodArgumentNotValidException.getName()
|
||||||
span0.context().tags["error.stack"] != null
|
span0.context().tags["error.stack"] != null
|
||||||
span0.context().tags.size() == 12
|
span0.context().tags.size() == 13
|
||||||
|
|
||||||
and: // trace 1
|
and: // trace 1
|
||||||
def trace1 = TEST_WRITER.get(1)
|
def trace1 = TEST_WRITER.get(1)
|
||||||
|
@ -234,9 +241,10 @@ class SpringBootBasedTest extends AgentTestRunner {
|
||||||
span1.context().tags["span.kind"] == "server"
|
span1.context().tags["span.kind"] == "server"
|
||||||
span1.context().tags["span.type"] == "web"
|
span1.context().tags["span.type"] == "web"
|
||||||
span1.context().tags["component"] == "java-web-servlet"
|
span1.context().tags["component"] == "java-web-servlet"
|
||||||
|
span1.context().tags["servlet.context"] == ""
|
||||||
span1.context().tags["http.status_code"] == 400
|
span1.context().tags["http.status_code"] == 400
|
||||||
span1.context().tags["thread.name"] != null
|
span1.context().tags["thread.name"] != null
|
||||||
span1.context().tags["thread.id"] != null
|
span1.context().tags["thread.id"] != null
|
||||||
span1.context().tags.size() == 8
|
span1.context().tags.size() == 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,12 +86,4 @@ public final class TraceAnnotationsInstrumentation extends Instrumenter.Configur
|
||||||
.advice(isAnnotatedWith(methodTraceMatcher), TraceAdvice.class.getName()))
|
.advice(isAnnotatedWith(methodTraceMatcher), TraceAdvice.class.getName()))
|
||||||
.asDecorator();
|
.asDecorator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPropOrEnv(final String name) {
|
|
||||||
return System.getProperty(name, System.getenv(propToEnvName(name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static String propToEnvName(final String name) {
|
|
||||||
return name.toUpperCase().replace(".", "_");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,12 +102,4 @@ public class TraceConfigInstrumentation extends Instrumenter.Configurable {
|
||||||
}
|
}
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPropOrEnv(final String name) {
|
|
||||||
return System.getProperty(name, System.getenv(propToEnvName(name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static String propToEnvName(final String name) {
|
|
||||||
return name.toUpperCase().replace(".", "_");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ import datadog.opentracing.DDSpan
|
||||||
|
|
||||||
class TagsAssert {
|
class TagsAssert {
|
||||||
private final Map<String, Object> tags
|
private final Map<String, Object> tags
|
||||||
private final Set<String> assertedTags = new HashSet<>()
|
private final Set<String> assertedTags = new TreeSet<>()
|
||||||
|
|
||||||
private TagsAssert(DDSpan span) {
|
private TagsAssert(DDSpan span) {
|
||||||
this.tags = span.tags
|
this.tags = new TreeMap(span.tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
static TagsAssert assertTags(DDSpan span,
|
static TagsAssert assertTags(DDSpan span,
|
||||||
|
|
|
@ -241,7 +241,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
|
||||||
|
|
||||||
// Call decorators
|
// Call decorators
|
||||||
final List<AbstractDecorator> decorators = tracer.getSpanContextDecorators(tag);
|
final List<AbstractDecorator> decorators = tracer.getSpanContextDecorators(tag);
|
||||||
if (decorators != null && value != null) {
|
if (decorators != null) {
|
||||||
for (final AbstractDecorator decorator : decorators) {
|
for (final AbstractDecorator decorator : decorators) {
|
||||||
try {
|
try {
|
||||||
addTag &= decorator.shouldSetTag(this, tag, value);
|
addTag &= decorator.shouldSetTag(this, tag, value);
|
||||||
|
|
|
@ -7,7 +7,6 @@ import datadog.opentracing.propagation.ExtractedContext;
|
||||||
import datadog.opentracing.propagation.HTTPCodec;
|
import datadog.opentracing.propagation.HTTPCodec;
|
||||||
import datadog.opentracing.scopemanager.ContextualScopeManager;
|
import datadog.opentracing.scopemanager.ContextualScopeManager;
|
||||||
import datadog.opentracing.scopemanager.ScopeContext;
|
import datadog.opentracing.scopemanager.ScopeContext;
|
||||||
import datadog.trace.api.DDTags;
|
|
||||||
import datadog.trace.api.interceptor.MutableSpan;
|
import datadog.trace.api.interceptor.MutableSpan;
|
||||||
import datadog.trace.api.interceptor.TraceInterceptor;
|
import datadog.trace.api.interceptor.TraceInterceptor;
|
||||||
import datadog.trace.api.sampling.PrioritySampling;
|
import datadog.trace.api.sampling.PrioritySampling;
|
||||||
|
@ -379,16 +378,8 @@ public class DDTracer implements io.opentracing.Tracer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DDSpanBuilder withTag(final String tag, final String string) {
|
public DDSpanBuilder withTag(final String tag, final String string) {
|
||||||
if (tag.equals(DDTags.SERVICE_NAME)) {
|
|
||||||
return withServiceName(string);
|
|
||||||
} else if (tag.equals(DDTags.RESOURCE_NAME)) {
|
|
||||||
return withResourceName(string);
|
|
||||||
} else if (tag.equals(DDTags.SPAN_TYPE)) {
|
|
||||||
return withSpanType(string);
|
|
||||||
} else {
|
|
||||||
return withTag(tag, (Object) string);
|
return withTag(tag, (Object) string);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DDSpanBuilder withTag(final String tag, final boolean bool) {
|
public DDSpanBuilder withTag(final String tag, final boolean bool) {
|
||||||
|
@ -534,6 +525,36 @@ public class DDTracer implements io.opentracing.Tracer {
|
||||||
parentTrace,
|
parentTrace,
|
||||||
DDTracer.this);
|
DDTracer.this);
|
||||||
|
|
||||||
|
// Apply Decorators to handle any tags that may have been set via the builder.
|
||||||
|
for (final Map.Entry<String, Object> tag : this.tags.entrySet()) {
|
||||||
|
if (tag.getValue() == null) {
|
||||||
|
context.setTag(tag.getKey(), null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean addTag = true;
|
||||||
|
|
||||||
|
// Call decorators
|
||||||
|
final List<AbstractDecorator> decorators =
|
||||||
|
DDTracer.this.getSpanContextDecorators(tag.getKey());
|
||||||
|
if (decorators != null) {
|
||||||
|
for (final AbstractDecorator decorator : decorators) {
|
||||||
|
try {
|
||||||
|
addTag &= decorator.shouldSetTag(context, tag.getKey(), tag.getValue());
|
||||||
|
} catch (final Throwable ex) {
|
||||||
|
log.debug(
|
||||||
|
"Could not decorate the span decorator={}: {}",
|
||||||
|
decorator.getClass().getSimpleName(),
|
||||||
|
ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addTag) {
|
||||||
|
context.setTag(tag.getKey(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class DDDecoratorsFactory {
|
||||||
new OperationDecorator(),
|
new OperationDecorator(),
|
||||||
new ResourceNameDecorator(),
|
new ResourceNameDecorator(),
|
||||||
new ServiceNameDecorator(mappings),
|
new ServiceNameDecorator(mappings),
|
||||||
|
new ServletContextDecorator(),
|
||||||
new SpanTypeDecorator(),
|
new SpanTypeDecorator(),
|
||||||
new Status5XXDecorator(),
|
new Status5XXDecorator(),
|
||||||
new Status404Decorator(),
|
new Status404Decorator(),
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package datadog.opentracing.decorators;
|
||||||
|
|
||||||
|
import datadog.opentracing.DDSpanContext;
|
||||||
|
import datadog.opentracing.DDTracer;
|
||||||
|
|
||||||
|
public class ServletContextDecorator extends AbstractDecorator {
|
||||||
|
|
||||||
|
public ServletContextDecorator() {
|
||||||
|
super();
|
||||||
|
this.setMatchingTag("servlet.context");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldSetTag(final DDSpanContext context, final String tag, final Object value) {
|
||||||
|
String contextName = String.valueOf(value).trim();
|
||||||
|
if (contextName.equals("/")
|
||||||
|
|| (!context.getServiceName().equals(DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME)
|
||||||
|
&& !context.getServiceName().isEmpty())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (contextName.startsWith("/")) {
|
||||||
|
if (contextName.length() > 1) {
|
||||||
|
contextName = contextName.substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!contextName.isEmpty()) {
|
||||||
|
context.setServiceName(contextName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,9 +53,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set operation name"() {
|
def "set operation name"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new OperationDecorator())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
Tags.COMPONENT.set(span, component)
|
Tags.COMPONENT.set(span, component)
|
||||||
|
|
||||||
|
@ -68,9 +65,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set resource name"() {
|
def "set resource name"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new ResourceNameDecorator())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
span.setTag(DDTags.RESOURCE_NAME, name)
|
span.setTag(DDTags.RESOURCE_NAME, name)
|
||||||
|
|
||||||
|
@ -82,9 +76,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set span type"() {
|
def "set span type"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new SpanTypeDecorator())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
span.setTag(DDTags.SPAN_TYPE, type)
|
span.setTag(DDTags.SPAN_TYPE, type)
|
||||||
|
|
||||||
|
@ -96,9 +87,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "override operation with DBTypeDecorator"() {
|
def "override operation with DBTypeDecorator"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new DBTypeDecorator())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
Tags.DB_TYPE.set(span, type)
|
Tags.DB_TYPE.set(span, type)
|
||||||
|
|
||||||
|
@ -119,9 +107,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "DBStatementAsResource should not interact on Mongo queries"() {
|
def "DBStatementAsResource should not interact on Mongo queries"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new DBStatementAsResourceName())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
span.setResourceName("not-change-me")
|
span.setResourceName("not-change-me")
|
||||||
Tags.COMPONENT.set(span, "java-mongo")
|
Tags.COMPONENT.set(span, "java-mongo")
|
||||||
|
@ -144,9 +129,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set 404 as a resource on a 404 issue"() {
|
def "set 404 as a resource on a 404 issue"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new Status404Decorator())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
Tags.HTTP_STATUS.set(span, 404)
|
Tags.HTTP_STATUS.set(span, 404)
|
||||||
|
|
||||||
|
@ -155,9 +137,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set 5XX status code as an error"() {
|
def "set 5XX status code as an error"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new Status5XXDecorator())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
Tags.HTTP_STATUS.set(span, status)
|
Tags.HTTP_STATUS.set(span, status)
|
||||||
|
|
||||||
|
@ -176,9 +155,6 @@ class SpanDecoratorTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set error flag when error tag reported"() {
|
def "set error flag when error tag reported"() {
|
||||||
setup:
|
|
||||||
tracer.addDecorator(new ErrorFlag())
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
Tags.ERROR.set(span, error)
|
Tags.ERROR.set(span, error)
|
||||||
|
|
||||||
|
@ -190,4 +166,56 @@ class SpanDecoratorTest extends Specification {
|
||||||
true | _
|
true | _
|
||||||
false | _
|
false | _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "#attribute decorators apply to builder too"() {
|
||||||
|
setup:
|
||||||
|
def span = tracer.buildSpan("decorator.test").withTag(name, value).start()
|
||||||
|
|
||||||
|
expect:
|
||||||
|
span.context()."$attribute" == value
|
||||||
|
|
||||||
|
where:
|
||||||
|
attribute | name | value
|
||||||
|
"serviceName" | DDTags.SERVICE_NAME | "my-service"
|
||||||
|
"resourceName" | DDTags.RESOURCE_NAME | "my-resource"
|
||||||
|
"spanType" | DDTags.SPAN_TYPE | "my-span-type"
|
||||||
|
}
|
||||||
|
|
||||||
|
def "decorators apply to builder too"() {
|
||||||
|
when:
|
||||||
|
def span = tracer.buildSpan("decorator.test").withTag("servlet.context", "/my-servlet").start()
|
||||||
|
|
||||||
|
then:
|
||||||
|
span.serviceName == "my-servlet"
|
||||||
|
|
||||||
|
when:
|
||||||
|
span = tracer.buildSpan("decorator.test").withTag(Tags.HTTP_STATUS.key, 404).start()
|
||||||
|
|
||||||
|
then:
|
||||||
|
span.resourceName == "404"
|
||||||
|
|
||||||
|
when:
|
||||||
|
span = tracer.buildSpan("decorator.test").withTag("error", "true").start()
|
||||||
|
|
||||||
|
then:
|
||||||
|
span.error
|
||||||
|
|
||||||
|
when:
|
||||||
|
span = tracer.buildSpan("decorator.test").withTag(Tags.HTTP_STATUS.key, 500).start()
|
||||||
|
|
||||||
|
then:
|
||||||
|
span.error
|
||||||
|
|
||||||
|
when:
|
||||||
|
span = tracer.buildSpan("decorator.test").withTag(Tags.HTTP_URL.key, "http://example.com/path/number123/?param=true").start()
|
||||||
|
|
||||||
|
then:
|
||||||
|
span.resourceName == "/path/?/"
|
||||||
|
|
||||||
|
when:
|
||||||
|
span = tracer.buildSpan("decorator.test").withTag(Tags.DB_STATEMENT.key, "some-statement").start()
|
||||||
|
|
||||||
|
then:
|
||||||
|
span.resourceName == "some-statement"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ class DDTraceConfigTest extends Specification {
|
||||||
tracer.sampler instanceof AllSampler
|
tracer.sampler instanceof AllSampler
|
||||||
tracer.writer.toString() == "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:8126/v0.3/traces } }"
|
tracer.writer.toString() == "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:8126/v0.3/traces } }"
|
||||||
|
|
||||||
tracer.spanContextDecorators.size() == 9
|
tracer.spanContextDecorators.size() == 10
|
||||||
}
|
}
|
||||||
|
|
||||||
def "verify mapping configs on tracer"() {
|
def "verify mapping configs on tracer"() {
|
||||||
|
|
Loading…
Reference in New Issue