Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add instrumentation for hibernate reactive #9304

Merged
merged 2 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/supported-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ or [contributing](../CONTRIBUTING.md).
These are the supported libraries and frameworks:

| Library/Framework | Auto-instrumented versions | Standalone Library Instrumentation [1] | Semantic Conventions |
| ------------------------------------------------------------------------------------------------------------------------------------------- |-------------------------------| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|---------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [Akka Actors](https://doc.akka.io/docs/akka/current/typed/index.html) | 2.5+ | N/A | Context propagation |
| [Akka HTTP](https://doc.akka.io/docs/akka-http/current/index.html) | 10.0+ | N/A | [HTTP Client Spans], [HTTP Client Metrics], [HTTP Server Spans], [HTTP Server Metrics] |
| [Apache Axis2](https://axis.apache.org/axis2/java/core/) | 1.6+ | N/A | Provides `http.route` [2], Controller Spans [3] |
Expand Down Expand Up @@ -65,6 +65,7 @@ These are the supported libraries and frameworks:
| [Guava ListenableFuture](https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html) | 10.0+ | [opentelemetry-guava-10.0](../instrumentation/guava-10.0/library) | Context propagation |
| [GWT](http://www.gwtproject.org/) | 2.0+ | N/A | [RPC Server Spans] |
| [Hibernate](https://github.com/hibernate/hibernate-orm) | 3.3+ | N/A | none |
| [Hibernate Reactive](https://hibernate.org/reactive) | 1.0+ | N/A | none |
| [HikariCP](https://github.com/brettwooldridge/HikariCP) | 3.0+ | [opentelemetry-hikaricp-3.0](../instrumentation/hikaricp-3.0/library) | [Database Pool Metrics] |
| [HttpURLConnection](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpURLConnection.html) | Java 8+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
| [Hystrix](https://github.com/Netflix/Hystrix) | 1.4+ | N/A | none |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("org.hibernate.reactive")
module.set("hibernate-reactive-core")
versions.set("(,)")
assertInverse.set(true)
}
}

dependencies {
compileOnly("org.hibernate.reactive:hibernate-reactive-core:1.0.0.Final")

testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent"))
testInstrumentation(project(":instrumentation:vertx:vertx-sql-client-4.0:javaagent"))

library("io.vertx:vertx-sql-client:4.4.2")
compileOnly("io.vertx:vertx-codegen:4.4.2")

testLibrary("io.vertx:vertx-pg-client:4.4.2")
testLibrary("io.vertx:vertx-codegen:4.4.2")
}

val latestDepTest = findProperty("testLatestDeps") as Boolean

testing {
suites {
val hibernateReactive1Test by registering(JvmTestSuite::class) {
dependencies {
implementation("org.testcontainers:testcontainers")
if (latestDepTest) {
implementation("org.hibernate.reactive:hibernate-reactive-core:1.+")
implementation("io.vertx:vertx-pg-client:+")
} else {
implementation("org.hibernate.reactive:hibernate-reactive-core:1.0.0.Final")
implementation("io.vertx:vertx-pg-client:4.1.5")
}
}
}

val hibernateReactive2Test by registering(JvmTestSuite::class) {
dependencies {
implementation("org.testcontainers:testcontainers")
if (latestDepTest) {
implementation("org.hibernate.reactive:hibernate-reactive-core:2.+")
implementation("io.vertx:vertx-pg-client:+")
} else {
implementation("org.hibernate.reactive:hibernate-reactive-core:2.0.0.Final")
implementation("io.vertx:vertx-pg-client:4.4.2")
}
}
}
}
}

tasks {
withType<Test>().configureEach {
usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service)
}
named("compileHibernateReactive2TestJava", JavaCompile::class).configure {
options.release.set(11)
}
val testJavaVersion =
gradle.startParameter.projectProperties.get("testJavaVersion")?.let(JavaVersion::toVersion)
?: JavaVersion.current()
if (testJavaVersion.isJava8) {
named("hibernateReactive2Test", Test::class).configure {
enabled = false
}
if (latestDepTest) {
named("hibernateReactive1Test", Test::class).configure {
enabled = false
}
}
}

check {
dependsOn(testing.suites)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
Expand Down Expand Up @@ -98,10 +99,15 @@ void testMutiny() {
() -> {
mutinySessionFactory
.withSession(
session ->
session
.find(Value.class, 1L)
.invoke(value -> testing.runWithSpan("callback", () -> {})))
session -> {
if (!Span.current().getSpanContext().isValid()) {
throw new IllegalStateException("missing parent span");
}

return session
.find(Value.class, 1L)
.invoke(value -> testing.runWithSpan("callback", () -> {}));
})
.await()
.atMost(Duration.ofSeconds(30));
});
Expand All @@ -117,10 +123,15 @@ void testStage() throws Exception {
() ->
stageSessionFactory
.withSession(
session ->
session
.find(Value.class, 1L)
.thenAccept(value -> testing.runWithSpan("callback", () -> {})))
session -> {
if (!Span.current().getSpanContext().isValid()) {
throw new IllegalStateException("missing parent span");
}

return session
.find(Value.class, 1L)
.thenAccept(value -> testing.runWithSpan("callback", () -> {}));
})
.toCompletableFuture())
.get(30, TimeUnit.SECONDS);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
Expand Down Expand Up @@ -98,10 +99,15 @@ void testMutiny() {
() -> {
mutinySessionFactory
.withSession(
session ->
session
.find(Value.class, 1L)
.invoke(value -> testing.runWithSpan("callback", () -> {})))
session -> {
if (!Span.current().getSpanContext().isValid()) {
throw new IllegalStateException("missing parent span");
}

return session
.find(Value.class, 1L)
.invoke(value -> testing.runWithSpan("callback", () -> {}));
})
.await()
.atMost(Duration.ofSeconds(30));
});
Expand All @@ -117,10 +123,15 @@ void testStage() throws Exception {
() ->
stageSessionFactory
.withSession(
session ->
session
.find(Value.class, 1L)
.thenAccept(value -> testing.runWithSpan("callback", () -> {})))
session -> {
if (!Span.current().getSpanContext().isValid()) {
throw new IllegalStateException("missing parent span");
}

return session
.find(Value.class, 1L)
.thenAccept(value -> testing.runWithSpan("callback", () -> {}));
})
.toCompletableFuture())
.get(30, TimeUnit.SECONDS);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v1_0;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.operators.UniOperator;
import io.smallrye.mutiny.subscription.UniSubscriber;
import io.smallrye.mutiny.subscription.UniSubscription;

public final class ContextOperator<T> extends UniOperator<T, T> {
private final Context context;

public ContextOperator(Uni<? extends T> upstream, Context context) {
super(upstream);
this.context = context;
}

public static <T> Uni<T> plug(Uni<T> uni) {
if (uni instanceof ContextOperator) {
return uni;
}
Context parentContext = Context.current();
if (parentContext == Context.root()) {
return uni;
}

return uni.plug(u -> new ContextOperator<>(u, parentContext));
}

@Override
public void subscribe(UniSubscriber<? super T> downstream) {
try (Scope ignore = context.makeCurrent()) {
upstream().subscribe().withSubscriber(new ContextSubscriber<>(downstream, context));
}
}

private static class ContextSubscriber<T> implements UniSubscriber<T> {
private final UniSubscriber<? super T> downstream;
private final Context context;

private ContextSubscriber(UniSubscriber<? super T> downstream, Context context) {
this.downstream = downstream;
this.context = context;
}

@Override
public void onSubscribe(UniSubscription uniSubscription) {
try (Scope ignore = context.makeCurrent()) {
downstream.onSubscribe(uniSubscription);
}
}

@Override
public void onItem(T t) {
try (Scope ignore = context.makeCurrent()) {
downstream.onItem(t);
}
}

@Override
public void onFailure(Throwable throwable) {
try (Scope ignore = context.makeCurrent()) {
downstream.onFailure(throwable);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v1_0;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import java.util.function.Function;

public final class FunctionWrapper<T, R> implements Function<T, R> {
private final Function<T, R> delegate;
private final Context context;

private FunctionWrapper(Function<T, R> delegate, Context context) {
this.delegate = delegate;
this.context = context;
}

public static <T, R> Function<T, R> wrap(Function<T, R> function) {
if (function instanceof FunctionWrapper) {
return function;
}
Context context = Context.current();
if (context == Context.root()) {
return function;
}

return new FunctionWrapper<>(function, context);
}

@Override
public R apply(T t) {
try (Scope ignore = context.makeCurrent()) {
return delegate.apply(t);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v1_0;

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;

@AutoService(InstrumentationModule.class)
public class HibernateReactiveInstrumentationModule extends InstrumentationModule {

public HibernateReactiveInstrumentationModule() {
super("hibernate-reactive", "hibernate-reactive-1.0");
}

@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(
new StageSessionFactoryInstrumentation(), new MutinySessionFactoryInstrumentation());
}
}
Loading
Loading