diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/DBTypeDecorator.java similarity index 78% rename from dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java rename to dd-trace/src/main/java/com/datadoghq/trace/integration/DBTypeDecorator.java index a26f7a7f2e..ec6782fd86 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/DBTypeDecorator.java @@ -8,9 +8,9 @@ import io.opentracing.tag.Tags; * This span decorator leverages DB tags. It allows the dev to define a custom service name and * retrieves some DB meta such as the statement */ -public class DBComponent extends DDSpanContextDecorator { +public class DBTypeDecorator extends AbstractDecorator { - public DBComponent() { + public DBTypeDecorator() { super(); this.setMatchingTag(Tags.DB_TYPE.getKey()); this.setSetTag(DDTags.SERVICE_NAME); @@ -22,6 +22,8 @@ public class DBComponent extends DDSpanContextDecorator { if (super.afterSetTag(context, tag, value)) { //Assign span type to DB context.setSpanType("db"); + // Works for: mongo, cassandra, jdbc + context.setOperationName(String.valueOf(value) + ".query"); return true; } return false; diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java deleted file mode 100644 index f43aded971..0000000000 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.datadoghq.trace.integration; - -import com.datadoghq.trace.DDSpanContext; -import com.datadoghq.trace.DDTags; - -/** - * Span decorators are called when new tags are written and proceed to various remappings and - * enrichments - */ -public abstract class DDSpanContextDecorator { - - private String matchingTag; - - private String matchingValue; - - private String setTag; - - private String setValue; - - public boolean afterSetTag(DDSpanContext context, String tag, Object value) { - if ((this.getMatchingValue() == null || value.equals(this.getMatchingValue()))) { - String targetTag = getSetTag() == null ? tag : getSetTag(); - String targetValue = getSetValue() == null ? String.valueOf(value) : getSetValue(); - - if (targetTag.equals(DDTags.SERVICE_NAME)) { - context.setServiceName(targetValue); - } else if (targetTag.equals(DDTags.RESOURCE_NAME)) { - context.setResourceName(targetValue); - } else if (targetTag.equals(DDTags.SPAN_TYPE)) { - context.setSpanType(targetValue); - } else { - context.setTag(targetTag, targetValue); - } - return true; - } else { - return false; - } - } - - public String getMatchingTag() { - return matchingTag; - } - - public void setMatchingTag(String tag) { - this.matchingTag = tag; - } - - public String getMatchingValue() { - return matchingValue; - } - - public void setMatchingValue(String value) { - this.matchingValue = value; - } - - public String getSetTag() { - return setTag; - } - - public void setSetTag(String targetTag) { - this.setTag = targetTag; - } - - public String getSetValue() { - return setValue; - } - - public void setSetValue(String targetValue) { - this.setValue = targetValue; - } -} diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/OperationDecorator.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/OperationDecorator.java new file mode 100644 index 0000000000..72ff05e703 --- /dev/null +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/OperationDecorator.java @@ -0,0 +1,43 @@ +package com.datadoghq.trace.integration; + +import com.datadoghq.trace.DDSpanContext; +import io.opentracing.tag.Tags; +import java.util.HashMap; +import java.util.Map; + +/** + * This span decorator is a simple mapping to override the operation DB tags. The operation name of + * DB integration are handled by the DBTypeDecorator + */ +public class OperationDecorator extends AbstractDecorator { + + static final Map MAPPINGS = + new HashMap() { + { + // Component name <> Operation name + put("apache-httpclient", "apache.http"); + put("java-aws-sdk", "aws.http"); + // Jetty + Tomcat (same integration used) + put("java-web-servlet", "servlet.request"); + // FIXME: JMS ops card is low (jms-send or jms-receive), may be this mapping is useless + put("java-jms", "jms"); + put("okhttp", "okhttp.http"); + // Cassandra, Mongo, JDBC are set via DBTypeDecorator + } + }; + + public OperationDecorator() { + super(); + this.setMatchingTag(Tags.COMPONENT.getKey()); + } + + @Override + public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) { + + if (MAPPINGS.containsKey(String.valueOf(value))) { + context.setOperationName(MAPPINGS.get(String.valueOf(value))); + return true; + } + return false; + } +} diff --git a/dd-trace/src/main/resources/dd-trace-decorators.yaml b/dd-trace/src/main/resources/dd-trace-decorators.yaml index a463da61f1..c06b531132 100644 --- a/dd-trace/src/main/resources/dd-trace-decorators.yaml +++ b/dd-trace/src/main/resources/dd-trace-decorators.yaml @@ -4,9 +4,8 @@ decorators: - type: HTTPComponent matchingValue: java-okhttp setValue: http-client - - type: DBComponent + - type: BDTypeDecorator - type: HTTPComponent matchingValue: java-aws-sdk setValue: aws-client -# - type: DBStatementAsResourceName - type: ErrorFlag diff --git a/dd-trace/src/test/groovy/com/datadoghq/trace/integration/SpanDecoratorTest.groovy b/dd-trace/src/test/groovy/com/datadoghq/trace/integration/SpanDecoratorTest.groovy index 8efaf390c7..5e39b5d4d8 100644 --- a/dd-trace/src/test/groovy/com/datadoghq/trace/integration/SpanDecoratorTest.groovy +++ b/dd-trace/src/test/groovy/com/datadoghq/trace/integration/SpanDecoratorTest.groovy @@ -4,6 +4,7 @@ import com.datadoghq.trace.DDSpanContext import com.datadoghq.trace.DDTracer import com.datadoghq.trace.SpanFactory import io.opentracing.tag.StringTag +import io.opentracing.tag.Tags import spock.lang.Specification class SpanDecoratorTest extends Specification { @@ -11,7 +12,7 @@ class SpanDecoratorTest extends Specification { def "adding span personalisation using Decorators"() { setup: def tracer = new DDTracer() - def decorator = new DDSpanContextDecorator() { + def decorator = new AbstractDecorator() { @Override boolean afterSetTag(DDSpanContext context, String tag, Object value) { @@ -32,4 +33,44 @@ class SpanDecoratorTest extends Specification { span.getTags().containsKey("newFoo") span.getTags().get("newFoo") == "newBar" } + + def "override operation with OperationDecorator"() { + + setup: + def tracer = new DDTracer() + def span = SpanFactory.newSpanOf(tracer) + tracer.addDecorator(new OperationDecorator()) + + when: + Tags.COMPONENT.set(span, component) + + then: + span.getOperationName() == operationName + + where: + component << OperationDecorator.MAPPINGS.keySet() + operationName << OperationDecorator.MAPPINGS.values() + + + } + + def "override operation with DBTypeDecorator"() { + + setup: + def tracer = new DDTracer() + def span = SpanFactory.newSpanOf(tracer) + tracer.addDecorator(new DBTypeDecorator()) + + when: + Tags.DB_TYPE.set(span, type) + + then: + span.getOperationName() == type + ".query" + span.context().getSpanType() == "db" + + where: + type = "foo" + + + } }