Merge pull request #725 from DataDog/tyler/couchbase-decorator

Add decorator for couchbase and cassandra instrumentation
This commit is contained in:
Tyler Benson 2019-02-22 11:26:47 -08:00 committed by GitHub
commit 0f55c9f951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 369 additions and 141 deletions

View File

@ -0,0 +1,35 @@
package datadog.trace.agent.decorator;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
public abstract class DatabaseClientDecorator<SESSION> extends ClientDecorator {
protected abstract String dbType();
protected abstract String dbUser(SESSION session);
protected abstract String dbInstance(SESSION session);
@Override
public Span afterStart(final Span span) {
assert span != null;
Tags.DB_TYPE.set(span, dbType());
return super.afterStart(span);
}
public Span onSession(final Span span, final SESSION statement) {
assert span != null;
if (statement != null) {
Tags.DB_USER.set(span, dbUser(statement));
Tags.DB_INSTANCE.set(span, dbInstance(statement));
}
return span;
}
public Span onStatement(final Span span, final String statement) {
assert span != null;
Tags.DB_STATEMENT.set(span, statement);
return span;
}
}

View File

@ -23,6 +23,7 @@ class ClientDecoratorTest extends BaseDecoratorTest {
1 * span.setTag(Tags.SPAN_KIND.key, "client")
1 * span.setTag(DDTags.SPAN_TYPE, decorator.spanType())
1 * span.setTag(DDTags.ANALYTICS_SAMPLE_RATE, 1.0)
_ * span.setTag(_, _) // Want to allow other calls from child implementations.
0 * _
where:

View File

@ -0,0 +1,139 @@
package datadog.trace.agent.decorator
import datadog.trace.api.DDTags
import io.opentracing.Span
import io.opentracing.tag.Tags
class DatabaseClientDecoratorTest extends ClientDecoratorTest {
def span = Mock(Span)
def "test afterStart"() {
setup:
def decorator = newDecorator((String) serviceName)
when:
decorator.afterStart(span)
then:
if (serviceName != null) {
1 * span.setTag(DDTags.SERVICE_NAME, serviceName)
}
1 * span.setTag(Tags.COMPONENT.key, "test-component")
1 * span.setTag(Tags.SPAN_KIND.key, "client")
1 * span.setTag(Tags.DB_TYPE.key, "test-db")
1 * span.setTag(DDTags.SPAN_TYPE, "test-type")
1 * span.setTag(DDTags.ANALYTICS_SAMPLE_RATE, 1.0)
0 * _
where:
serviceName << ["test-service", "other-service", null]
}
def "test onSession"() {
setup:
def decorator = newDecorator()
when:
decorator.onSession(span, session)
then:
if (session) {
1 * span.setTag(Tags.DB_USER.key, session.user)
1 * span.setTag(Tags.DB_INSTANCE.key, session.instance)
}
0 * _
where:
session | _
null | _
[user: "test-user"] | _
[instance: "test-instance"] | _
[user: "test-user", instance: "test-instance"] | _
}
def "test onStatement"() {
setup:
def decorator = newDecorator()
when:
decorator.onStatement(span, statement)
then:
1 * span.setTag(Tags.DB_STATEMENT.key, statement)
0 * _
where:
statement | _
null | _
"" | _
"db-statement" | _
}
def "test assert null span"() {
setup:
def decorator = newDecorator()
when:
decorator.afterStart(null)
then:
thrown(AssertionError)
when:
decorator.onSession(null, null)
then:
thrown(AssertionError)
when:
decorator.onStatement(null, null)
then:
thrown(AssertionError)
}
@Override
def newDecorator(String serviceName = "test-service") {
return new DatabaseClientDecorator<Map>() {
@Override
protected String[] instrumentationNames() {
return ["test1", "test2"]
}
@Override
protected String service() {
return serviceName
}
@Override
protected String component() {
return "test-component"
}
@Override
protected String spanType() {
return "test-type"
}
@Override
protected String dbType() {
return "test-db"
}
@Override
protected String dbUser(Map map) {
return map.user
}
@Override
protected String dbInstance(Map map) {
return map.instance
}
protected boolean traceAnalyticsDefault() {
return true
}
}
}
}

View File

@ -9,7 +9,7 @@ import io.opentracing.Span;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
class AwsSdkClientDecorator extends HttpClientDecorator<Request, Response> {
public class AwsSdkClientDecorator extends HttpClientDecorator<Request, Response> {
public static final AwsSdkClientDecorator INSTANCE = new AwsSdkClientDecorator();
static final String COMPONENT_NAME = "java-aws-sdk";

View File

@ -10,7 +10,7 @@ import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.SdkHttpResponse;
class AwsSdkClientDecorator extends HttpClientDecorator<SdkHttpRequest, SdkHttpResponse> {
public class AwsSdkClientDecorator extends HttpClientDecorator<SdkHttpRequest, SdkHttpResponse> {
public static final AwsSdkClientDecorator INSTANCE = new AwsSdkClientDecorator();
static final String COMPONENT_NAME = "java-aws-sdk";

View File

@ -1,6 +1,5 @@
package datadog.trace.instrumentation.couchbase.client;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -12,12 +11,10 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import com.couchbase.client.java.CouchbaseCluster;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.DDSpanTypes;
import datadog.trace.api.DDTags;
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import io.opentracing.Span;
import io.opentracing.noop.NoopSpan;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Method;
import java.util.Map;
@ -48,6 +45,10 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
packageName + ".CouchbaseClientDecorator",
getClass().getName() + "$TraceSpanStart",
getClass().getName() + "$TraceSpanFinish",
getClass().getName() + "$TraceSpanError",
@ -113,14 +114,12 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
// just replace the no-op span.
spanRef.set(
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(Tags.COMPONENT.getKey(), "couchbase-client")
.withTag(DDTags.SERVICE_NAME, "couchbase")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.COUCHBASE)
.withTag("bucket", bucket)
.start());
CouchbaseClientDecorator.INSTANCE.afterStart(
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.withTag("bucket", bucket)
.start()));
}
}
@ -136,6 +135,7 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
final Span span = spanRef.getAndSet(null);
if (span != null) {
CouchbaseClientDecorator.INSTANCE.beforeFinish(span);
span.finish();
}
}
@ -152,8 +152,8 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
public void call(final Throwable throwable) {
final Span span = spanRef.getAndSet(null);
if (span != null) {
Tags.ERROR.set(span, true);
span.log(singletonMap(ERROR_OBJECT, throwable));
CouchbaseClientDecorator.INSTANCE.onError(span, throwable);
CouchbaseClientDecorator.INSTANCE.beforeFinish(span);
span.finish();
}
}

View File

@ -0,0 +1,43 @@
package datadog.trace.instrumentation.couchbase.client;
import datadog.trace.agent.decorator.DatabaseClientDecorator;
import datadog.trace.api.DDSpanTypes;
class CouchbaseClientDecorator extends DatabaseClientDecorator {
public static final CouchbaseClientDecorator INSTANCE = new CouchbaseClientDecorator();
@Override
protected String[] instrumentationNames() {
return new String[] {"couchbase"};
}
@Override
protected String service() {
return "couchbase";
}
@Override
protected String component() {
return "couchbase-client";
}
@Override
protected String spanType() {
return DDSpanTypes.COUCHBASE;
}
@Override
protected String dbType() {
return "couchbase";
}
@Override
protected String dbUser(final Object o) {
return null;
}
@Override
protected String dbInstance(final Object o) {
return null;
}
}

View File

@ -1,6 +1,5 @@
package datadog.trace.instrumentation.couchbase.client;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -12,12 +11,10 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import com.couchbase.client.java.CouchbaseCluster;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.DDSpanTypes;
import datadog.trace.api.DDTags;
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import io.opentracing.Span;
import io.opentracing.noop.NoopSpan;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Method;
import java.util.Map;
@ -48,6 +45,10 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
packageName + ".CouchbaseClientDecorator",
getClass().getName() + "$TraceSpanStart",
getClass().getName() + "$TraceSpanFinish",
getClass().getName() + "$TraceSpanError",
@ -108,13 +109,11 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
// just replace the no-op span.
spanRef.set(
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(Tags.COMPONENT.getKey(), "couchbase-client")
.withTag(DDTags.SERVICE_NAME, "couchbase")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.COUCHBASE)
.start());
CouchbaseClientDecorator.INSTANCE.afterStart(
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.start()));
}
}
@ -130,6 +129,7 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
final Span span = spanRef.getAndSet(null);
if (span != null) {
CouchbaseClientDecorator.INSTANCE.beforeFinish(span);
span.finish();
}
}
@ -146,8 +146,8 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
public void call(final Throwable throwable) {
final Span span = spanRef.getAndSet(null);
if (span != null) {
Tags.ERROR.set(span, true);
span.log(singletonMap(ERROR_OBJECT, throwable));
CouchbaseClientDecorator.INSTANCE.onError(span, throwable);
CouchbaseClientDecorator.INSTANCE.beforeFinish(span);
span.finish();
}
}

View File

@ -25,6 +25,8 @@ class CouchbaseClientTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
@ -52,6 +54,8 @@ class CouchbaseClientTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bkt.name()
defaultTags()
}
@ -79,6 +83,8 @@ class CouchbaseClientTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bkt.name()
defaultTags()
}
@ -122,6 +128,8 @@ class CouchbaseClientTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bkt.name()
defaultTags()
}

View File

@ -85,6 +85,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -115,6 +117,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -138,6 +142,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -164,6 +170,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -179,6 +187,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -194,6 +204,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -220,6 +232,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}
@ -235,6 +249,8 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" bucketCouchbase.name()
defaultTags()
}

View File

@ -51,6 +51,8 @@ class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" name
defaultTags()
}
@ -66,6 +68,8 @@ class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" name
defaultTags()
}
@ -81,6 +85,8 @@ class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" name
defaultTags()
}
@ -96,6 +102,8 @@ class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
tags {
"$DDTags.SPAN_TYPE" DDSpanTypes.COUCHBASE
"$Tags.COMPONENT.key" "couchbase-client"
"$Tags.DB_TYPE.key" "couchbase"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"bucket" name
defaultTags()
}

View File

@ -0,0 +1,68 @@
package datadog.trace.instrumentation.datastax.cassandra;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
import datadog.trace.agent.decorator.DatabaseClientDecorator;
import datadog.trace.api.DDSpanTypes;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
public class CassandraClientDecorator extends DatabaseClientDecorator<Session> {
public static final CassandraClientDecorator INSTANCE = new CassandraClientDecorator();
@Override
protected String[] instrumentationNames() {
return new String[] {"cassandra"};
}
@Override
protected String service() {
return "cassandra";
}
@Override
protected String component() {
return "java-cassandra";
}
@Override
protected String spanType() {
return DDSpanTypes.CASSANDRA;
}
@Override
protected String dbType() {
return "cassandra";
}
@Override
protected String dbUser(final Session session) {
return null;
}
@Override
protected String dbInstance(final Session session) {
return session.getLoggedKeyspace();
}
public Span onResponse(final Span span, final ResultSet result) {
if (result != null) {
final Host host = result.getExecutionInfo().getQueriedHost();
Tags.PEER_PORT.set(span, host.getSocketAddress().getPort());
Tags.PEER_HOSTNAME.set(span, host.getAddress().getHostName());
final InetAddress inetAddress = host.getSocketAddress().getAddress();
if (inetAddress instanceof Inet4Address) {
final byte[] address = inetAddress.getAddress();
Tags.PEER_HOST_IPV4.set(span, ByteBuffer.wrap(address).getInt());
} else {
Tags.PEER_HOST_IPV6.set(span, inetAddress.getHostAddress());
}
}
return span;
}
}

View File

@ -9,9 +9,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.datastax.driver.core.Session;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Constructor;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -33,9 +31,13 @@ public class CassandraClientInstrumentation extends Instrumenter.Default {
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.instrumentation.datastax.cassandra.TracingSession",
"datadog.trace.instrumentation.datastax.cassandra.TracingSession$1",
"datadog.trace.instrumentation.datastax.cassandra.TracingSession$2"
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
packageName + ".CassandraClientDecorator",
packageName + ".TracingSession",
packageName + ".TracingSession$1",
packageName + ".TracingSession$2",
};
}
@ -62,12 +64,7 @@ public class CassandraClientInstrumentation extends Instrumenter.Default {
if (session.getClass().getName().endsWith("cassandra.TracingSession")) {
return;
}
final Class<?> clazz =
Class.forName("datadog.trace.instrumentation.datastax.cassandra.TracingSession");
final Constructor<?> constructor = clazz.getDeclaredConstructor(Session.class, Tracer.class);
constructor.setAccessible(true);
session = (Session) constructor.newInstance(session, GlobalTracer.get());
session = new TracingSession(session, GlobalTracer.get());
}
}
}

View File

@ -1,28 +1,8 @@
/*
* Copyright 2017-2018 The OpenTracing Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package datadog.trace.instrumentation.datastax.cassandra;
import static io.opentracing.log.Fields.ERROR_KIND;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static io.opentracing.log.Fields.EVENT;
import static io.opentracing.log.Fields.MESSAGE;
import static io.opentracing.log.Fields.STACK;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.CloseFuture;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.RegularStatement;
import com.datastax.driver.core.ResultSet;
@ -32,48 +12,34 @@ import com.datastax.driver.core.Statement;
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import datadog.trace.api.DDSpanTypes;
import datadog.trace.api.DDTags;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.tag.Tags;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** Package private decorator for {@link Session} Instantiated only by TracingCluster */
class TracingSession implements Session {
public class TracingSession implements Session {
static final String COMPONENT_NAME = "java-cassandra";
private final ExecutorService executorService = Executors.newCachedThreadPool();
private final Session session;
private final Tracer tracer;
TracingSession(final Session session, final Tracer tracer) {
public TracingSession(final Session session, final Tracer tracer) {
this.session = session;
this.tracer = tracer;
}
/** {@inheritDoc} */
@Override
public String getLoggedKeyspace() {
return session.getLoggedKeyspace();
}
/** {@inheritDoc} */
@Override
public Session init() {
return new TracingSession(session.init(), tracer);
}
/** {@inheritDoc} */
@Override
public ListenableFuture<Session> initAsync() {
return Futures.transform(
@ -86,7 +52,6 @@ class TracingSession implements Session {
});
}
/** {@inheritDoc} */
@Override
public ResultSet execute(final String query) {
final Span span = buildSpan(query);
@ -99,7 +64,6 @@ class TracingSession implements Session {
}
}
/** {@inheritDoc} */
@Override
public ResultSet execute(final String query, final Object... values) {
final Span span = buildSpan(query);
@ -112,7 +76,6 @@ class TracingSession implements Session {
}
}
/** {@inheritDoc} */
@Override
public ResultSet execute(final String query, final Map<String, Object> values) {
final Span span = buildSpan(query);
@ -125,7 +88,6 @@ class TracingSession implements Session {
}
}
/** {@inheritDoc} */
@Override
public ResultSet execute(final Statement statement) {
final String query = getQuery(statement);
@ -139,7 +101,6 @@ class TracingSession implements Session {
}
}
/** {@inheritDoc} */
@Override
public ResultSetFuture executeAsync(final String query) {
final Span span = buildSpan(query);
@ -149,7 +110,6 @@ class TracingSession implements Session {
return future;
}
/** {@inheritDoc} */
@Override
public ResultSetFuture executeAsync(final String query, final Object... values) {
final Span span = buildSpan(query);
@ -159,7 +119,6 @@ class TracingSession implements Session {
return future;
}
/** {@inheritDoc} */
@Override
public ResultSetFuture executeAsync(final String query, final Map<String, Object> values) {
final Span span = buildSpan(query);
@ -169,7 +128,6 @@ class TracingSession implements Session {
return future;
}
/** {@inheritDoc} */
@Override
public ResultSetFuture executeAsync(final Statement statement) {
final String query = getQuery(statement);
@ -180,37 +138,31 @@ class TracingSession implements Session {
return future;
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepare(final String query) {
return session.prepare(query);
}
/** {@inheritDoc} */
@Override
public PreparedStatement prepare(final RegularStatement statement) {
return session.prepare(statement);
}
/** {@inheritDoc} */
@Override
public ListenableFuture<PreparedStatement> prepareAsync(final String query) {
return session.prepareAsync(query);
}
/** {@inheritDoc} */
@Override
public ListenableFuture<PreparedStatement> prepareAsync(final RegularStatement statement) {
return session.prepareAsync(statement);
}
/** {@inheritDoc} */
@Override
public CloseFuture closeAsync() {
return session.closeAsync();
}
/** {@inheritDoc} */
@Override
public void close() {
session.close();
@ -221,13 +173,11 @@ class TracingSession implements Session {
return session.isClosed();
}
/** {@inheritDoc} */
@Override
public Cluster getCluster() {
return session.getCluster();
}
/** {@inheritDoc} */
@Override
public State getState() {
return session.getState();
@ -258,63 +208,22 @@ class TracingSession implements Session {
}
private Span buildSpan(final String query) {
final Tracer.SpanBuilder spanBuilder =
tracer
.buildSpan("cassandra.execute")
.withTag(Tags.COMPONENT.getKey(), "datastax-cassandra")
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.CASSANDRA);
final Span span = spanBuilder.start();
Tags.COMPONENT.set(span, COMPONENT_NAME);
Tags.DB_STATEMENT.set(span, query);
Tags.DB_TYPE.set(span, "cassandra");
final String keyspace = getLoggedKeyspace();
if (keyspace != null) {
Tags.DB_INSTANCE.set(span, keyspace);
}
final Span span = tracer.buildSpan("cassandra.execute").start();
CassandraClientDecorator.INSTANCE.afterStart(span);
CassandraClientDecorator.INSTANCE.onSession(span, session);
CassandraClientDecorator.INSTANCE.onStatement(span, query);
return span;
}
private static void finishSpan(final Span span, final ResultSet resultSet) {
if (resultSet != null) {
final Host host = resultSet.getExecutionInfo().getQueriedHost();
Tags.PEER_PORT.set(span, host.getSocketAddress().getPort());
Tags.PEER_HOSTNAME.set(span, host.getAddress().getHostName());
final InetAddress inetAddress = host.getSocketAddress().getAddress();
if (inetAddress instanceof Inet4Address) {
final byte[] address = inetAddress.getAddress();
Tags.PEER_HOST_IPV4.set(span, ByteBuffer.wrap(address).getInt());
} else {
Tags.PEER_HOST_IPV6.set(span, inetAddress.getHostAddress());
}
}
CassandraClientDecorator.INSTANCE.onResponse(span, resultSet);
CassandraClientDecorator.INSTANCE.beforeFinish(span);
span.finish();
}
private static void finishSpan(final Span span, final Exception e) {
Tags.ERROR.set(span, Boolean.TRUE);
span.log(errorLogs(e));
CassandraClientDecorator.INSTANCE.onError(span, e);
CassandraClientDecorator.INSTANCE.beforeFinish(span);
span.finish();
}
private static Map<String, Object> errorLogs(final Throwable throwable) {
final Map<String, Object> errorLogs = new HashMap<>(4);
errorLogs.put(EVENT, Tags.ERROR.getKey());
errorLogs.put(ERROR_KIND, throwable.getClass().getName());
errorLogs.put(ERROR_OBJECT, throwable);
errorLogs.put(MESSAGE, throwable.getMessage());
final StringWriter sw = new StringWriter();
throwable.printStackTrace(new PrintWriter(sw));
errorLogs.put(STACK, sw.toString());
return errorLogs;
}
}

View File

@ -13,8 +13,8 @@ public class DBTypeDecorator extends AbstractDecorator {
public DBTypeDecorator() {
super();
this.setMatchingTag(Tags.DB_TYPE.getKey());
this.setReplacementTag(DDTags.SERVICE_NAME);
setMatchingTag(Tags.DB_TYPE.getKey());
setReplacementTag(DDTags.SERVICE_NAME);
}
@Override
@ -22,6 +22,10 @@ public class DBTypeDecorator extends AbstractDecorator {
// Assign service name
if (!super.shouldSetTag(context, tag, value)) {
if ("couchbase".equals(value)) {
// Couchbase instrumentation has different behavior.
return true;
}
// Assign span type to DB
// Special case: Mongo, set to mongodb
if ("mongo".equals(value)) {