Merge pull request #71 from gpolaert/operation-name
Override the operation name
This commit is contained in:
commit
7667fb6021
|
@ -5,6 +5,7 @@ import com.mongodb.MongoClientOptions;
|
||||||
import com.mongodb.event.CommandStartedEvent;
|
import com.mongodb.event.CommandStartedEvent;
|
||||||
import io.opentracing.Span;
|
import io.opentracing.Span;
|
||||||
import io.opentracing.contrib.mongo.TracingCommandListener;
|
import io.opentracing.contrib.mongo.TracingCommandListener;
|
||||||
|
import io.opentracing.tag.Tags;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -50,8 +51,14 @@ public class MongoHelper extends DDAgentTracingHelper<MongoClientOptions.Builder
|
||||||
|
|
||||||
public void decorate(final Span span, final CommandStartedEvent event) {
|
public void decorate(final Span span, final CommandStartedEvent event) {
|
||||||
try {
|
try {
|
||||||
|
// normalize the Mongo command so that parameters are removed from the string
|
||||||
final BsonDocument normalized = norm(event.getCommand());
|
final BsonDocument normalized = norm(event.getCommand());
|
||||||
span.setTag(DDTags.RESOURCE_NAME, normalized.toString());
|
final String mongoCmd = normalized.toString();
|
||||||
|
|
||||||
|
// add specific resource name and replace the `db.statement` OpenTracing
|
||||||
|
// tag with the quantized version of the Mongo command
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, mongoCmd);
|
||||||
|
span.setTag(Tags.DB_STATEMENT.getKey(), mongoCmd);
|
||||||
} catch (final Throwable e) {
|
} catch (final Throwable e) {
|
||||||
log.warn("Couldn't decorate the mongo query: " + e.getMessage(), e);
|
log.warn("Couldn't decorate the mongo query: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.datadoghq.trace;
|
package com.datadoghq.trace;
|
||||||
|
|
||||||
import com.datadoghq.trace.integration.DDSpanContextDecorator;
|
import com.datadoghq.trace.integration.AbstractDecorator;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import io.opentracing.tag.Tags;
|
import io.opentracing.tag.Tags;
|
||||||
|
@ -28,28 +28,27 @@ public class DDSpanContext implements io.opentracing.SpanContext {
|
||||||
private final long parentId;
|
private final long parentId;
|
||||||
private final String threadName = Thread.currentThread().getName();
|
private final String threadName = Thread.currentThread().getName();
|
||||||
private final long threadId = Thread.currentThread().getId();
|
private final long threadId = Thread.currentThread().getId();
|
||||||
private Map<String, String> baggageItems;
|
/** The collection of all span related to this one */
|
||||||
|
private final Queue<DDBaseSpan<?>> trace;
|
||||||
|
|
||||||
// DD attributes
|
// DD attributes
|
||||||
|
/** For technical reasons, the ref to the original tracer */
|
||||||
|
private final DDTracer tracer;
|
||||||
|
|
||||||
|
private Map<String, String> baggageItems;
|
||||||
/** The service name is required, otherwise the span are dropped by the agent */
|
/** The service name is required, otherwise the span are dropped by the agent */
|
||||||
private String serviceName;
|
private String serviceName;
|
||||||
/** The resource associated to the service (server_web, database, etc.) */
|
/** The resource associated to the service (server_web, database, etc.) */
|
||||||
private String resourceName;
|
private String resourceName;
|
||||||
/** True indicates that the span reports an error */
|
/** True indicates that the span reports an error */
|
||||||
private boolean errorFlag;
|
private boolean errorFlag;
|
||||||
|
|
||||||
/** The type of the span. If null, the Datadog Agent will report as a custom */
|
/** The type of the span. If null, the Datadog Agent will report as a custom */
|
||||||
private String spanType;
|
private String spanType;
|
||||||
/** The collection of all span related to this one */
|
|
||||||
private final Queue<DDBaseSpan<?>> trace;
|
|
||||||
/** Each span have an operation name describing the current span */
|
/** Each span have an operation name describing the current span */
|
||||||
private String operationName;
|
private String operationName;
|
||||||
|
// Others attributes
|
||||||
/** Tags are associated to the current span, they will not propagate to the children span */
|
/** Tags are associated to the current span, they will not propagate to the children span */
|
||||||
private Map<String, Object> tags;
|
private Map<String, Object> tags;
|
||||||
// Others attributes
|
|
||||||
/** For technical reasons, the ref to the original tracer */
|
|
||||||
private final DDTracer tracer;
|
|
||||||
|
|
||||||
public DDSpanContext(
|
public DDSpanContext(
|
||||||
final long traceId,
|
final long traceId,
|
||||||
|
@ -109,12 +108,20 @@ public class DDSpanContext implements io.opentracing.SpanContext {
|
||||||
return serviceName;
|
return serviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setServiceName(final String serviceName) {
|
||||||
|
this.serviceName = serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getResourceName() {
|
public String getResourceName() {
|
||||||
return this.resourceName == null || this.resourceName.isEmpty()
|
return this.resourceName == null || this.resourceName.isEmpty()
|
||||||
? this.operationName
|
? this.operationName
|
||||||
: this.resourceName;
|
: this.resourceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setResourceName(final String resourceName) {
|
||||||
|
this.resourceName = resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getErrorFlag() {
|
public boolean getErrorFlag() {
|
||||||
return errorFlag;
|
return errorFlag;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +134,10 @@ public class DDSpanContext implements io.opentracing.SpanContext {
|
||||||
return spanType;
|
return spanType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSpanType(final String spanType) {
|
||||||
|
this.spanType = spanType;
|
||||||
|
}
|
||||||
|
|
||||||
public void setBaggageItem(final String key, final String value) {
|
public void setBaggageItem(final String key, final String value) {
|
||||||
if (this.baggageItems.isEmpty()) {
|
if (this.baggageItems.isEmpty()) {
|
||||||
this.baggageItems = new HashMap<String, String>();
|
this.baggageItems = new HashMap<String, String>();
|
||||||
|
@ -184,9 +195,9 @@ public class DDSpanContext implements io.opentracing.SpanContext {
|
||||||
this.tags.put(tag, value);
|
this.tags.put(tag, value);
|
||||||
|
|
||||||
//Call decorators
|
//Call decorators
|
||||||
final List<DDSpanContextDecorator> decorators = tracer.getSpanContextDecorators(tag);
|
final List<AbstractDecorator> decorators = tracer.getSpanContextDecorators(tag);
|
||||||
if (decorators != null) {
|
if (decorators != null) {
|
||||||
for (final DDSpanContextDecorator decorator : decorators) {
|
for (final AbstractDecorator decorator : decorators) {
|
||||||
decorator.afterSetTag(this, tag, value);
|
decorator.afterSetTag(this, tag, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,23 +234,11 @@ public class DDSpanContext implements io.opentracing.SpanContext {
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOperationName(final String operationName) {
|
|
||||||
this.operationName = operationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOperationName() {
|
public String getOperationName() {
|
||||||
return operationName;
|
return operationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServiceName(final String serviceName) {
|
public void setOperationName(final String operationName) {
|
||||||
this.serviceName = serviceName;
|
this.operationName = operationName;
|
||||||
}
|
|
||||||
|
|
||||||
public void setResourceName(final String resourceName) {
|
|
||||||
this.resourceName = resourceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSpanType(final String spanType) {
|
|
||||||
this.spanType = spanType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.datadoghq.trace;
|
package com.datadoghq.trace;
|
||||||
|
|
||||||
import com.datadoghq.trace.integration.DDSpanContextDecorator;
|
import com.datadoghq.trace.integration.AbstractDecorator;
|
||||||
import com.datadoghq.trace.propagation.Codec;
|
import com.datadoghq.trace.propagation.Codec;
|
||||||
import com.datadoghq.trace.propagation.HTTPCodec;
|
import com.datadoghq.trace.propagation.HTTPCodec;
|
||||||
import com.datadoghq.trace.sampling.AllSampler;
|
import com.datadoghq.trace.sampling.AllSampler;
|
||||||
|
@ -39,7 +39,7 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac
|
||||||
private final String defaultServiceName;
|
private final String defaultServiceName;
|
||||||
|
|
||||||
/** Span context decorators */
|
/** Span context decorators */
|
||||||
private final Map<String, List<DDSpanContextDecorator>> spanContextDecorators = new HashMap<>();
|
private final Map<String, List<AbstractDecorator>> spanContextDecorators = new HashMap<>();
|
||||||
|
|
||||||
private final CodecRegistry registry;
|
private final CodecRegistry registry;
|
||||||
|
|
||||||
|
@ -70,18 +70,18 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac
|
||||||
*
|
*
|
||||||
* @return the list of span context decorators
|
* @return the list of span context decorators
|
||||||
*/
|
*/
|
||||||
public List<DDSpanContextDecorator> getSpanContextDecorators(final String tag) {
|
public List<AbstractDecorator> getSpanContextDecorators(final String tag) {
|
||||||
return spanContextDecorators.get(tag);
|
return spanContextDecorators.get(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new decorator in the list ({@link DDSpanContextDecorator})
|
* Add a new decorator in the list ({@link AbstractDecorator})
|
||||||
*
|
*
|
||||||
* @param decorator The decorator in the list
|
* @param decorator The decorator in the list
|
||||||
*/
|
*/
|
||||||
public void addDecorator(final DDSpanContextDecorator decorator) {
|
public void addDecorator(final AbstractDecorator decorator) {
|
||||||
|
|
||||||
List<DDSpanContextDecorator> list = spanContextDecorators.get(decorator.getMatchingTag());
|
List<AbstractDecorator> list = spanContextDecorators.get(decorator.getMatchingTag());
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import com.datadoghq.trace.DDTags;
|
||||||
* Span decorators are called when new tags are written and proceed to various remappings and
|
* Span decorators are called when new tags are written and proceed to various remappings and
|
||||||
* enrichments
|
* enrichments
|
||||||
*/
|
*/
|
||||||
public abstract class DDSpanContextDecorator {
|
public abstract class AbstractDecorator {
|
||||||
|
|
||||||
private String matchingTag;
|
private String matchingTag;
|
||||||
|
|
||||||
|
@ -17,10 +17,10 @@ public abstract class DDSpanContextDecorator {
|
||||||
|
|
||||||
private String setValue;
|
private String setValue;
|
||||||
|
|
||||||
public boolean afterSetTag(DDSpanContext context, String tag, Object value) {
|
public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) {
|
||||||
if ((this.getMatchingValue() == null || value.equals(this.getMatchingValue()))) {
|
if ((this.getMatchingValue() == null || value.equals(this.getMatchingValue()))) {
|
||||||
String targetTag = getSetTag() == null ? tag : getSetTag();
|
final String targetTag = getSetTag() == null ? tag : getSetTag();
|
||||||
String targetValue = getSetValue() == null ? String.valueOf(value) : getSetValue();
|
final String targetValue = getSetValue() == null ? String.valueOf(value) : getSetValue();
|
||||||
|
|
||||||
if (targetTag.equals(DDTags.SERVICE_NAME)) {
|
if (targetTag.equals(DDTags.SERVICE_NAME)) {
|
||||||
context.setServiceName(targetValue);
|
context.setServiceName(targetValue);
|
||||||
|
@ -41,7 +41,7 @@ public abstract class DDSpanContextDecorator {
|
||||||
return matchingTag;
|
return matchingTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMatchingTag(String tag) {
|
public void setMatchingTag(final String tag) {
|
||||||
this.matchingTag = tag;
|
this.matchingTag = tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public abstract class DDSpanContextDecorator {
|
||||||
return matchingValue;
|
return matchingValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMatchingValue(String value) {
|
public void setMatchingValue(final String value) {
|
||||||
this.matchingValue = value;
|
this.matchingValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public abstract class DDSpanContextDecorator {
|
||||||
return setTag;
|
return setTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSetTag(String targetTag) {
|
public void setSetTag(final String targetTag) {
|
||||||
this.setTag = targetTag;
|
this.setTag = targetTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public abstract class DDSpanContextDecorator {
|
||||||
return setValue;
|
return setValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSetValue(String targetValue) {
|
public void setSetValue(final String targetValue) {
|
||||||
this.setValue = targetValue;
|
this.setValue = targetValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,42 +3,11 @@ package com.datadoghq.trace.integration;
|
||||||
import com.datadoghq.trace.DDTags;
|
import com.datadoghq.trace.DDTags;
|
||||||
import io.opentracing.tag.Tags;
|
import io.opentracing.tag.Tags;
|
||||||
|
|
||||||
public class DBStatementAsResourceName extends DDSpanContextDecorator {
|
public class DBStatementAsResourceName extends AbstractDecorator {
|
||||||
|
|
||||||
public DBStatementAsResourceName() {
|
public DBStatementAsResourceName() {
|
||||||
super();
|
super();
|
||||||
this.setMatchingTag(Tags.DB_STATEMENT.getKey());
|
this.setMatchingTag(Tags.DB_STATEMENT.getKey());
|
||||||
this.setSetTag(DDTags.RESOURCE_NAME);
|
this.setSetTag(DDTags.RESOURCE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
//{ "insert" : "calls", "ordered" : true, "documents" : [{ "_id" : { "$oid" : "5979bbb0ed6fed5749cc9e7c" }, "name" : "MongoDB", "type" : "database", "identifier" : "10", "versions" : ["v3.2", "v3.0", "v2.6"], "info" : { "x" : 203, "y" : 102 } }] }
|
|
||||||
private void normalizeFilter(final Object f) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
def normalize_filter(f=None):
|
|
||||||
if f is None:
|
|
||||||
return {}
|
|
||||||
elif isinstance(f, list):
|
|
||||||
# normalize lists of filters
|
|
||||||
# e.g. {$or: [ { age: { $lt: 30 } }, { type: 1 } ]}
|
|
||||||
return [normalize_filter(s) for s in f]
|
|
||||||
elif isinstance(f, dict):
|
|
||||||
# normalize dicts of filters
|
|
||||||
# {$or: [ { age: { $lt: 30 } }, { type: 1 } ]})
|
|
||||||
out = {}
|
|
||||||
for k, v in iteritems(f):
|
|
||||||
if k == "$in" or k == "$nin":
|
|
||||||
# special case $in queries so we don't loop over lists.
|
|
||||||
out[k] = "?"
|
|
||||||
elif isinstance(v, list) or isinstance(v, dict):
|
|
||||||
# RECURSION ALERT: needs to move to the agent
|
|
||||||
out[k] = normalize_filter(v)
|
|
||||||
else:
|
|
||||||
# NOTE: this shouldn't happen, but let's have a safeguard.
|
|
||||||
out[k] = '?'
|
|
||||||
return out
|
|
||||||
else:
|
|
||||||
# FIXME[matt] unexpected type. not sure this should ever happen, but at
|
|
||||||
# least it won't crash.
|
|
||||||
return {}*/
|
|
||||||
|
|
|
@ -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
|
* 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
|
* retrieves some DB meta such as the statement
|
||||||
*/
|
*/
|
||||||
public class DBComponent extends DDSpanContextDecorator {
|
public class DBTypeDecorator extends AbstractDecorator {
|
||||||
|
|
||||||
public DBComponent() {
|
public DBTypeDecorator() {
|
||||||
super();
|
super();
|
||||||
this.setMatchingTag(Tags.DB_TYPE.getKey());
|
this.setMatchingTag(Tags.DB_TYPE.getKey());
|
||||||
this.setSetTag(DDTags.SERVICE_NAME);
|
this.setSetTag(DDTags.SERVICE_NAME);
|
||||||
|
@ -22,6 +22,8 @@ public class DBComponent extends DDSpanContextDecorator {
|
||||||
if (super.afterSetTag(context, tag, value)) {
|
if (super.afterSetTag(context, tag, value)) {
|
||||||
//Assign span type to DB
|
//Assign span type to DB
|
||||||
context.setSpanType("db");
|
context.setSpanType("db");
|
||||||
|
// Works for: mongo, cassandra, jdbc
|
||||||
|
context.setOperationName(String.valueOf(value) + ".query");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
|
@ -3,18 +3,18 @@ package com.datadoghq.trace.integration;
|
||||||
import com.datadoghq.trace.DDSpanContext;
|
import com.datadoghq.trace.DDSpanContext;
|
||||||
import io.opentracing.tag.Tags;
|
import io.opentracing.tag.Tags;
|
||||||
|
|
||||||
public class ErrorFlag extends DDSpanContextDecorator {
|
public class ErrorFlag extends AbstractDecorator {
|
||||||
public ErrorFlag() {
|
public ErrorFlag() {
|
||||||
super();
|
super();
|
||||||
this.setMatchingTag(Tags.ERROR.getKey());
|
this.setMatchingTag(Tags.ERROR.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean afterSetTag(DDSpanContext context, String tag, Object value) {
|
public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) {
|
||||||
//Assign resource name
|
//Assign resource name
|
||||||
try {
|
try {
|
||||||
context.setErrorFlag(Boolean.parseBoolean(String.valueOf(value)));
|
context.setErrorFlag(Boolean.parseBoolean(String.valueOf(value)));
|
||||||
} catch (Throwable t) {
|
} catch (final Throwable t) {
|
||||||
//DO NOTHING
|
//DO NOTHING
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import io.opentracing.tag.Tags;
|
||||||
* This span decorator leverages HTTP tags. It allows the dev to define a custom service name and
|
* This span decorator leverages HTTP tags. It allows the dev to define a custom service name and
|
||||||
* retrieves some HTTP meta such as the request path
|
* retrieves some HTTP meta such as the request path
|
||||||
*/
|
*/
|
||||||
public class HTTPComponent extends DDSpanContextDecorator {
|
public class HTTPComponent extends AbstractDecorator {
|
||||||
|
|
||||||
public HTTPComponent() {
|
public HTTPComponent() {
|
||||||
super();
|
super();
|
||||||
|
@ -17,7 +17,7 @@ public class HTTPComponent extends DDSpanContextDecorator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean afterSetTag(DDSpanContext context, String tag, Object value) {
|
public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) {
|
||||||
//Assign service name
|
//Assign service name
|
||||||
if (super.afterSetTag(context, tag, value)) {
|
if (super.afterSetTag(context, tag, value)) {
|
||||||
//Assign span type to WEB
|
//Assign span type to WEB
|
||||||
|
|
|
@ -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<String, String> MAPPINGS =
|
||||||
|
new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ import com.datadoghq.trace.DDTags;
|
||||||
import io.opentracing.tag.Tags;
|
import io.opentracing.tag.Tags;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
public class URLAsResourceName extends DDSpanContextDecorator {
|
public class URLAsResourceName extends AbstractDecorator {
|
||||||
|
|
||||||
public URLAsResourceName() {
|
public URLAsResourceName() {
|
||||||
super();
|
super();
|
||||||
|
@ -14,12 +14,12 @@ public class URLAsResourceName extends DDSpanContextDecorator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean afterSetTag(DDSpanContext context, String tag, Object value) {
|
public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) {
|
||||||
//Assign resource name
|
//Assign resource name
|
||||||
try {
|
try {
|
||||||
String path = new java.net.URL(String.valueOf(value)).getPath();
|
final String path = new java.net.URL(String.valueOf(value)).getPath();
|
||||||
context.setResourceName(path);
|
context.setResourceName(path);
|
||||||
} catch (MalformedURLException e) {
|
} catch (final MalformedURLException e) {
|
||||||
context.setResourceName(String.valueOf(value));
|
context.setResourceName(String.valueOf(value));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.datadoghq.trace.resolver;
|
package com.datadoghq.trace.resolver;
|
||||||
|
|
||||||
import com.datadoghq.trace.integration.DDSpanContextDecorator;
|
import com.datadoghq.trace.integration.AbstractDecorator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -9,9 +9,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DDDecoratorsFactory {
|
public class DDDecoratorsFactory {
|
||||||
|
|
||||||
public static String DECORATORS_PACKAGE = "com.datadoghq.trace.integration.";
|
|
||||||
|
|
||||||
public static final String CONFIG_PATH = "dd-trace-decorators";
|
public static final String CONFIG_PATH = "dd-trace-decorators";
|
||||||
|
public static String DECORATORS_PACKAGE = "com.datadoghq.trace.integration.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create decorators from configuration
|
* Create decorators from configuration
|
||||||
|
@ -19,9 +18,8 @@ public class DDDecoratorsFactory {
|
||||||
* @param decoratorsConfig
|
* @param decoratorsConfig
|
||||||
* @return the list of instanciated and configured decorators
|
* @return the list of instanciated and configured decorators
|
||||||
*/
|
*/
|
||||||
public static List<DDSpanContextDecorator> create(
|
public static List<AbstractDecorator> create(final List<DDSpanDecoratorConfig> decoratorsConfig) {
|
||||||
final List<DDSpanDecoratorConfig> decoratorsConfig) {
|
final List<AbstractDecorator> decorators = new ArrayList<>();
|
||||||
final List<DDSpanContextDecorator> decorators = new ArrayList<>();
|
|
||||||
for (final DDSpanDecoratorConfig decoratorConfig : decoratorsConfig) {
|
for (final DDSpanDecoratorConfig decoratorConfig : decoratorsConfig) {
|
||||||
if (decoratorConfig.getType() == null) {
|
if (decoratorConfig.getType() == null) {
|
||||||
log.warn("Cannot create decorator without type from configuration {}", decoratorConfig);
|
log.warn("Cannot create decorator without type from configuration {}", decoratorConfig);
|
||||||
|
@ -39,9 +37,9 @@ public class DDDecoratorsFactory {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DDSpanContextDecorator decorator = null;
|
AbstractDecorator decorator = null;
|
||||||
try {
|
try {
|
||||||
decorator = (DDSpanContextDecorator) decoratorClass.getConstructor().newInstance();
|
decorator = (AbstractDecorator) decoratorClass.getConstructor().newInstance();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.warn(
|
log.warn(
|
||||||
"Cannot create decorator as we could not invoke the default constructor. Provided configuration {}",
|
"Cannot create decorator as we could not invoke the default constructor. Provided configuration {}",
|
||||||
|
@ -68,8 +66,8 @@ public class DDDecoratorsFactory {
|
||||||
return decorators;
|
return decorators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<DDSpanContextDecorator> createFromResources() {
|
public static List<AbstractDecorator> createFromResources() {
|
||||||
List<DDSpanContextDecorator> result = new ArrayList<>();
|
List<AbstractDecorator> result = new ArrayList<>();
|
||||||
final TracerConfig config =
|
final TracerConfig config =
|
||||||
FactoryUtils.loadConfigFromResource(CONFIG_PATH, TracerConfig.class);
|
FactoryUtils.loadConfigFromResource(CONFIG_PATH, TracerConfig.class);
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.datadoghq.trace.resolver;
|
package com.datadoghq.trace.resolver;
|
||||||
|
|
||||||
import com.datadoghq.trace.DDTracer;
|
import com.datadoghq.trace.DDTracer;
|
||||||
import com.datadoghq.trace.integration.DDSpanContextDecorator;
|
import com.datadoghq.trace.integration.AbstractDecorator;
|
||||||
import com.datadoghq.trace.sampling.AbstractSampler;
|
import com.datadoghq.trace.sampling.AbstractSampler;
|
||||||
import com.datadoghq.trace.sampling.AllSampler;
|
import com.datadoghq.trace.sampling.AllSampler;
|
||||||
import com.datadoghq.trace.sampling.RateSampler;
|
import com.datadoghq.trace.sampling.RateSampler;
|
||||||
|
@ -102,8 +102,8 @@ public class DDTracerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create decorators from resource files
|
//Create decorators from resource files
|
||||||
final List<DDSpanContextDecorator> decorators = DDDecoratorsFactory.createFromResources();
|
final List<AbstractDecorator> decorators = DDDecoratorsFactory.createFromResources();
|
||||||
for (final DDSpanContextDecorator decorator : decorators) {
|
for (final AbstractDecorator decorator : decorators) {
|
||||||
tracer.addDecorator(decorator);
|
tracer.addDecorator(decorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ decorators:
|
||||||
- type: HTTPComponent
|
- type: HTTPComponent
|
||||||
matchingValue: java-okhttp
|
matchingValue: java-okhttp
|
||||||
setValue: http-client
|
setValue: http-client
|
||||||
- type: DBComponent
|
|
||||||
- type: HTTPComponent
|
- type: HTTPComponent
|
||||||
matchingValue: java-aws-sdk
|
matchingValue: java-aws-sdk
|
||||||
setValue: aws-client
|
setValue: aws-client
|
||||||
# - type: DBStatementAsResourceName
|
|
||||||
- type: ErrorFlag
|
- type: ErrorFlag
|
||||||
|
- type: DBTypeDecorator
|
||||||
|
- type: OperationDecorator
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.datadoghq.trace.DDSpanContext
|
||||||
import com.datadoghq.trace.DDTracer
|
import com.datadoghq.trace.DDTracer
|
||||||
import com.datadoghq.trace.SpanFactory
|
import com.datadoghq.trace.SpanFactory
|
||||||
import io.opentracing.tag.StringTag
|
import io.opentracing.tag.StringTag
|
||||||
|
import io.opentracing.tag.Tags
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class SpanDecoratorTest extends Specification {
|
class SpanDecoratorTest extends Specification {
|
||||||
|
@ -11,7 +12,7 @@ class SpanDecoratorTest extends Specification {
|
||||||
def "adding span personalisation using Decorators"() {
|
def "adding span personalisation using Decorators"() {
|
||||||
setup:
|
setup:
|
||||||
def tracer = new DDTracer()
|
def tracer = new DDTracer()
|
||||||
def decorator = new DDSpanContextDecorator() {
|
def decorator = new AbstractDecorator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean afterSetTag(DDSpanContext context, String tag, Object value) {
|
boolean afterSetTag(DDSpanContext context, String tag, Object value) {
|
||||||
|
@ -32,4 +33,44 @@ class SpanDecoratorTest extends Specification {
|
||||||
span.getTags().containsKey("newFoo")
|
span.getTags().containsKey("newFoo")
|
||||||
span.getTags().get("newFoo") == "newBar"
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.datadoghq.trace.resolver;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import com.datadoghq.trace.DDTracer;
|
import com.datadoghq.trace.DDTracer;
|
||||||
import com.datadoghq.trace.integration.DDSpanContextDecorator;
|
import com.datadoghq.trace.integration.AbstractDecorator;
|
||||||
import com.datadoghq.trace.integration.HTTPComponent;
|
import com.datadoghq.trace.integration.HTTPComponent;
|
||||||
import com.datadoghq.trace.integration.URLAsResourceName;
|
import com.datadoghq.trace.integration.URLAsResourceName;
|
||||||
import io.opentracing.NoopTracerFactory;
|
import io.opentracing.NoopTracerFactory;
|
||||||
|
@ -19,17 +19,16 @@ public class TracerResolverTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResolve() {
|
public void testResolve() {
|
||||||
DDTracerResolver tracerResolver = new DDTracerResolver();
|
final DDTracerResolver tracerResolver = new DDTracerResolver();
|
||||||
DDTracer tracer = (DDTracer) tracerResolver.resolve();
|
final DDTracer tracer = (DDTracer) tracerResolver.resolve();
|
||||||
|
|
||||||
// for HTTP decorators
|
// for HTTP decorators
|
||||||
List<DDSpanContextDecorator> decorators =
|
List<AbstractDecorator> decorators = tracer.getSpanContextDecorators(Tags.COMPONENT.getKey());
|
||||||
tracer.getSpanContextDecorators(Tags.COMPONENT.getKey());
|
|
||||||
|
|
||||||
assertThat(decorators.size()).isEqualTo(2);
|
assertThat(decorators.size()).isEqualTo(2);
|
||||||
DDSpanContextDecorator decorator = decorators.get(0);
|
AbstractDecorator decorator = decorators.get(0);
|
||||||
assertThat(decorator.getClass()).isEqualTo(HTTPComponent.class);
|
assertThat(decorator.getClass()).isEqualTo(HTTPComponent.class);
|
||||||
HTTPComponent httpServiceDecorator = (HTTPComponent) decorator;
|
final HTTPComponent httpServiceDecorator = (HTTPComponent) decorator;
|
||||||
assertThat(httpServiceDecorator.getMatchingTag()).isEqualTo("component");
|
assertThat(httpServiceDecorator.getMatchingTag()).isEqualTo("component");
|
||||||
assertThat(httpServiceDecorator.getMatchingValue()).isEqualTo("hello");
|
assertThat(httpServiceDecorator.getMatchingValue()).isEqualTo("hello");
|
||||||
assertThat(httpServiceDecorator.getSetValue()).isEqualTo("world");
|
assertThat(httpServiceDecorator.getSetValue()).isEqualTo("world");
|
||||||
|
@ -44,13 +43,13 @@ public class TracerResolverTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResolveTracer() throws Exception {
|
public void testResolveTracer() throws Exception {
|
||||||
Field tracerField = GlobalTracer.class.getDeclaredField("tracer");
|
final Field tracerField = GlobalTracer.class.getDeclaredField("tracer");
|
||||||
tracerField.setAccessible(true);
|
tracerField.setAccessible(true);
|
||||||
tracerField.set(null, NoopTracerFactory.create());
|
tracerField.set(null, NoopTracerFactory.create());
|
||||||
|
|
||||||
assertThat(GlobalTracer.isRegistered()).isFalse();
|
assertThat(GlobalTracer.isRegistered()).isFalse();
|
||||||
|
|
||||||
Tracer tracer = TracerResolver.resolveTracer();
|
final Tracer tracer = TracerResolver.resolveTracer();
|
||||||
|
|
||||||
assertThat(GlobalTracer.isRegistered()).isFalse();
|
assertThat(GlobalTracer.isRegistered()).isFalse();
|
||||||
assertThat(tracer).isInstanceOf(DDTracer.class);
|
assertThat(tracer).isInstanceOf(DDTracer.class);
|
||||||
|
@ -58,7 +57,7 @@ public class TracerResolverTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegisterTracer() throws Exception {
|
public void testRegisterTracer() throws Exception {
|
||||||
Field tracerField = GlobalTracer.class.getDeclaredField("tracer");
|
final Field tracerField = GlobalTracer.class.getDeclaredField("tracer");
|
||||||
tracerField.setAccessible(true);
|
tracerField.setAccessible(true);
|
||||||
tracerField.set(null, NoopTracerFactory.create());
|
tracerField.set(null, NoopTracerFactory.create());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue