Instrumentation for redisson 3.17.2 (#6096)
* Instrumentation for redisson 3.17.2 * cross test instrumentation * split at 3.17.0, assert inverse * Apply suggestions from code review Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com> Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
parent
24d3e1a5e8
commit
efd40f8cdf
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.redisson;
|
|
||||||
|
|
||||||
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.db.DbClientAttributesExtractor;
|
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
|
||||||
|
|
||||||
public final class RedissonSingletons {
|
|
||||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.redisson-3.0";
|
|
||||||
|
|
||||||
private static final Instrumenter<RedissonRequest, Void> INSTRUMENTER;
|
|
||||||
|
|
||||||
static {
|
|
||||||
RedissonDbAttributesGetter dbAttributesGetter = new RedissonDbAttributesGetter();
|
|
||||||
RedissonNetAttributesGetter netAttributesGetter = new RedissonNetAttributesGetter();
|
|
||||||
|
|
||||||
INSTRUMENTER =
|
|
||||||
Instrumenter.<RedissonRequest, Void>builder(
|
|
||||||
GlobalOpenTelemetry.get(),
|
|
||||||
INSTRUMENTATION_NAME,
|
|
||||||
DbClientSpanNameExtractor.create(dbAttributesGetter))
|
|
||||||
.addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter))
|
|
||||||
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
|
||||||
.newInstrumenter(SpanKindExtractor.alwaysClient());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Instrumenter<RedissonRequest, Void> instrumenter() {
|
|
||||||
return INSTRUMENTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RedissonSingletons() {}
|
|
||||||
}
|
|
|
@ -6,18 +6,23 @@ muzzle {
|
||||||
pass {
|
pass {
|
||||||
group.set("org.redisson")
|
group.set("org.redisson")
|
||||||
module.set("redisson")
|
module.set("redisson")
|
||||||
versions.set("[3.0.0,3.17.2)")
|
versions.set("[3.0.0,3.17.0)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
library("org.redisson:redisson:3.0.0")
|
library("org.redisson:redisson:3.0.0")
|
||||||
|
|
||||||
// TODO (trask) split out instrumentation into two modules and support 3.17.2+
|
implementation(project(":instrumentation:redisson:redisson-common:javaagent"))
|
||||||
latestDepTestLibrary("org.redisson:redisson:3.17.1")
|
|
||||||
|
|
||||||
compileOnly("com.google.auto.value:auto-value-annotations")
|
compileOnly("com.google.auto.value:auto-value-annotations")
|
||||||
annotationProcessor("com.google.auto.value:auto-value")
|
annotationProcessor("com.google.auto.value:auto-value")
|
||||||
|
|
||||||
|
testInstrumentation(project(":instrumentation:redisson:redisson-3.17:javaagent"))
|
||||||
|
|
||||||
|
testImplementation(project(":instrumentation:redisson:redisson-common:testing"))
|
||||||
|
|
||||||
|
latestDepTestLibrary("org.redisson:redisson:3.16.+")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.redisson;
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_0;
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
|
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
@ -12,6 +12,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.CompletableFutureWrapper;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
|
@ -3,10 +3,10 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.redisson;
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_0;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||||
import static io.opentelemetry.javaagent.instrumentation.redisson.RedissonSingletons.instrumenter;
|
import static io.opentelemetry.javaagent.instrumentation.redisson.v3_0.RedissonSingletons.instrumenter;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
|
@ -14,6 +14,9 @@ import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.EndOperationListener;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.PromiseWrapper;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.RedissonRequest;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
@ -57,7 +60,7 @@ public class RedisConnectionInstrumentation implements TypeInstrumentation {
|
||||||
context = instrumenter().start(parentContext, request);
|
context = instrumenter().start(parentContext, request);
|
||||||
scope = context.makeCurrent();
|
scope = context.makeCurrent();
|
||||||
|
|
||||||
promise.setEndOperationListener(new EndOperationListener<>(context, request));
|
promise.setEndOperationListener(new EndOperationListener<>(instrumenter(), context, request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
@ -3,14 +3,17 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.redisson;
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_0;
|
||||||
|
|
||||||
|
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
@AutoService(InstrumentationModule.class)
|
@AutoService(InstrumentationModule.class)
|
||||||
public class RedissonInstrumentationModule extends InstrumentationModule {
|
public class RedissonInstrumentationModule extends InstrumentationModule {
|
||||||
|
@ -19,6 +22,11 @@ public class RedissonInstrumentationModule extends InstrumentationModule {
|
||||||
super("redisson", "redisson-3.0");
|
super("redisson", "redisson-3.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||||
|
return not(hasClassesNamed("org.redisson.api.RFunction"));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TypeInstrumentation> typeInstrumentations() {
|
public List<TypeInstrumentation> typeInstrumentations() {
|
||||||
return asList(new RedisConnectionInstrumentation(), new RedisCommandDataInstrumentation());
|
return asList(new RedisConnectionInstrumentation(), new RedisCommandDataInstrumentation());
|
|
@ -3,10 +3,12 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.redisson;
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_0;
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.EndOperationListener;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.PromiseWrapper;
|
||||||
import org.redisson.misc.RPromise;
|
import org.redisson.misc.RPromise;
|
||||||
import org.redisson.misc.RedissonPromise;
|
import org.redisson.misc.RedissonPromise;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_0;
|
||||||
|
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.RedissonInstrumenterFactory;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.RedissonRequest;
|
||||||
|
|
||||||
|
public final class RedissonSingletons {
|
||||||
|
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.redisson-3.0";
|
||||||
|
|
||||||
|
private static final Instrumenter<RedissonRequest, Void> INSTRUMENTER =
|
||||||
|
RedissonInstrumenterFactory.createInstrumenter(INSTRUMENTATION_NAME);
|
||||||
|
|
||||||
|
public static Instrumenter<RedissonRequest, Void> instrumenter() {
|
||||||
|
return INSTRUMENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RedissonSingletons() {}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RedissonAsyncClientTest extends AbstractRedissonAsyncClientTest {
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RedissonClientTest extends AbstractRedissonClientTest {
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
plugins {
|
||||||
|
id("otel.javaagent-instrumentation")
|
||||||
|
}
|
||||||
|
|
||||||
|
muzzle {
|
||||||
|
pass {
|
||||||
|
group.set("org.redisson")
|
||||||
|
module.set("redisson")
|
||||||
|
versions.set("[3.17.0,)")
|
||||||
|
assertInverse.set(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
library("org.redisson:redisson:3.17.0")
|
||||||
|
|
||||||
|
implementation(project(":instrumentation:redisson:redisson-common:javaagent"))
|
||||||
|
|
||||||
|
compileOnly("com.google.auto.value:auto-value-annotations")
|
||||||
|
annotationProcessor("com.google.auto.value:auto-value")
|
||||||
|
|
||||||
|
testInstrumentation(project(":instrumentation:redisson:redisson-3.0:javaagent"))
|
||||||
|
|
||||||
|
testImplementation(project(":instrumentation:redisson:redisson-common:testing"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
|
||||||
|
usesService(gradle.sharedServices.registrations["testcontainersBuildService"].getService())
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_17;
|
||||||
|
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.CompletableFutureWrapper;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
|
public class RedisCommandDataInstrumentation implements TypeInstrumentation {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||||
|
return namedOneOf(
|
||||||
|
"org.redisson.client.protocol.CommandData", "org.redisson.client.protocol.CommandsData");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(TypeTransformer transformer) {
|
||||||
|
transformer.applyAdviceToMethod(
|
||||||
|
isConstructor().and(takesArgument(0, CompletableFuture.class)),
|
||||||
|
this.getClass().getName() + "$WrapCompletableFutureAdvice");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class WrapCompletableFutureAdvice {
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static void onEnter(
|
||||||
|
@Advice.Argument(value = 0, readOnly = false) CompletableFuture<?> completableFuture) {
|
||||||
|
completableFuture = CompletableFutureWrapper.wrap(completableFuture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_17;
|
||||||
|
|
||||||
|
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||||
|
import static io.opentelemetry.javaagent.instrumentation.redisson.v3_17.RedissonSingletons.instrumenter;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
|
import io.opentelemetry.context.Context;
|
||||||
|
import io.opentelemetry.context.Scope;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.EndOperationListener;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.PromiseWrapper;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.RedissonRequest;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
import org.redisson.client.RedisConnection;
|
||||||
|
|
||||||
|
public class RedisConnectionInstrumentation implements TypeInstrumentation {
|
||||||
|
@Override
|
||||||
|
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||||
|
return named("org.redisson.client.RedisConnection");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(TypeTransformer transformer) {
|
||||||
|
transformer.applyAdviceToMethod(
|
||||||
|
isMethod().and(named("send")), this.getClass().getName() + "$SendAdvice");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class SendAdvice {
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static void onEnter(
|
||||||
|
@Advice.This RedisConnection connection,
|
||||||
|
@Advice.Argument(0) Object arg,
|
||||||
|
@Advice.Local("otelRequest") RedissonRequest request,
|
||||||
|
@Advice.Local("otelContext") Context context,
|
||||||
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
|
|
||||||
|
Context parentContext = currentContext();
|
||||||
|
InetSocketAddress remoteAddress = (InetSocketAddress) connection.getChannel().remoteAddress();
|
||||||
|
request = RedissonRequest.create(remoteAddress, arg);
|
||||||
|
PromiseWrapper<?> promise = request.getPromiseWrapper();
|
||||||
|
if (promise == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!instrumenter().shouldStart(parentContext, request)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = instrumenter().start(parentContext, request);
|
||||||
|
scope = context.makeCurrent();
|
||||||
|
|
||||||
|
promise.setEndOperationListener(new EndOperationListener<>(instrumenter(), context, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
public static void stopSpan(
|
||||||
|
@Advice.Thrown Throwable throwable,
|
||||||
|
@Advice.Local("otelRequest") RedissonRequest request,
|
||||||
|
@Advice.Local("otelContext") Context context,
|
||||||
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
|
|
||||||
|
if (scope == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scope.close();
|
||||||
|
|
||||||
|
if (throwable != null) {
|
||||||
|
instrumenter().end(context, request, null, throwable);
|
||||||
|
}
|
||||||
|
// span ended in EndOperationListener
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_17;
|
||||||
|
|
||||||
|
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
|
import java.util.List;
|
||||||
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
|
@AutoService(InstrumentationModule.class)
|
||||||
|
public class RedissonInstrumentationModule extends InstrumentationModule {
|
||||||
|
|
||||||
|
public RedissonInstrumentationModule() {
|
||||||
|
super("redisson", "redisson-3.17");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||||
|
return hasClassesNamed("org.redisson.api.RFunction");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TypeInstrumentation> typeInstrumentations() {
|
||||||
|
return asList(new RedisConnectionInstrumentation(), new RedisCommandDataInstrumentation());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.redisson.v3_17;
|
||||||
|
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.RedissonInstrumenterFactory;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.redisson.RedissonRequest;
|
||||||
|
|
||||||
|
public final class RedissonSingletons {
|
||||||
|
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.redisson-3.17";
|
||||||
|
|
||||||
|
private static final Instrumenter<RedissonRequest, Void> INSTRUMENTER =
|
||||||
|
RedissonInstrumenterFactory.createInstrumenter(INSTRUMENTATION_NAME);
|
||||||
|
|
||||||
|
public static Instrumenter<RedissonRequest, Void> instrumenter() {
|
||||||
|
return INSTRUMENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RedissonSingletons() {}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RedissonAsyncClientTest extends AbstractRedissonAsyncClientTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean useRedisProtocol() {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RedissonClientTest extends AbstractRedissonClientTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean useRedisProtocol() {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
plugins {
|
||||||
|
id("otel.javaagent-instrumentation")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly("org.redisson:redisson:3.0.0")
|
||||||
|
|
||||||
|
compileOnly("com.google.auto.value:auto-value-annotations")
|
||||||
|
annotationProcessor("com.google.auto.value:auto-value")
|
||||||
|
}
|
|
@ -5,22 +5,24 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.redisson;
|
package io.opentelemetry.javaagent.instrumentation.redisson;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.redisson.RedissonSingletons.instrumenter;
|
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public final class EndOperationListener<T> implements BiConsumer<T, Throwable> {
|
public final class EndOperationListener<T> implements BiConsumer<T, Throwable> {
|
||||||
|
private final Instrumenter<RedissonRequest, Void> instrumenter;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final RedissonRequest request;
|
private final RedissonRequest request;
|
||||||
|
|
||||||
public EndOperationListener(Context context, RedissonRequest request) {
|
public EndOperationListener(
|
||||||
|
Instrumenter<RedissonRequest, Void> instrumenter, Context context, RedissonRequest request) {
|
||||||
|
this.instrumenter = instrumenter;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(T t, Throwable error) {
|
public void accept(T t, Throwable error) {
|
||||||
instrumenter().end(context, request, null, error);
|
instrumenter.end(context, request, null, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.redisson;
|
||||||
|
|
||||||
|
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.db.DbClientAttributesExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
||||||
|
|
||||||
|
public final class RedissonInstrumenterFactory {
|
||||||
|
|
||||||
|
public static Instrumenter<RedissonRequest, Void> createInstrumenter(String instrumentationName) {
|
||||||
|
RedissonDbAttributesGetter dbAttributesGetter = new RedissonDbAttributesGetter();
|
||||||
|
RedissonNetAttributesGetter netAttributesGetter = new RedissonNetAttributesGetter();
|
||||||
|
|
||||||
|
return Instrumenter.<RedissonRequest, Void>builder(
|
||||||
|
GlobalOpenTelemetry.get(),
|
||||||
|
instrumentationName,
|
||||||
|
DbClientSpanNameExtractor.create(dbAttributesGetter))
|
||||||
|
.addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter))
|
||||||
|
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
||||||
|
.newInstrumenter(SpanKindExtractor.alwaysClient());
|
||||||
|
}
|
||||||
|
|
||||||
|
private RedissonInstrumenterFactory() {}
|
||||||
|
}
|
|
@ -23,7 +23,6 @@ import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.redisson.client.protocol.CommandData;
|
import org.redisson.client.protocol.CommandData;
|
||||||
import org.redisson.client.protocol.CommandsData;
|
import org.redisson.client.protocol.CommandsData;
|
||||||
import org.redisson.misc.RPromise;
|
|
||||||
|
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class RedissonRequest {
|
public abstract class RedissonRequest {
|
||||||
|
@ -138,9 +137,12 @@ public abstract class RedissonRequest {
|
||||||
private static MethodHandle findGetPromiseMethod(Class<?> commandClass) {
|
private static MethodHandle findGetPromiseMethod(Class<?> commandClass) {
|
||||||
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||||
try {
|
try {
|
||||||
|
Class<?> promiseClass =
|
||||||
|
Class.forName(
|
||||||
|
"org.redisson.misc.RPromise", false, RedissonRequest.class.getClassLoader());
|
||||||
// try versions older than 3.16.8
|
// try versions older than 3.16.8
|
||||||
return lookup.findVirtual(commandClass, "getPromise", MethodType.methodType(RPromise.class));
|
return lookup.findVirtual(commandClass, "getPromise", MethodType.methodType(promiseClass));
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||||
// in 3.16.8 CommandsData#getPromise() and CommandData#getPromise() return type was changed in
|
// in 3.16.8 CommandsData#getPromise() and CommandData#getPromise() return type was changed in
|
||||||
// a backwards-incompatible way from RPromise to CompletableFuture
|
// a backwards-incompatible way from RPromise to CompletableFuture
|
||||||
try {
|
try {
|
|
@ -0,0 +1,14 @@
|
||||||
|
plugins {
|
||||||
|
id("otel.java-conventions")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":testing-common"))
|
||||||
|
|
||||||
|
implementation("org.apache.groovy:groovy")
|
||||||
|
implementation("io.opentelemetry:opentelemetry-api")
|
||||||
|
implementation("org.spockframework:spock-core")
|
||||||
|
implementation("org.testcontainers:testcontainers")
|
||||||
|
|
||||||
|
compileOnly("org.redisson:redisson:3.0.0")
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.concurrent.CompletionStage
|
import java.util.concurrent.CompletionStage
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import org.redisson.Redisson
|
import org.redisson.Redisson
|
||||||
import org.redisson.api.RBucket
|
import org.redisson.api.RBucket
|
||||||
import org.redisson.api.RFuture
|
import org.redisson.api.RFuture
|
||||||
|
@ -19,12 +20,10 @@ import org.redisson.config.SingleServerConfig
|
||||||
import org.testcontainers.containers.GenericContainer
|
import org.testcontainers.containers.GenericContainer
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
import static io.opentelemetry.api.trace.SpanKind.CLIENT
|
import static io.opentelemetry.api.trace.SpanKind.CLIENT
|
||||||
import static io.opentelemetry.api.trace.SpanKind.INTERNAL
|
import static io.opentelemetry.api.trace.SpanKind.INTERNAL
|
||||||
|
|
||||||
class RedissonAsyncClientTest extends AgentInstrumentationSpecification {
|
abstract class AbstractRedissonAsyncClientTest extends AgentInstrumentationSpecification {
|
||||||
|
|
||||||
private static GenericContainer redisServer = new GenericContainer<>("redis:6.2.3-alpine").withExposedPorts(6379)
|
private static GenericContainer redisServer = new GenericContainer<>("redis:6.2.3-alpine").withExposedPorts(6379)
|
||||||
@Shared
|
@Shared
|
||||||
|
@ -39,7 +38,7 @@ class RedissonAsyncClientTest extends AgentInstrumentationSpecification {
|
||||||
redisServer.start()
|
redisServer.start()
|
||||||
port = redisServer.getMappedPort(6379)
|
port = redisServer.getMappedPort(6379)
|
||||||
address = "localhost:" + port
|
address = "localhost:" + port
|
||||||
if (Boolean.getBoolean("testLatestDeps")) {
|
if (useRedisProtocol()) {
|
||||||
// Newer versions of redisson require scheme, older versions forbid it
|
// Newer versions of redisson require scheme, older versions forbid it
|
||||||
address = "redis://" + address
|
address = "redis://" + address
|
||||||
}
|
}
|
||||||
|
@ -61,6 +60,10 @@ class RedissonAsyncClientTest extends AgentInstrumentationSpecification {
|
||||||
clearExportedData()
|
clearExportedData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean useRedisProtocol() {
|
||||||
|
return Boolean.getBoolean("testLatestDeps")
|
||||||
|
}
|
||||||
|
|
||||||
def "test future set"() {
|
def "test future set"() {
|
||||||
when:
|
when:
|
||||||
RBucket<String> keyObject = redisson.getBucket("foo")
|
RBucket<String> keyObject = redisson.getBucket("foo")
|
|
@ -24,7 +24,7 @@ import static io.opentelemetry.api.trace.SpanKind.CLIENT
|
||||||
import static java.util.regex.Pattern.compile
|
import static java.util.regex.Pattern.compile
|
||||||
import static java.util.regex.Pattern.quote
|
import static java.util.regex.Pattern.quote
|
||||||
|
|
||||||
class RedissonClientTest extends AgentInstrumentationSpecification {
|
abstract class AbstractRedissonClientTest extends AgentInstrumentationSpecification {
|
||||||
|
|
||||||
private static GenericContainer redisServer = new GenericContainer<>("redis:6.2.3-alpine").withExposedPorts(6379)
|
private static GenericContainer redisServer = new GenericContainer<>("redis:6.2.3-alpine").withExposedPorts(6379)
|
||||||
@Shared
|
@Shared
|
||||||
|
@ -39,7 +39,7 @@ class RedissonClientTest extends AgentInstrumentationSpecification {
|
||||||
redisServer.start()
|
redisServer.start()
|
||||||
port = redisServer.getMappedPort(6379)
|
port = redisServer.getMappedPort(6379)
|
||||||
address = "localhost:" + port
|
address = "localhost:" + port
|
||||||
if (Boolean.getBoolean("testLatestDeps")) {
|
if (useRedisProtocol()) {
|
||||||
// Newer versions of redisson require scheme, older versions forbid it
|
// Newer versions of redisson require scheme, older versions forbid it
|
||||||
address = "redis://" + address
|
address = "redis://" + address
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,10 @@ class RedissonClientTest extends AgentInstrumentationSpecification {
|
||||||
clearExportedData()
|
clearExportedData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean useRedisProtocol() {
|
||||||
|
return Boolean.getBoolean("testLatestDeps")
|
||||||
|
}
|
||||||
|
|
||||||
def "test string command"() {
|
def "test string command"() {
|
||||||
when:
|
when:
|
||||||
RBucket<String> keyObject = redisson.getBucket("foo")
|
RBucket<String> keyObject = redisson.getBucket("foo")
|
|
@ -365,7 +365,10 @@ include(":instrumentation:reactor:reactor-3.1:testing")
|
||||||
include(":instrumentation:reactor:reactor-netty:reactor-netty-0.9:javaagent")
|
include(":instrumentation:reactor:reactor-netty:reactor-netty-0.9:javaagent")
|
||||||
include(":instrumentation:reactor:reactor-netty:reactor-netty-1.0:javaagent")
|
include(":instrumentation:reactor:reactor-netty:reactor-netty-1.0:javaagent")
|
||||||
include(":instrumentation:rediscala-1.8:javaagent")
|
include(":instrumentation:rediscala-1.8:javaagent")
|
||||||
include(":instrumentation:redisson-3.0:javaagent")
|
include(":instrumentation:redisson:redisson-3.0:javaagent")
|
||||||
|
include(":instrumentation:redisson:redisson-3.17:javaagent")
|
||||||
|
include(":instrumentation:redisson:redisson-common:javaagent")
|
||||||
|
include(":instrumentation:redisson:redisson-common:testing")
|
||||||
include(":instrumentation:restlet:restlet-1.0:javaagent")
|
include(":instrumentation:restlet:restlet-1.0:javaagent")
|
||||||
include(":instrumentation:restlet:restlet-1.0:library")
|
include(":instrumentation:restlet:restlet-1.0:library")
|
||||||
include(":instrumentation:restlet:restlet-1.0:testing")
|
include(":instrumentation:restlet:restlet-1.0:testing")
|
||||||
|
|
Loading…
Reference in New Issue