memcache
This commit is contained in:
parent
2e7899b405
commit
094552cad3
|
@ -2,6 +2,7 @@ package datadog.trace.instrumentation.spymemcached;
|
||||||
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
||||||
|
|
||||||
|
import datadog.trace.api.DDSpanTypes;
|
||||||
import datadog.trace.api.DDTags;
|
import datadog.trace.api.DDTags;
|
||||||
import io.opentracing.Scope;
|
import io.opentracing.Scope;
|
||||||
import io.opentracing.Span;
|
import io.opentracing.Span;
|
||||||
|
@ -19,12 +20,6 @@ public abstract class CompletionListener<T> {
|
||||||
static final String OPERATION_NAME = "memcached.query";
|
static final String OPERATION_NAME = "memcached.query";
|
||||||
|
|
||||||
static final String SERVICE_NAME = "memcached";
|
static final String SERVICE_NAME = "memcached";
|
||||||
/*
|
|
||||||
Ideally this should be "spymemcached" or something along those lines.
|
|
||||||
Unfortunately nondeterministic interaction between SpanTypeDecorator and DBTypeDecorator
|
|
||||||
pretty much forces this to be "sql".
|
|
||||||
*/
|
|
||||||
static final String SPAN_TYPE = "cache";
|
|
||||||
static final String COMPONENT_NAME = "java-spymemcached";
|
static final String COMPONENT_NAME = "java-spymemcached";
|
||||||
static final String DB_TYPE = "memcached";
|
static final String DB_TYPE = "memcached";
|
||||||
static final String DB_COMMAND_CANCELLED = "db.command.cancelled";
|
static final String DB_COMMAND_CANCELLED = "db.command.cancelled";
|
||||||
|
@ -35,36 +30,36 @@ public abstract class CompletionListener<T> {
|
||||||
private final Tracer tracer;
|
private final Tracer tracer;
|
||||||
private final Scope scope;
|
private final Scope scope;
|
||||||
|
|
||||||
public CompletionListener(final Tracer tracer, String methodName, boolean async) {
|
public CompletionListener(final Tracer tracer, final String methodName, final boolean async) {
|
||||||
this.tracer = tracer;
|
this.tracer = tracer;
|
||||||
scope = buildSpan(getOperationName(methodName), async);
|
scope = buildSpan(getOperationName(methodName), async);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scope buildSpan(String operation, boolean async) {
|
private Scope buildSpan(final String operation, final boolean async) {
|
||||||
final Tracer.SpanBuilder spanBuilder =
|
final Tracer.SpanBuilder spanBuilder =
|
||||||
tracer
|
tracer
|
||||||
.buildSpan(OPERATION_NAME)
|
.buildSpan(OPERATION_NAME)
|
||||||
.withTag(DDTags.SERVICE_NAME, SERVICE_NAME)
|
.withTag(DDTags.SERVICE_NAME, SERVICE_NAME)
|
||||||
.withTag(DDTags.RESOURCE_NAME, operation)
|
.withTag(DDTags.RESOURCE_NAME, operation)
|
||||||
.withTag(DDTags.SPAN_TYPE, SPAN_TYPE)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MEMCACHED)
|
||||||
.withTag(Tags.COMPONENT.getKey(), COMPONENT_NAME)
|
.withTag(Tags.COMPONENT.getKey(), COMPONENT_NAME)
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
|
||||||
.withTag(Tags.DB_TYPE.getKey(), DB_TYPE);
|
.withTag(Tags.DB_TYPE.getKey(), DB_TYPE);
|
||||||
|
|
||||||
Scope scope = spanBuilder.startActive(false);
|
final Scope scope = spanBuilder.startActive(false);
|
||||||
if (async) {
|
if (async) {
|
||||||
scope.close();
|
scope.close();
|
||||||
}
|
}
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void closeAsyncSpan(T future) {
|
protected void closeAsyncSpan(final T future) {
|
||||||
Span span = scope.span();
|
final Span span = scope.span();
|
||||||
try {
|
try {
|
||||||
processResult(span, future);
|
processResult(span, future);
|
||||||
} catch (CancellationException e) {
|
} catch (final CancellationException e) {
|
||||||
span.setTag(DB_COMMAND_CANCELLED, true);
|
span.setTag(DB_COMMAND_CANCELLED, true);
|
||||||
} catch (ExecutionException e) {
|
} catch (final ExecutionException e) {
|
||||||
if (e.getCause() instanceof CancellationException) {
|
if (e.getCause() instanceof CancellationException) {
|
||||||
// Looks like underlying OperationFuture wraps CancellationException into ExecutionException
|
// Looks like underlying OperationFuture wraps CancellationException into ExecutionException
|
||||||
span.setTag(DB_COMMAND_CANCELLED, true);
|
span.setTag(DB_COMMAND_CANCELLED, true);
|
||||||
|
@ -72,12 +67,12 @@ public abstract class CompletionListener<T> {
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
Tags.ERROR.set(span, Boolean.TRUE);
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, e.getCause()));
|
span.log(Collections.singletonMap(ERROR_OBJECT, e.getCause()));
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
// Avoid swallowing InterruptedException
|
// Avoid swallowing InterruptedException
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
Tags.ERROR.set(span, Boolean.TRUE);
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, e));
|
span.log(Collections.singletonMap(ERROR_OBJECT, e));
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
// This should never happen, just in case to make sure we cover all unexpected exceptions
|
// This should never happen, just in case to make sure we cover all unexpected exceptions
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
Tags.ERROR.set(span, Boolean.TRUE);
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, e));
|
span.log(Collections.singletonMap(ERROR_OBJECT, e));
|
||||||
|
@ -86,8 +81,8 @@ public abstract class CompletionListener<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void closeSyncSpan(Throwable thrown) {
|
protected void closeSyncSpan(final Throwable thrown) {
|
||||||
Span span = scope.span();
|
final Span span = scope.span();
|
||||||
|
|
||||||
if (thrown != null) {
|
if (thrown != null) {
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
Tags.ERROR.set(span, Boolean.TRUE);
|
||||||
|
@ -101,12 +96,12 @@ public abstract class CompletionListener<T> {
|
||||||
protected abstract void processResult(Span span, T future)
|
protected abstract void processResult(Span span, T future)
|
||||||
throws ExecutionException, InterruptedException;
|
throws ExecutionException, InterruptedException;
|
||||||
|
|
||||||
protected void setResultTag(Span span, boolean hit) {
|
protected void setResultTag(final Span span, final boolean hit) {
|
||||||
span.setTag(MEMCACHED_RESULT, hit ? HIT : MISS);
|
span.setTag(MEMCACHED_RESULT, hit ? HIT : MISS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getOperationName(String methodName) {
|
private static String getOperationName(final String methodName) {
|
||||||
char chars[] =
|
final char[] chars =
|
||||||
methodName
|
methodName
|
||||||
.replaceFirst("^async", "")
|
.replaceFirst("^async", "")
|
||||||
// 'CAS' name is special, we have to lowercase whole name
|
// 'CAS' name is special, we have to lowercase whole name
|
||||||
|
|
|
@ -3,6 +3,7 @@ package datadog.trace.instrumentation.spymemcached
|
||||||
import com.google.common.util.concurrent.MoreExecutors
|
import com.google.common.util.concurrent.MoreExecutors
|
||||||
import datadog.trace.agent.test.AgentTestRunner
|
import datadog.trace.agent.test.AgentTestRunner
|
||||||
import datadog.trace.agent.test.TraceAssert
|
import datadog.trace.agent.test.TraceAssert
|
||||||
|
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 net.spy.memcached.CASResponse
|
import net.spy.memcached.CASResponse
|
||||||
|
@ -25,7 +26,6 @@ import java.util.concurrent.locks.ReentrantLock
|
||||||
import static CompletionListener.COMPONENT_NAME
|
import static CompletionListener.COMPONENT_NAME
|
||||||
import static CompletionListener.OPERATION_NAME
|
import static CompletionListener.OPERATION_NAME
|
||||||
import static CompletionListener.SERVICE_NAME
|
import static CompletionListener.SERVICE_NAME
|
||||||
import static CompletionListener.SPAN_TYPE
|
|
||||||
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
|
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
|
||||||
import static datadog.trace.agent.test.TestUtils.runUnderTrace
|
import static datadog.trace.agent.test.TestUtils.runUnderTrace
|
||||||
import static net.spy.memcached.ConnectionFactoryBuilder.Protocol.BINARY
|
import static net.spy.memcached.ConnectionFactoryBuilder.Protocol.BINARY
|
||||||
|
@ -631,12 +631,12 @@ class SpymemcachedTest extends AgentTestRunner {
|
||||||
serviceName SERVICE_NAME
|
serviceName SERVICE_NAME
|
||||||
operationName OPERATION_NAME
|
operationName OPERATION_NAME
|
||||||
resourceName operation
|
resourceName operation
|
||||||
spanType SPAN_TYPE
|
spanType DDSpanTypes.MEMCACHED
|
||||||
errored(error != null && error != "canceled")
|
errored(error != null && error != "canceled")
|
||||||
|
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" SPAN_TYPE
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MEMCACHED
|
||||||
"${Tags.COMPONENT.key}" COMPONENT_NAME
|
"${Tags.COMPONENT.key}" COMPONENT_NAME
|
||||||
"${Tags.SPAN_KIND.key}" Tags.SPAN_KIND_CLIENT
|
"${Tags.SPAN_KIND.key}" Tags.SPAN_KIND_CLIENT
|
||||||
"${Tags.DB_TYPE.key}" CompletionListener.DB_TYPE
|
"${Tags.DB_TYPE.key}" CompletionListener.DB_TYPE
|
||||||
|
|
Loading…
Reference in New Issue