Convert Spymemcached integration to Instrumenter (#4273)

* Convert Spymemcached integration to Instrumenter

* Update instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedAttributeExtractor.java

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>

* Spotless

* Optimise

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
Nikita Salnikov-Tarnovski 2021-10-04 15:10:39 +03:00 committed by GitHub
parent fbb5f8f5c6
commit 11b2f16820
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 71 deletions

View File

@ -14,6 +14,9 @@ muzzle {
dependencies {
library("net.spy:spymemcached:2.12.0")
compileOnly("com.google.auto.value:auto-value-annotations")
annotationProcessor("com.google.auto.value:auto-value")
testImplementation("com.google.guava:guava")
}

View File

@ -5,7 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.spymemcached;
import static io.opentelemetry.javaagent.instrumentation.spymemcached.MemcacheClientTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.spymemcached.SpymemcachedSingletons.instrumenter;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
@ -26,10 +26,12 @@ public abstract class CompletionListener<T> {
private static final String MISS = "miss";
private final Context context;
private final SpymemcachedRequest request;
protected CompletionListener(
Context parentContext, MemcachedConnection connection, String methodName) {
context = tracer().startSpan(parentContext, connection, methodName);
request = SpymemcachedRequest.create(connection, methodName);
context = instrumenter().start(parentContext, request);
}
protected void closeAsyncSpan(T future) {
@ -48,26 +50,22 @@ public abstract class CompletionListener<T> {
span.setAttribute(DB_COMMAND_CANCELLED, true);
}
} else {
tracer().endExceptionally(context, e);
instrumenter().end(context, request, null, e);
}
} catch (InterruptedException e) {
// Avoid swallowing InterruptedException
tracer().endExceptionally(context, e);
instrumenter().end(context, request, null, e);
Thread.currentThread().interrupt();
} catch (Throwable t) {
// This should never happen, just in case to make sure we cover all unexpected exceptions
tracer().endExceptionally(context, t);
instrumenter().end(context, request, null, t);
} finally {
tracer().end(context);
instrumenter().end(context, request, future, null);
}
}
protected void closeSyncSpan(Throwable thrown) {
if (thrown == null) {
tracer().end(context);
} else {
tracer().endExceptionally(context, thrown);
}
instrumenter().end(context, request, null, thrown);
}
protected abstract void processResult(Span span, T future)

View File

@ -1,60 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.spymemcached;
import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer;
import io.opentelemetry.instrumentation.api.tracer.net.NetPeerAttributes;
import java.net.InetSocketAddress;
import net.spy.memcached.MemcachedConnection;
public class MemcacheClientTracer
extends DatabaseClientTracer<MemcachedConnection, String, String> {
private static final MemcacheClientTracer TRACER = new MemcacheClientTracer();
private MemcacheClientTracer() {
super(NetPeerAttributes.INSTANCE);
}
public static MemcacheClientTracer tracer() {
return TRACER;
}
@Override
protected String sanitizeStatement(String methodName) {
char[] chars =
methodName
.replaceFirst("^async", "")
// 'CAS' name is special, we have to lowercase whole name
.replaceFirst("^CAS", "cas")
.toCharArray();
// Lowercase first letter
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
@Override
protected String dbSystem(MemcachedConnection memcachedConnection) {
return "memcached";
}
@Override
protected InetSocketAddress peerAddress(MemcachedConnection memcachedConnection) {
return null;
}
@Override
protected String dbOperation(
MemcachedConnection connection, String methodName, String operation) {
return operation;
}
@Override
protected String getInstrumentationName() {
return "io.opentelemetry.spymemcached-2.12";
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.spymemcached;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
import org.checkerframework.checker.nullness.qual.Nullable;
public class SpymemcachedAttributeExtractor
extends DbAttributesExtractor<SpymemcachedRequest, Object> {
@Override
protected String system(SpymemcachedRequest spymemcachedRequest) {
return "memcached";
}
@Override
protected @Nullable String user(SpymemcachedRequest spymemcachedRequest) {
return null;
}
@Override
protected @Nullable String name(SpymemcachedRequest spymemcachedRequest) {
return null;
}
@Override
protected @Nullable String connectionString(SpymemcachedRequest spymemcachedRequest) {
return null;
}
@Override
protected @Nullable String statement(SpymemcachedRequest spymemcachedRequest) {
return null;
}
@Override
protected @Nullable String operation(SpymemcachedRequest spymemcachedRequest) {
return spymemcachedRequest.dbOperation();
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.spymemcached;
import com.google.auto.value.AutoValue;
import net.spy.memcached.MemcachedConnection;
@AutoValue
public abstract class SpymemcachedRequest {
public static SpymemcachedRequest create(MemcachedConnection connection, String statement) {
return new AutoValue_SpymemcachedRequest(connection, statement);
}
public abstract MemcachedConnection getConnection();
public abstract String getStatement();
public String dbOperation() {
String statement = getStatement();
if (statement.startsWith("async")) {
statement = statement.substring("async".length());
}
if (statement.startsWith("CAS")) {
// 'CAS' name is special, we have to lowercase whole name
return "cas" + statement.substring("CAS".length());
}
char[] chars = statement.toCharArray();
// Lowercase first letter
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.spymemcached;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbSpanNameExtractor;
public final class SpymemcachedSingletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spymemcached-2.12";
private static final Instrumenter<SpymemcachedRequest, Object> INSTRUMENTER;
static {
DbAttributesExtractor<SpymemcachedRequest, Object> attributesExtractor =
new SpymemcachedAttributeExtractor();
SpanNameExtractor<SpymemcachedRequest> spanName =
DbSpanNameExtractor.create(attributesExtractor);
INSTRUMENTER =
Instrumenter.newBuilder(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanName)
.addAttributesExtractor(attributesExtractor)
.newInstrumenter(SpanKindExtractor.alwaysClient());
}
public static Instrumenter<SpymemcachedRequest, Object> instrumenter() {
return INSTRUMENTER;
}
private SpymemcachedSingletons() {}
}