Fix tests for hibernate 7 (#13890)

This commit is contained in:
Lauri Tulmin 2025-05-21 17:27:02 +03:00 committed by GitHub
parent 2addc6e7f7
commit f3690c1be6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1314 additions and 12 deletions

View File

@ -28,24 +28,67 @@ dependencies {
testImplementation("com.sun.xml.bind:jaxb-impl:2.2.11") testImplementation("com.sun.xml.bind:jaxb-impl:2.2.11")
testImplementation("javax.activation:activation:1.1.1") testImplementation("javax.activation:activation:1.1.1")
testImplementation("org.hsqldb:hsqldb:2.0.0") testImplementation("org.hsqldb:hsqldb:2.0.0")
testImplementation("org.springframework.data:spring-data-jpa:3.0.0") testLibrary("org.springframework.data:spring-data-jpa:3.0.0")
} }
otelJava { otelJava {
minJavaVersionSupported.set(JavaVersion.VERSION_11) minJavaVersionSupported.set(JavaVersion.VERSION_11)
} }
val latestDepTest = findProperty("testLatestDeps") as Boolean
testing {
suites {
val hibernate6Test by registering(JvmTestSuite::class) {
dependencies {
implementation("com.h2database:h2:1.4.197")
implementation("org.hsqldb:hsqldb:2.0.0")
if (latestDepTest) {
implementation("org.hibernate:hibernate-core:6.+")
} else {
implementation("org.hibernate:hibernate-core:6.0.0.Final")
}
}
}
val hibernate7Test by registering(JvmTestSuite::class) {
dependencies {
implementation("com.h2database:h2:1.4.197")
implementation("org.hsqldb:hsqldb:2.0.0")
if (latestDepTest) {
implementation("org.hibernate:hibernate-core:7.+")
} else {
implementation("org.hibernate:hibernate-core:7.0.0.Final")
}
}
}
}
}
tasks { tasks {
withType<Test>().configureEach { withType<Test>().configureEach {
// TODO run tests both with and without experimental span attributes // TODO run tests both with and without experimental span attributes
jvmArgs("-Dotel.instrumentation.hibernate.experimental-span-attributes=true") jvmArgs("-Dotel.instrumentation.hibernate.experimental-span-attributes=true")
} }
named("compileHibernate7TestJava", JavaCompile::class).configure {
options.release.set(17)
}
val testJavaVersion =
gradle.startParameter.projectProperties.get("testJavaVersion")?.let(JavaVersion::toVersion)
?: JavaVersion.current()
if (!testJavaVersion.isCompatibleWith(JavaVersion.VERSION_17)) {
named("hibernate7Test", Test::class).configure {
enabled = false
}
}
val testStableSemconv by registering(Test::class) { val testStableSemconv by registering(Test::class) {
jvmArgs("-Dotel.semconv-stability.opt-in=database") jvmArgs("-Dotel.semconv-stability.opt-in=database")
} }
check { check {
dependsOn(testStableSemconv) dependsOn(testStableSemconv)
dependsOn(testing.suites)
} }
} }

View File

@ -0,0 +1,47 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v6_0;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension;
abstract class AbstractHibernateTest {
protected static SessionFactory sessionFactory;
protected static List<Value> prepopulated;
@RegisterExtension
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@BeforeAll
protected static void setup() {
sessionFactory = new Configuration().configure().buildSessionFactory();
// Pre-populate the DB, so delete/update can be tested.
Session writer = sessionFactory.openSession();
writer.beginTransaction();
prepopulated = new ArrayList<>();
for (int i = 0; i < 5; i++) {
prepopulated.add(new Value("Hello :) " + i));
writer.persist(prepopulated.get(i));
}
writer.getTransaction().commit();
writer.close();
}
@AfterAll
protected static void cleanup() {
if (sessionFactory != null) {
sessionFactory.close();
}
}
}

View File

@ -38,7 +38,7 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
public class ProcedureCallTest { class ProcedureCallTest {
protected static SessionFactory sessionFactory; protected static SessionFactory sessionFactory;
protected static List<Value> prepopulated; protected static List<Value> prepopulated;

View File

@ -45,7 +45,7 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
@SuppressWarnings("deprecation") // testing instrumentation of deprecated class @SuppressWarnings("deprecation") // testing instrumentation of deprecated class
public class SessionTest extends AbstractHibernateTest { class SessionTest extends AbstractHibernateTest {
@ParameterizedTest(name = "{index}: {0}") @ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateActionParameters") @MethodSource("provideHibernateActionParameters")
void testHibernateAction(Parameter parameter) { void testHibernateAction(Parameter parameter) {

View File

@ -0,0 +1,47 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v6_0;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.NamedQuery;
@Entity
@Table
@NamedQuery(name = "TestNamedQuery", query = "from Value")
public class Value {
private Long id;
private String name;
public Value() {}
public Value(String name) {
this.name = name;
}
@Id
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String title) {
name = title;
}
}

View File

@ -0,0 +1,29 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Use in-memory DB for testing -->
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
<property name="connection.username">sa</property>
<property name="connection.password"/>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="connection.pool_size">3</property>
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<property name="show_sql">true</property>
<!-- Reset the DB each test -->
<property name="hbm2ddl.auto">create</property>
<!-- Objects -->
<mapping class="io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value"/>
</session-factory>
</hibernate-configuration>

View File

@ -0,0 +1,47 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v7_0;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension;
abstract class AbstractHibernateTest {
protected static SessionFactory sessionFactory;
protected static List<Value> prepopulated;
@RegisterExtension
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@BeforeAll
protected static void setup() {
sessionFactory = new Configuration().configure().buildSessionFactory();
// Pre-populate the DB, so delete/update can be tested.
Session writer = sessionFactory.openSession();
writer.beginTransaction();
prepopulated = new ArrayList<>();
for (int i = 0; i < 5; i++) {
prepopulated.add(new Value("Hello :) " + i));
writer.persist(prepopulated.get(i));
}
writer.getTransaction().commit();
writer.close();
}
@AfterAll
protected static void cleanup() {
if (sessionFactory != null) {
sessionFactory.close();
}
}
}

View File

@ -0,0 +1,193 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v7_0;
import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_CONNECTION_STRING;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_USER;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.sdk.trace.data.StatusData;
import jakarta.persistence.ParameterMode;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.ProcedureParameter;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
class ProcedureCallTest {
protected static SessionFactory sessionFactory;
protected static List<Value> prepopulated;
@RegisterExtension
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@BeforeAll
static void setup() throws SQLException {
sessionFactory =
new Configuration().configure("procedure-call-hibernate.cfg.xml").buildSessionFactory();
// Pre-populate the DB, so delete/update can be tested.
Session writer = sessionFactory.openSession();
writer.beginTransaction();
prepopulated = new ArrayList<>();
for (int i = 0; i < 2; i++) {
prepopulated.add(new Value("Hello :) " + i));
writer.persist(prepopulated.get(i));
}
writer.getTransaction().commit();
writer.close();
// Create a stored procedure.
Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:test", "sa", "1");
Statement stmt = conn.createStatement();
stmt.execute(
"CREATE PROCEDURE TEST_PROC() MODIFIES SQL DATA BEGIN ATOMIC INSERT INTO Value VALUES (420, 'fred'); END");
stmt.close();
conn.close();
}
@AfterAll
static void cleanup() {
if (sessionFactory != null) {
sessionFactory.close();
}
}
@SuppressWarnings("deprecation") // TODO DB_CONNECTION_STRING deprecation
@Test
void testProcedureCall() {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
ProcedureCall call = session.createStoredProcedureCall("TEST_PROC");
call.getOutputs();
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("ProcedureCall.getOutputs TEST_PROC")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
satisfies(
AttributeKey.stringKey("hibernate.session_id"),
val -> val.isInstanceOf(String.class))),
span ->
span.hasName("CALL test.TEST_PROC")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), "hsqldb"),
equalTo(maybeStable(DB_NAME), "test"),
equalTo(DB_USER, emitStableDatabaseSemconv() ? null : "sa"),
equalTo(
DB_CONNECTION_STRING,
emitStableDatabaseSemconv() ? null : "hsqldb:mem:"),
equalTo(maybeStable(DB_STATEMENT), "{call TEST_PROC()}"),
equalTo(maybeStable(DB_OPERATION), "CALL")),
span ->
span.hasName("Transaction.commit")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(
AttributeKey.stringKey("hibernate.session_id"),
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))))));
}
@Test
void testFailingProcedureCall() {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
ProcedureCall call = session.createStoredProcedureCall("TEST_PROC");
ProcedureParameter<Long> parameterRegistration =
call.registerParameter("nonexistent", Long.class, ParameterMode.IN);
call.setParameter(parameterRegistration, 420L);
try {
call.getOutputs();
} catch (RuntimeException e) {
// We expected this.
}
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("ProcedureCall.getOutputs TEST_PROC")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasStatus(StatusData.error())
.hasEventsSatisfyingExactly(
event ->
event
.hasName("exception")
.hasAttributesSatisfyingExactly(
equalTo(
AttributeKey.stringKey("exception.type"),
"org.hibernate.exception.AuthException"),
satisfies(
AttributeKey.stringKey("exception.message"),
val -> val.startsWith("could not prepare statement")),
satisfies(
AttributeKey.stringKey("exception.stacktrace"),
val -> val.isNotNull())))
.hasAttributesSatisfyingExactly(
satisfies(
AttributeKey.stringKey("hibernate.session_id"),
val -> val.isInstanceOf(String.class))),
span ->
span.hasName("Transaction.commit")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(
AttributeKey.stringKey("hibernate.session_id"),
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))))));
}
}

View File

@ -0,0 +1,756 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v7_0;
import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStableDbSystemName;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_CONNECTION_STRING;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SQL_TABLE;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_USER;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Named.named;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.sdk.testing.assertj.SpanDataAssert;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.StatusData;
import jakarta.persistence.Timeout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import org.hibernate.LockMode;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.UnknownEntityTypeException;
import org.hibernate.query.SelectionQuery;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@SuppressWarnings("deprecation") // testing instrumentation of deprecated class
class SessionTest extends AbstractHibernateTest {
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateActionParameters")
void testHibernateAction(Parameter parameter) {
Session session = sessionFactory.openSession();
Value value = session.merge(prepopulated.get(0));
testing.waitForTraces(1);
testing.clearData();
testing.runWithSpan(
"parent",
() -> {
session.beginTransaction();
try {
parameter.sessionMethodTest.accept(session, value);
} catch (RuntimeException e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit();
session.close();
});
assertTraces(parameter, "refresh".equals(parameter.methodName));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateActionWithStatelessSessionParameters")
void testHibernateActionStatelessSession(Parameter parameter) {
testing.runWithSpan(
"parent",
() -> {
StatelessSession session = sessionFactory.openStatelessSession();
session.beginTransaction();
try {
parameter.statelessSessionMethodTest.accept(session, prepopulated.get(0));
} catch (RuntimeException e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit();
session.close();
});
assertTraces(parameter, true);
}
private static void assertTraces(Parameter parameter, boolean hasClientSpan) {
testing.waitAndAssertTraces(
trace -> {
List<Consumer<SpanDataAssert>> assertions = new ArrayList<>();
assertions.add(span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent());
assertions.add(
span ->
assertSessionSpan(
span,
trace.getSpan(0),
"Session." + parameter.methodName + " " + parameter.resource));
if (hasClientSpan) {
assertions.add(span -> assertClientSpan(span, trace.getSpan(1)));
}
assertions.add(
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Transaction.commit",
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))));
trace.hasSpansSatisfyingExactly(assertions);
});
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateReplicateParameters")
void testHibernateReplicate(Parameter parameter) {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
try {
parameter.sessionMethodTest.accept(session, prepopulated.get(0));
} catch (RuntimeException e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
assertSessionSpan(
span,
trace.getSpan(0),
"Session." + parameter.methodName + " " + parameter.resource),
span -> assertClientSpan(span, trace.getSpan(1), "SELECT"),
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Transaction.commit",
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))),
span -> assertClientSpan(span, trace.getSpan(3))));
}
@Test
void testHibernateFailedReplicate() {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
try {
session.replicate(
Long.valueOf(123) /* Not a valid entity */, ReplicationMode.OVERWRITE);
} catch (RuntimeException e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("Session.replicate java.lang.Long")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasStatus(StatusData.error())
.hasException(new UnknownEntityTypeException("java.lang.Long"))
.hasAttributesSatisfyingExactly(
satisfies(
AttributeKey.stringKey("hibernate.session_id"),
val -> val.isInstanceOf(String.class))),
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Transaction.commit",
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")))));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateCommitActionParameters")
void testHibernateCommitAction(Parameter parameter) {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
try {
parameter.sessionMethodTest.accept(session, prepopulated.get(0));
} catch (RuntimeException e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
assertSessionSpan(
span,
trace.getSpan(0),
"Session." + parameter.methodName + " " + parameter.resource),
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Transaction.commit",
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))),
span -> assertClientSpan(span, trace.getSpan(2))));
}
@SuppressWarnings("deprecation") // TODO DB_CONNECTION_STRING deprecation
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideAttachesStateToQueryParameters")
void testAttachesStateToQuery(Parameter parameter) {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
SelectionQuery<?> query = parameter.queryBuildMethod.apply(session);
query.list();
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span -> assertSessionSpan(span, trace.getSpan(0), parameter.resource),
span ->
span.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), maybeStableDbSystemName("h2")),
equalTo(maybeStable(DB_NAME), "db1"),
equalTo(DB_USER, emitStableDatabaseSemconv() ? null : "sa"),
equalTo(
DB_CONNECTION_STRING,
emitStableDatabaseSemconv() ? null : "h2:mem:"),
satisfies(
maybeStable(DB_STATEMENT), val -> val.isInstanceOf(String.class)),
equalTo(maybeStable(DB_OPERATION), "SELECT"),
equalTo(maybeStable(DB_SQL_TABLE), "Value")),
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Transaction.commit",
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")))));
}
@Test
void testHibernateOverlappingSessions() {
AtomicReference<String> sessionId1 = new AtomicReference<>();
AtomicReference<String> sessionId2 = new AtomicReference<>();
AtomicReference<String> sessionId3 = new AtomicReference<>();
testing.runWithSpan(
"overlapping Sessions",
() -> {
Session session1 = sessionFactory.openSession();
session1.beginTransaction();
StatelessSession session2 = sessionFactory.openStatelessSession();
Session session3 = sessionFactory.openSession();
Value value1 = new Value("Value 1");
session1.merge(value1);
session2.insert(new Value("Value 2"));
session3.merge(new Value("Value 3"));
session1.remove(value1);
session2.close();
session1.getTransaction().commit();
session1.close();
session3.close();
});
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("overlapping Sessions"),
span -> {
assertSessionSpan(
span,
trace.getSpan(0),
"Session.merge io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value");
sessionId1.set(
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")));
},
span -> {
assertSessionSpan(
span,
trace.getSpan(0),
"Session.insert io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value");
sessionId2.set(
trace
.getSpan(2)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")));
},
span -> assertClientSpan(span, trace.getSpan(2), "INSERT"),
span -> {
assertSessionSpan(
span,
trace.getSpan(0),
"Session.merge io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value");
sessionId3.set(
trace
.getSpan(4)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")));
},
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Session.remove io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
sessionId1.get()),
span ->
assertSpanWithSessionId(
span, trace.getSpan(0), "Transaction.commit", sessionId1.get()),
span -> assertClientSpan(span, trace.getSpan(6), "INSERT")));
assertNotEquals(sessionId1.get(), sessionId2.get());
assertNotEquals(sessionId2.get(), sessionId3.get());
assertNotEquals(sessionId1.get(), sessionId3.get());
}
private static Stream<Arguments> provideHibernateActionParameters() {
List<BiConsumer<Session, Value>> sessionMethodTests =
Arrays.asList(
(session, val) -> session.lock(val, LockMode.READ),
(session, val) -> session.lock(val, LockMode.READ, Timeout.seconds(1)),
(session, val) -> session.refresh(val),
(session, val) -> session.find(Value.class, val.getId()));
return Stream.of(
Arguments.of(
named(
"lock",
new Parameter(
"lock",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(0),
null))),
Arguments.of(
named(
"lock with options",
new Parameter(
"lock",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(1),
null))),
Arguments.of(
named(
"refresh",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(2),
null))),
Arguments.of(
named(
"find",
new Parameter(
"find",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(3),
null))));
}
private static Stream<Arguments> provideHibernateActionWithStatelessSessionParameters() {
List<BiConsumer<StatelessSession, Value>> statelessSessionMethodTests =
Arrays.asList(
(statelessSession, val) -> statelessSession.refresh(val),
(statelessSession, val) ->
statelessSession.refresh(
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value", val),
(statelessSession, val) ->
statelessSession.get(
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value", val.getId()),
(statelessSession, val) -> statelessSession.get(Value.class, val.getId()),
(statelessSession, val) -> statelessSession.insert(new Value("insert me")),
(statelessSession, val) ->
statelessSession.insert(
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
new Value("insert me")),
(statelessSession, val) -> statelessSession.insert(null, new Value("insert me")),
(statelessSession, val) -> {
val.setName("New name");
statelessSession.update(val);
},
(statelessSession, val) -> {
val.setName("New name");
statelessSession.update(
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value", val);
},
(statelessSession, val) -> {
statelessSession.delete(val);
prepopulated.remove(val);
},
(statelessSession, val) -> {
statelessSession.delete(
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value", val);
prepopulated.remove(val);
});
return Stream.of(
Arguments.of(
named(
"refresh",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(0)))),
Arguments.of(
named(
"refresh with entity name",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(1)))),
Arguments.of(
named(
"get with entity name",
new Parameter(
"get",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(2)))),
Arguments.of(
named(
"get with entity class",
new Parameter(
"get",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(3)))),
Arguments.of(
named(
"insert",
new Parameter(
"insert",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(4)))),
Arguments.of(
named(
"insert with entity name",
new Parameter(
"insert",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(5)))),
Arguments.of(
named(
"insert with null entity name",
new Parameter(
"insert",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(6)))),
Arguments.of(
named(
"update (StatelessSession)",
new Parameter(
"update",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(7)))),
Arguments.of(
named(
"update with entity name (StatelessSession)",
new Parameter(
"update",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(8)))),
Arguments.of(
named(
"delete (Session)",
new Parameter(
"delete",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(9)))),
Arguments.of(
named(
"delete with entity name (Session)",
new Parameter(
"delete",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
null,
statelessSessionMethodTests.get(10)))));
}
private static Stream<Arguments> provideHibernateReplicateParameters() {
List<BiConsumer<Session, Value>> sessionMethodTests =
Arrays.asList(
(session, val) -> {
Value replicated = new Value(val.getName() + " replicated");
replicated.setId(val.getId());
session.replicate(replicated, ReplicationMode.OVERWRITE);
},
(session, val) -> {
Value replicated = new Value(val.getName() + " replicated");
replicated.setId(val.getId());
session.replicate("Value", replicated, ReplicationMode.OVERWRITE);
});
return Stream.of(
Arguments.of(
named(
"replicate",
new Parameter(
"replicate",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(0),
null))),
Arguments.of(
named(
"replicate by entityName",
new Parameter("replicate", "Value", null, sessionMethodTests.get(1), null))));
}
private static Stream<Arguments> provideHibernateCommitActionParameters() {
List<BiConsumer<Session, Value>> sessionMethodTests =
Arrays.asList(
(session, val) -> session.merge(new Value("merge me in")),
(session, val) -> session.merge("Value", new Value("merge me in")),
(session, val) -> session.persist(new Value("merge me in")),
(session, val) -> session.persist("Value", new Value("merge me in")),
(session, val) -> session.persist(null, new Value("merge me in")),
(session, val) -> {
session.remove(val);
prepopulated.remove(val);
});
return Stream.of(
Arguments.of(
named(
"merge",
new Parameter(
"merge",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(0),
null))),
Arguments.of(
named(
"merge with entity name",
new Parameter("merge", "Value", null, sessionMethodTests.get(1), null))),
Arguments.of(
named(
"persist",
new Parameter(
"persist",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(2),
null))),
Arguments.of(
named(
"persist with entity name",
new Parameter("persist", "Value", null, sessionMethodTests.get(3), null))),
Arguments.of(
named(
"persist with null entity name",
new Parameter(
"persist",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(4),
null))),
Arguments.of(
named(
"remove",
new Parameter(
"remove",
"io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
null,
sessionMethodTests.get(5),
null))));
}
private static Stream<Arguments> provideAttachesStateToQueryParameters() {
List<Function<Session, SelectionQuery<?>>> queryBuildMethods =
Arrays.asList(
session -> session.createQuery("from Value"),
session -> session.getNamedQuery("TestNamedQuery"),
session -> session.createNativeQuery("SELECT * FROM Value"),
session -> session.createSelectionQuery("from Value"));
return Stream.of(
Arguments.of(
named(
"createQuery",
new Parameter(
"createQuery",
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
queryBuildMethods.get(0),
null,
null))),
Arguments.of(
named(
"getNamedQuery",
new Parameter(
"getNamedQuery",
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
queryBuildMethods.get(1),
null,
null))),
Arguments.of(
named(
"createNativeQuery",
new Parameter(
"createNativeQuery", "SELECT Value", queryBuildMethods.get(2), null, null))),
Arguments.of(
named(
"createSelectionQuery",
new Parameter(
"createSelectionQuery",
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value",
queryBuildMethods.get(3),
null,
null))));
}
private static class Parameter {
Parameter(
String methodName,
String resource,
Function<Session, SelectionQuery<?>> queryBuildMethod,
BiConsumer<Session, Value> sessionMethodTest,
BiConsumer<StatelessSession, Value> statelessSessionMethodTest) {
this.methodName = methodName;
this.resource = resource;
this.sessionMethodTest = sessionMethodTest;
this.queryBuildMethod = queryBuildMethod;
this.statelessSessionMethodTest = statelessSessionMethodTest;
}
public final String methodName;
public final String resource;
public final Function<Session, SelectionQuery<?>> queryBuildMethod;
public final BiConsumer<Session, Value> sessionMethodTest;
public final BiConsumer<StatelessSession, Value> statelessSessionMethodTest;
}
private static SpanDataAssert assertSessionSpan(
SpanDataAssert span, SpanData parent, String spanName) {
return span.hasName(spanName)
.hasKind(SpanKind.INTERNAL)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
satisfies(
AttributeKey.stringKey("hibernate.session_id"),
val -> val.isInstanceOf(String.class)));
}
private static SpanDataAssert assertSpanWithSessionId(
SpanDataAssert span, SpanData parent, String spanName, String sessionId) {
return span.hasName(spanName)
.hasKind(SpanKind.INTERNAL)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(AttributeKey.stringKey("hibernate.session_id"), sessionId));
}
@SuppressWarnings("deprecation") // TODO DB_CONNECTION_STRING deprecation
private static SpanDataAssert assertClientSpan(SpanDataAssert span, SpanData parent) {
return span.hasKind(SpanKind.CLIENT)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), maybeStableDbSystemName("h2")),
equalTo(maybeStable(DB_NAME), "db1"),
equalTo(DB_USER, emitStableDatabaseSemconv() ? null : "sa"),
equalTo(DB_CONNECTION_STRING, emitStableDatabaseSemconv() ? null : "h2:mem:"),
satisfies(maybeStable(DB_STATEMENT), val -> val.isInstanceOf(String.class)),
satisfies(maybeStable(DB_OPERATION), val -> val.isInstanceOf(String.class)),
equalTo(maybeStable(DB_SQL_TABLE), "Value"));
}
@SuppressWarnings("deprecation") // TODO DB_CONNECTION_STRING deprecation
private static SpanDataAssert assertClientSpan(
SpanDataAssert span, SpanData parent, String verb) {
return span.hasName(verb.concat(" db1.Value"))
.hasKind(SpanKind.CLIENT)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), maybeStableDbSystemName("h2")),
equalTo(maybeStable(DB_NAME), "db1"),
equalTo(DB_USER, emitStableDatabaseSemconv() ? null : "sa"),
equalTo(DB_CONNECTION_STRING, emitStableDatabaseSemconv() ? null : "h2:mem:"),
satisfies(
maybeStable(DB_STATEMENT),
stringAssert -> stringAssert.startsWith(verb.toLowerCase(Locale.ROOT))),
equalTo(maybeStable(DB_OPERATION), verb),
equalTo(maybeStable(DB_SQL_TABLE), "Value"));
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v7_0;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.NamedQuery;
@Entity
@Table
@NamedQuery(name = "TestNamedQuery", query = "from Value")
public class Value {
private Long id;
private String name;
public Value() {}
public Value(String name) {
this.name = name;
}
@Id
@ValueGeneratedId
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String title) {
name = title;
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v7_0;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hibernate.annotations.IdGeneratorType;
@IdGeneratorType(ValueIdGenerator.class)
@Target({FIELD, METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValueGeneratedId {}

View File

@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v7_0;
import java.util.concurrent.atomic.AtomicLong;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
public class ValueIdGenerator extends SequenceStyleGenerator {
private final AtomicLong counter = new AtomicLong();
@Override
public Object generate(SharedSessionContractImplementor session, Object owner) {
return counter.incrementAndGet();
}
}

View File

@ -0,0 +1,29 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Use in-memory DB for testing -->
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
<property name="connection.username">sa</property>
<property name="connection.password"/>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="connection.pool_size">3</property>
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<property name="show_sql">true</property>
<!-- Reset the DB each test -->
<property name="hbm2ddl.auto">create</property>
<!-- Objects -->
<mapping class="io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value"/>
</session-factory>
</hibernate-configuration>

View File

@ -0,0 +1,24 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.archive.autodetection">class,hbm</property>
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password">1</property>
<property name="hibernate.connection.url">jdbc:hsqldb:mem:test</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<!-- Objects -->
<mapping class="io.opentelemetry.javaagent.instrumentation.hibernate.v7_0.Value"/>
</session-factory>
</hibernate-configuration>

View File

@ -64,7 +64,9 @@ public class SessionInstrumentation implements TypeInstrumentation {
"fireLock", "fireLock",
"refresh", "refresh",
"insert", "insert",
"delete")), "delete",
"remove",
"upsert")),
SessionInstrumentation.class.getName() + "$SessionMethodAdvice"); SessionInstrumentation.class.getName() + "$SessionMethodAdvice");
// Handle the non-generic 'get' separately. // Handle the non-generic 'get' separately.
transformer.applyAdviceToMethod( transformer.applyAdviceToMethod(

View File

@ -16,7 +16,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
public abstract class AbstractHibernateTest { abstract class AbstractHibernateTest {
protected static SessionFactory sessionFactory; protected static SessionFactory sessionFactory;
protected static List<Value> prepopulated; protected static List<Value> prepopulated;

View File

@ -34,7 +34,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
public class CriteriaTest extends AbstractHibernateTest { class CriteriaTest extends AbstractHibernateTest {
private static Stream<Arguments> provideParameters() { private static Stream<Arguments> provideParameters() {
List<Consumer<Query<Value>>> interactions = List<Consumer<Query<Value>>> interactions =
Arrays.asList(Query::getResultList, Query::uniqueResult, Query::getSingleResultOrNull); Arrays.asList(Query::getResultList, Query::uniqueResult, Query::getSingleResultOrNull);

View File

@ -43,7 +43,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
public class EntityManagerTest extends AbstractHibernateTest { class EntityManagerTest extends AbstractHibernateTest {
static final EntityManagerFactory entityManagerFactory = static final EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("test-pu"); Persistence.createEntityManagerFactory("test-pu");
@ -258,7 +258,7 @@ public class EntityManagerTest extends AbstractHibernateTest {
named( named(
"remove", "remove",
new Parameter( new Parameter(
"delete", "remove",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value", "io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
true, true,
true, true,

View File

@ -9,9 +9,12 @@ import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.NamedQuery; import org.hibernate.annotations.NamedQuery;
@SuppressWarnings({
"deprecation",
"removal"
}) // GenericGenerator is deprecated for removal in hibernate 7
@Entity @Entity
@Table @Table
@NamedQuery(name = "TestNamedQuery", query = "from Value") @NamedQuery(name = "TestNamedQuery", query = "from Value")
@ -28,7 +31,7 @@ public class Value {
@Id @Id
@GeneratedValue(generator = "increment") @GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment") @org.hibernate.annotations.GenericGenerator(name = "increment", strategy = "increment")
public Long getId() { public Long getId() {
return id; return id;
} }

View File

@ -15,7 +15,7 @@ dependencies {
testInstrumentation(project(":instrumentation:hibernate:hibernate-procedure-call-4.3:javaagent")) testInstrumentation(project(":instrumentation:hibernate:hibernate-procedure-call-4.3:javaagent"))
testImplementation("org.hsqldb:hsqldb:2.0.0") testImplementation("org.hsqldb:hsqldb:2.0.0")
testImplementation("org.springframework.data:spring-data-jpa:3.0.0") testLibrary("org.springframework.data:spring-data-jpa:3.0.0")
springAgent("org.springframework:spring-instrument:6.0.7") springAgent("org.springframework:spring-instrument:6.0.7")
} }

View File

@ -344,7 +344,7 @@ class SpringJpaTest {
stringKey("hibernate.session_id"), stringKey("hibernate.session_id"),
val -> val.isInstanceOf(String.class))), val -> val.isInstanceOf(String.class))),
span -> span ->
span.hasName("Session.delete spring.jpa.Customer") span.hasName("Session.remove spring.jpa.Customer")
.hasKind(INTERNAL) .hasKind(INTERNAL)
.hasParent(trace.getSpan(0)) .hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly( .hasAttributesSatisfyingExactly(