convert hibernate 6 tests from groovy to java (#8304)

This commit is contained in:
Nitesh S 2023-05-05 19:40:50 +05:30 committed by GitHub
parent aef70d2f63
commit f7c7004250
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1526 additions and 1141 deletions

View File

@ -1,39 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import org.hibernate.Session
import org.hibernate.SessionFactory
import org.hibernate.cfg.Configuration
import spock.lang.Shared
abstract class AbstractHibernateTest extends AgentInstrumentationSpecification {
@Shared
protected SessionFactory sessionFactory
@Shared
protected List<Value> prepopulated
def setupSpec() {
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.save(prepopulated.get(i))
}
writer.getTransaction().commit()
writer.close()
}
def cleanupSpec() {
if (sessionFactory != null) {
sessionFactory.close()
}
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import jakarta.persistence.criteria.CriteriaBuilder
import jakarta.persistence.criteria.CriteriaQuery
import jakarta.persistence.criteria.Root
import org.hibernate.Session
import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.SpanKind.INTERNAL
class CriteriaTest extends AbstractHibernateTest {
def "test criteria query.#methodName"() {
setup:
runWithSpan("parent") {
Session session = sessionFactory.openSession()
session.beginTransaction()
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder()
CriteriaQuery<Value> createQuery = criteriaBuilder.createQuery(Value)
Root<Value> root = createQuery.from(Value)
createQuery.select(root)
.where(criteriaBuilder.like(root.get("name"), "Hello"))
.orderBy(criteriaBuilder.desc(root.get("name")))
def query= session.createQuery(createQuery)
interaction.call(query)
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 4) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "SELECT Value"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "SELECT db1.Value"
kind CLIENT
childOf span(1)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" ~/^select /
"$SemanticAttributes.DB_OPERATION" "SELECT"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(3) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
where:
methodName | interaction
"getResultList" | { c -> c.getResultList() }
"uniqueResult" | { c -> c.uniqueResult() }
"getSingleResultOrNull" | { c -> c.getSingleResultOrNull() }
}
}

View File

@ -1,233 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import jakarta.persistence.EntityManager
import jakarta.persistence.EntityManagerFactory
import jakarta.persistence.EntityTransaction
import jakarta.persistence.LockModeType
import jakarta.persistence.Persistence
import jakarta.persistence.Query
import spock.lang.Shared
import spock.lang.Unroll
import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.SpanKind.INTERNAL
class EntityManagerTest extends AbstractHibernateTest {
@Shared
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-pu")
@Unroll
def "test hibernate action #testName"() {
setup:
EntityManager entityManager = entityManagerFactory.createEntityManager()
EntityTransaction entityTransaction = entityManager.getTransaction()
entityTransaction.begin()
def entity = prepopulated.get(0)
if (attach) {
entity = runWithSpan("setup") {
entityManager.merge(prepopulated.get(0))
}
ignoreTracesAndClear(1)
}
when:
runWithSpan("parent") {
try {
sessionMethodTest.call(entityManager, entity)
} catch (Exception e) {
// We expected this, we should see the error field set on the span.
}
entityTransaction.commit()
entityManager.close()
}
then:
boolean isPersistTest = "persist" == testName
def sessionId
assertTraces(1) {
trace(0, 4 + (isPersistTest ? 1 : 0)) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name ~/Session.$methodName $resource/
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
def offset = 0
if (isPersistTest) {
// persist test has an extra query for getting id of inserted element
offset = 1
span(2) {
name "SELECT db1.Value"
childOf span(1)
kind CLIENT
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" String
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
}
if (!flushOnCommit) {
span(2 + offset) {
childOf span(1)
kind CLIENT
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" String
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(3 + offset) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
} else {
span(2 + offset) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
span(3 + offset) {
childOf span(2 + offset)
kind CLIENT
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" String
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
}
}
}
where:
testName | methodName | resource | attach | flushOnCommit | sessionMethodTest
"lock" | "lock" | "Value" | true | false | { em, val ->
em.lock(val, LockModeType.PESSIMISTIC_READ)
}
"refresh" | "refresh" | "Value" | true | false | { em, val ->
em.refresh(val)
}
"find" | "(get|find)" | "Value" | false | false | { em, val ->
em.find(Value, val.getId())
}
"persist" | "persist" | "Value" | false | true | { em, val ->
em.persist(new Value("insert me"))
}
"merge" | "merge" | "Value" | true | true | { em, val ->
val.setName("New name")
em.merge(val)
}
"remove" | "delete" | "Value" | true | true | { em, val ->
em.remove(val)
}
}
@Unroll
def "test attaches State to query created via #queryMethodName"() {
setup:
runWithSpan("parent") {
EntityManager entityManager = entityManagerFactory.createEntityManager()
EntityTransaction entityTransaction = entityManager.getTransaction()
entityTransaction.begin()
Query query = queryBuildMethod(entityManager)
query.getResultList()
entityTransaction.commit()
entityManager.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 4) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name resource
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "SELECT db1.Value"
kind CLIENT
childOf span(1)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" "SELECT"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(3) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
where:
queryMethodName | resource | queryBuildMethod
"createQuery" | "SELECT Value" | { em -> em.createQuery("from Value") }
"getNamedQuery" | "SELECT Value" | { em -> em.createNamedQuery("TestNamedQuery") }
"createSQLQuery" | "SELECT Value" | { em -> em.createNativeQuery("SELECT * FROM Value") }
}
}

View File

@ -1,175 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import jakarta.persistence.ParameterMode
import org.hibernate.Session
import org.hibernate.SessionFactory
import org.hibernate.cfg.Configuration
import org.hibernate.exception.SQLGrammarException
import org.hibernate.procedure.ProcedureCall
import spock.lang.Shared
import java.sql.Connection
import java.sql.DriverManager
import java.sql.Statement
import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.SpanKind.INTERNAL
import static io.opentelemetry.api.trace.StatusCode.ERROR
class ProcedureCallTest extends AgentInstrumentationSpecification {
@Shared
protected SessionFactory sessionFactory
@Shared
protected List<Value> prepopulated
def setupSpec() {
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.save(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()
}
def cleanupSpec() {
if (sessionFactory != null) {
sessionFactory.close()
}
}
def "test ProcedureCall"() {
setup:
runWithSpan("parent") {
Session session = sessionFactory.openSession()
session.beginTransaction()
ProcedureCall call = session.createStoredProcedureCall("TEST_PROC")
call.getOutputs()
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 4) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "ProcedureCall.getOutputs TEST_PROC"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "CALL test.TEST_PROC"
kind CLIENT
childOf span(1)
attributes {
"$SemanticAttributes.DB_SYSTEM" "hsqldb"
"$SemanticAttributes.DB_NAME" "test"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_STATEMENT" "{call TEST_PROC()}"
"$SemanticAttributes.DB_CONNECTION_STRING" "hsqldb:mem:"
"$SemanticAttributes.DB_OPERATION" "CALL"
}
}
span(3) {
kind INTERNAL
name "Transaction.commit"
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
}
def "test failing ProcedureCall"() {
setup:
runWithSpan("parent") {
Session session = sessionFactory.openSession()
session.beginTransaction()
ProcedureCall call = session.createStoredProcedureCall("TEST_PROC")
def parameterRegistration = call.registerParameter("nonexistent", Long, ParameterMode.IN)
call.setParameter(parameterRegistration, 420L)
try {
call.getOutputs()
} catch (Exception e) {
// We expected this.
}
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 3) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "ProcedureCall.getOutputs TEST_PROC"
kind INTERNAL
childOf span(0)
status ERROR
errorEvent(SQLGrammarException, ~/could not prepare statement/)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
}
}

View File

@ -1,603 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.hibernate.LockMode
import org.hibernate.LockOptions
import org.hibernate.ReplicationMode
import org.hibernate.Session
import org.hibernate.UnknownEntityTypeException
import spock.lang.Shared
import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.SpanKind.INTERNAL
import static io.opentelemetry.api.trace.StatusCode.ERROR
class SessionTest extends AbstractHibernateTest {
@Shared
private Closure sessionBuilder = { return sessionFactory.openSession() }
@Shared
private Closure statelessSessionBuilder = { return sessionFactory.openStatelessSession() }
def "test hibernate action #testName"() {
setup:
// Test for each implementation of Session.
for (def buildSession : sessionImplementations) {
runWithSpan("parent") {
def session = buildSession()
session.beginTransaction()
try {
sessionMethodTest.call(session, prepopulated.get(0))
} catch (Exception e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit()
session.close()
}
}
expect:
def sessionId
assertTraces(sessionImplementations.size()) {
for (int i = 0; i < sessionImplementations.size(); i++) {
trace(i, 4) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "Session.$methodName $resource"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
childOf span(1)
kind CLIENT
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" String
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(3) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
}
where:
testName | methodName | resource | sessionImplementations | sessionMethodTest
"lock" | "lock" | "Value" | [sessionBuilder] | { sesh, val ->
sesh.lock(val, LockMode.READ)
}
"lock with entity name" | "lock" | "Value" | [sessionBuilder] | { sesh, val ->
sesh.lock("Value", val, LockMode.READ)
}
"lock with null name" | "lock" | "Value" | [sessionBuilder] | { sesh, val ->
sesh.lock(null, val, LockMode.READ)
}
"buildLockRequest" | "lock" | "Value" | [sessionBuilder] | { sesh, val ->
sesh.buildLockRequest(LockOptions.READ)
.lock(val)
}
"refresh" | "refresh" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val ->
sesh.refresh(val)
}
"refresh with entity name" | "refresh" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val ->
sesh.refresh("Value", val)
}
"get with entity name" | "get" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val ->
sesh.get("Value", val.getId())
}
"get with entity class" | "get" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val ->
sesh.get(Value, val.getId())
}
"insert" | "insert" | "Value" | [statelessSessionBuilder] | { sesh, val ->
sesh.insert(new Value("insert me"))
}
"insert with entity name" | "insert" | "Value" | [statelessSessionBuilder] | { sesh, val ->
sesh.insert("Value", new Value("insert me"))
}
"insert with null entity name" | "insert" | "Value" | [statelessSessionBuilder] | { sesh, val ->
sesh.insert(null, new Value("insert me"))
}
"update (StatelessSession)" | "update" | "Value" | [statelessSessionBuilder] | { sesh, val ->
val.setName("New name")
sesh.update(val)
}
"update with entity name (StatelessSession)" | "update" | "Value" | [statelessSessionBuilder] | { sesh, val ->
val.setName("New name")
sesh.update("Value", val)
}
"delete (Session)" | "delete" | "Value" | [statelessSessionBuilder] | { sesh, val ->
sesh.delete(val)
prepopulated.remove(val)
}
"delete with entity name (Session)" | "delete" | "Value" | [statelessSessionBuilder] | { sesh, val ->
sesh.delete("Value", val)
prepopulated.remove(val)
}
}
def "test hibernate replicate: #testName"() {
setup:
// Test for each implementation of Session.
runWithSpan("parent") {
def session = sessionFactory.openSession()
session.beginTransaction()
try {
sessionMethodTest.call(session, prepopulated.get(0))
} catch (Exception e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 5) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "Session.$methodName $resource"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "SELECT db1.Value"
kind CLIENT
childOf span(1)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" ~/^select /
"$SemanticAttributes.DB_OPERATION" "SELECT"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(3) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
span(4) {
kind CLIENT
childOf span(3)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" String
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
}
}
where:
testName | methodName | resource | sessionMethodTest
"replicate" | "replicate" | "Value" | { sesh, val ->
Value replicated = new Value(val.getName() + " replicated")
replicated.setId(val.getId())
sesh.replicate(replicated, ReplicationMode.OVERWRITE)
}
"replicate by entityName" | "replicate" | "Value" | { sesh, val ->
Value replicated = new Value(val.getName() + " replicated")
replicated.setId(val.getId())
sesh.replicate("Value", replicated, ReplicationMode.OVERWRITE)
}
}
def "test hibernate failed replicate"() {
setup:
// Test for each implementation of Session.
runWithSpan("parent") {
def session = sessionFactory.openSession()
session.beginTransaction()
try {
session.replicate(new Long(123) /* Not a valid entity */, ReplicationMode.OVERWRITE)
} catch (Exception e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 3) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "Session.replicate java.lang.Long"
kind INTERNAL
childOf span(0)
status ERROR
errorEvent(UnknownEntityTypeException, "Unable to locate persister: java.lang.Long")
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
}
def "test hibernate commit action #testName"() {
setup:
runWithSpan("parent") {
def session = sessionBuilder()
session.beginTransaction()
try {
sessionMethodTest.call(session, prepopulated.get(0))
} catch (Exception e) {
// We expected this, we should see the error field set on the span.
}
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 4) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name "Session.$methodName $resource"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
span(3) {
kind CLIENT
childOf span(2)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" String
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
}
}
where:
testName | methodName | resource | sessionMethodTest
"save" | "save" | "Value" | { sesh, val ->
sesh.save(new Value("Another value"))
}
"save with entity name" | "save" | "Value" | { sesh, val ->
sesh.save("Value", new Value("Another value"))
}
"saveOrUpdate save" | "saveOrUpdate" | "Value" | { sesh, val ->
sesh.saveOrUpdate(new Value("Value"))
}
"saveOrUpdate save with entity name" | "saveOrUpdate" | "Value" | { sesh, val ->
sesh.saveOrUpdate("Value", new Value("Value"))
}
"saveOrUpdate update with entity name" | "saveOrUpdate" | "Value" | { sesh, val ->
val.setName("New name")
sesh.saveOrUpdate("Value", val)
}
"merge" | "merge" | "Value" | { sesh, val ->
sesh.merge(new Value("merge me in"))
}
"merge with entity name" | "merge" | "Value" | { sesh, val ->
sesh.merge("Value", new Value("merge me in"))
}
"persist" | "persist" | "Value" | { sesh, val ->
sesh.persist(new Value("merge me in"))
}
"persist with entity name" | "persist" | "Value" | { sesh, val ->
sesh.persist("Value", new Value("merge me in"))
}
"persist with null entity name" | "persist" | "Value" | { sesh, val ->
sesh.persist(null, new Value("merge me in"))
}
"update (Session)" | "update" | "Value" | { sesh, val ->
val.setName("New name")
sesh.update(val)
}
"update by entityName (Session)" | "update" | "Value" | { sesh, val ->
val.setName("New name")
sesh.update("Value", val)
}
"delete (Session)" | "delete" | "Value" | { sesh, val ->
sesh.delete(val)
prepopulated.remove(val)
}
"delete by entityName (Session)" | "delete" | "Value" | { sesh, val ->
sesh.delete("Value", val)
prepopulated.remove(val)
}
}
def "test attaches State to query created via #queryMethodName"() {
setup:
runWithSpan("parent") {
Session session = sessionFactory.openSession()
session.beginTransaction()
def query = queryBuildMethod(session)
query.list()
session.getTransaction().commit()
session.close()
}
expect:
def sessionId
assertTraces(1) {
trace(0, 4) {
span(0) {
name "parent"
kind INTERNAL
hasNoParent()
attributes {
}
}
span(1) {
name resource
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId = it
it instanceof String
}
}
}
span(2) {
kind CLIENT
childOf span(1)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" String
"$SemanticAttributes.DB_OPERATION" "SELECT"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(3) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId
}
}
}
}
where:
queryMethodName | resource | queryBuildMethod
"createQuery" | "SELECT Value" | { sess -> sess.createQuery("from Value") }
"getNamedQuery" | "SELECT Value" | { sess -> sess.getNamedQuery("TestNamedQuery") }
"createNativeQuery" | "SELECT Value" | { sess -> sess.createNativeQuery("SELECT * FROM Value") }
"createSelectionQuery" | "SELECT Value" | { sess -> sess.createSelectionQuery("from Value") }
}
def "test hibernate overlapping Sessions"() {
setup:
runWithSpan("overlapping Sessions") {
def session1 = sessionFactory.openSession()
session1.beginTransaction()
def session2 = sessionFactory.openStatelessSession()
def session3 = sessionFactory.openSession()
def value1 = new Value("Value 1")
session1.save(value1)
session2.insert(new Value("Value 2"))
session3.save(new Value("Value 3"))
session1.delete(value1)
session2.close()
session1.getTransaction().commit()
session1.close()
session3.close()
}
expect:
def sessionId1
def sessionId2
def sessionId3
assertTraces(1) {
trace(0, 9) {
span(0) {
name "overlapping Sessions"
attributes {
}
}
span(1) {
name "Session.save Value"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId1 = it
it instanceof String
}
}
}
span(2) {
name "Session.insert Value"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId2 = it
it instanceof String
}
}
}
span(3) {
name "INSERT db1.Value"
kind CLIENT
childOf span(2)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" ~/^insert /
"$SemanticAttributes.DB_OPERATION" "INSERT"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(4) {
name "Session.save Value"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" {
sessionId3 = it
it instanceof String
}
}
}
span(5) {
name "Session.delete Value"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId1
}
}
span(6) {
name "Transaction.commit"
kind INTERNAL
childOf span(0)
attributes {
"hibernate.session_id" sessionId1
}
}
span(7) {
name "INSERT db1.Value"
kind CLIENT
childOf span(6)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" ~/^insert /
"$SemanticAttributes.DB_OPERATION" "INSERT"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
span(8) {
name "DELETE db1.Value"
kind CLIENT
childOf span(6)
attributes {
"$SemanticAttributes.DB_SYSTEM" "h2"
"$SemanticAttributes.DB_NAME" "db1"
"$SemanticAttributes.DB_USER" "sa"
"$SemanticAttributes.DB_CONNECTION_STRING" "h2:mem:"
"$SemanticAttributes.DB_STATEMENT" ~/^delete /
"$SemanticAttributes.DB_OPERATION" "DELETE"
"$SemanticAttributes.DB_SQL_TABLE" "Value"
}
}
}
}
sessionId1 != sessionId2 != sessionId3
}
}

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;
public 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<Value>();
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,101 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v6_0;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static org.junit.jupiter.api.Named.named;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class CriteriaTest extends AbstractHibernateTest {
private static Stream<Arguments> provideParameters() {
List<Consumer<Query<Value>>> interactions =
Arrays.asList(Query::getResultList, Query::uniqueResult, Query::getSingleResultOrNull);
return Stream.of(
Arguments.of(named("getResultList", interactions.get(0))),
Arguments.of(named("uniqueResult", interactions.get(1))),
Arguments.of(named("getSingleResultOrNull", interactions.get(2))));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideParameters")
void testCriteriaQuery(Consumer<Query<Value>> interaction) {
testing.runWithSpan(
"parent",
() -> {
Session session = sessionFactory.openSession();
session.beginTransaction();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Value> createQuery = criteriaBuilder.createQuery(Value.class);
Root<Value> root = createQuery.from(Value.class);
createQuery
.select(root)
.where(criteriaBuilder.like(root.get("name"), "Hello"))
.orderBy(criteriaBuilder.desc(root.get("name")));
Query<Value> query = session.createQuery(createQuery);
interaction.accept(query);
session.getTransaction().commit();
session.close();
});
testing.waitAndAssertTraces(
trace ->
trace
.hasSize(4)
.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName(
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
satisfies(
AttributeKey.stringKey("hibernate.session_id"),
val -> val.isInstanceOf(String.class))),
span ->
span.hasName("SELECT db1.Value")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly(
equalTo(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(
SemanticAttributes.DB_STATEMENT,
stringAssert -> stringAssert.startsWith("select")),
equalTo(SemanticAttributes.DB_OPERATION, "SELECT"),
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
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,339 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v6_0;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
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.semconv.trace.attributes.SemanticAttributes;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.LockModeType;
import jakarta.persistence.Persistence;
import jakarta.persistence.Query;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class EntityManagerTest extends AbstractHibernateTest {
static final EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("test-pu");
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateActionParameters")
void testHibernateAction(Parameter parameter) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
Value entity;
if (parameter.attach) {
entity =
testing.runWithSpan(
"setup",
() -> {
return entityManager.merge(prepopulated.get(0));
});
testing.clearData();
} else {
entity = prepopulated.get(0);
}
testing.runWithSpan(
"parent",
() -> {
try {
parameter.sessionMethodTest.accept(entityManager, entity);
} catch (RuntimeException e) {
// We expected this, we should see the error field set on the span.
}
entityTransaction.commit();
entityManager.close();
});
boolean isPersistTest = "persist".equals(parameter.methodName);
testing.waitAndAssertTraces(
trace -> {
if (isPersistTest) {
trace.hasSpansSatisfyingExactlyInAnyOrder(
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 db1.Value"),
span ->
assertClientSpan(
span, !parameter.flushOnCommit ? trace.getSpan(1) : trace.getSpan(3)),
span ->
assertTransactionCommitSpan(
span,
trace.getSpan(0),
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))));
} else {
trace.hasSpansSatisfyingExactlyInAnyOrder(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
assertSessionSpan(
span,
trace.getSpan(0),
"Session." + parameter.methodName + " " + parameter.resource),
span ->
assertClientSpan(
span, !parameter.flushOnCommit ? trace.getSpan(1) : trace.getSpan(2)),
span ->
assertTransactionCommitSpan(
span,
trace.getSpan(0),
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id"))));
}
});
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideAttachesStateParameters")
void testAttachesStateToQuery(Parameter parameter) {
testing.runWithSpan(
"parent",
() -> {
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
Query query = parameter.queryBuildMethod.apply(entityManager);
query.getResultList();
entityTransaction.commit();
entityManager.close();
});
testing.waitAndAssertTraces(
trace ->
trace
.hasSize(4)
.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span -> assertSessionSpan(span, trace.getSpan(0), parameter.resource),
span ->
span.hasName("SELECT db1.Value")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly(
equalTo(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(
SemanticAttributes.DB_STATEMENT,
val -> val.isInstanceOf(String.class)),
equalTo(SemanticAttributes.DB_OPERATION, "SELECT"),
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
span ->
assertTransactionCommitSpan(
span,
trace.getSpan(0),
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")))));
}
private static Stream<Arguments> provideHibernateActionParameters() {
List<BiConsumer<EntityManager, Value>> sessionMethodTests =
Arrays.asList(
(em, val) -> em.lock(val, LockModeType.PESSIMISTIC_READ),
(em, val) -> em.refresh(val),
(em, val) -> em.find(Value.class, val.getId()),
(em, val) -> em.persist(new Value("insert me")),
(em, val) -> {
val.setName("New name");
em.merge(val);
},
(em, val) -> em.remove(val));
return Stream.of(
Arguments.of(
named(
"lock",
new Parameter(
"lock",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
true,
false,
sessionMethodTests.get(0)))),
Arguments.of(
named(
"refresh",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
true,
false,
sessionMethodTests.get(1)))),
Arguments.of(
named(
"find",
new Parameter(
"find",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
false,
false,
sessionMethodTests.get(2)))),
Arguments.of(
named(
"persist",
new Parameter(
"persist",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
false,
true,
sessionMethodTests.get(3)))),
Arguments.of(
named(
"merge",
new Parameter(
"merge",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
true,
true,
sessionMethodTests.get(4)))),
Arguments.of(
named(
"remove",
new Parameter(
"delete",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
true,
true,
sessionMethodTests.get(5)))));
}
private static Stream<Arguments> provideAttachesStateParameters() {
List<Function<EntityManager, Query>> queryBuildMethods =
Arrays.asList(
em -> em.createQuery("from Value"),
em -> em.createNamedQuery("TestNamedQuery"),
em -> em.createNativeQuery("SELECT * FROM Value"));
return Stream.of(
Arguments.of(
named(
"createQuery",
new Parameter(
"createQuery",
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
queryBuildMethods.get(0)))),
Arguments.of(
named(
"getNamedQuery",
new Parameter(
"getNamedQuery",
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
queryBuildMethods.get(1)))),
Arguments.of(
named(
"createSQLQuery",
new Parameter("createSQLQuery", "SELECT Value", queryBuildMethods.get(2)))));
}
private static class Parameter {
Parameter(String methodName, String resource, Function<EntityManager, Query> queryBuildMethod) {
this.methodName = methodName;
this.resource = resource;
this.attach = false;
this.flushOnCommit = false;
this.sessionMethodTest = null;
this.queryBuildMethod = queryBuildMethod;
}
Parameter(
String methodName,
String resource,
boolean attach,
boolean flushOnCommit,
BiConsumer<EntityManager, Value> sessionMethodTest) {
this.methodName = methodName;
this.resource = resource;
this.attach = attach;
this.flushOnCommit = flushOnCommit;
this.sessionMethodTest = sessionMethodTest;
this.queryBuildMethod = null;
}
public final String methodName;
public final String resource;
public final boolean attach;
public final boolean flushOnCommit;
public final BiConsumer<EntityManager, Value> sessionMethodTest;
public final Function<EntityManager, Query> queryBuildMethod;
}
private static SpanDataAssert assertClientSpan(SpanDataAssert span, SpanData parent) {
return span.hasKind(SpanKind.CLIENT)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(SemanticAttributes.DB_STATEMENT, val -> val.isInstanceOf(String.class)),
satisfies(SemanticAttributes.DB_OPERATION, val -> val.isInstanceOf(String.class)),
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value"));
}
private static SpanDataAssert assertClientSpan(
SpanDataAssert span, SpanData parent, String spanName) {
return span.hasName(spanName)
.hasKind(SpanKind.CLIENT)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(SemanticAttributes.DB_STATEMENT, val -> val.isInstanceOf(String.class)),
satisfies(SemanticAttributes.DB_OPERATION, val -> val.isInstanceOf(String.class)),
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value"));
}
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 assertTransactionCommitSpan(
SpanDataAssert span, SpanData parent, String sessionId) {
return span.hasName("Transaction.commit")
.hasKind(SpanKind.INTERNAL)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(AttributeKey.stringKey("hibernate.session_id"), sessionId));
}
}

View File

@ -0,0 +1,188 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v6_0;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
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 io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
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.query.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;
public 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();
}
}
@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
.hasSize(4)
.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(SemanticAttributes.DB_SYSTEM, "hsqldb"),
equalTo(SemanticAttributes.DB_NAME, "test"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "hsqldb:mem:"),
equalTo(SemanticAttributes.DB_STATEMENT, "{call TEST_PROC()}"),
equalTo(SemanticAttributes.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
.hasSize(3)
.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.SQLGrammarException"),
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,845 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.hibernate.v6_0;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
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 io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Stream;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
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
public class SessionTest extends AbstractHibernateTest {
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("provideHibernateActionParameters")
void testHibernateAction(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();
});
assertTraces(parameter);
}
@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);
}
private static void assertTraces(Parameter parameter) {
testing.waitAndAssertTraces(
trace ->
trace
.hasSize(4)
.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)),
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Transaction.commit",
trace
.getSpan(1)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")))));
}
@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
.hasSize(5)
.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
.hasSize(3)
.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(
"Unable to locate persister: 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
.hasSize(4)
.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))));
}
@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
.hasSize(4)
.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(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(
SemanticAttributes.DB_STATEMENT,
val -> val.isInstanceOf(String.class)),
equalTo(SemanticAttributes.DB_OPERATION, "SELECT"),
equalTo(SemanticAttributes.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.save(value1);
session2.insert(new Value("Value 2"));
session3.save(new Value("Value 3"));
session1.delete(value1);
session2.close();
session1.getTransaction().commit();
session1.close();
session3.close();
});
testing.waitAndAssertTraces(
trace ->
trace
.hasSize(9)
.hasSpansSatisfyingExactly(
span -> span.hasName("overlapping Sessions"),
span -> {
assertSessionSpan(
span,
trace.getSpan(0),
"Session.save io.opentelemetry.javaagent.instrumentation.hibernate.v6_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.v6_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.save io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value");
sessionId3.set(
trace
.getSpan(4)
.getAttributes()
.get(AttributeKey.stringKey("hibernate.session_id")));
},
span ->
assertSpanWithSessionId(
span,
trace.getSpan(0),
"Session.delete io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
sessionId1.get()),
span ->
assertSpanWithSessionId(
span, trace.getSpan(0), "Transaction.commit", sessionId1.get()),
span -> assertClientSpan(span, trace.getSpan(6), "INSERT"),
span -> assertClientSpan(span, trace.getSpan(6), "DELETE")));
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("Value", val, LockMode.READ),
(session, val) -> session.lock(null, val, LockMode.READ),
(session, val) -> session.buildLockRequest(LockOptions.READ).lock(val),
(session, val) -> session.refresh(val),
(session, val) -> session.refresh("Value", val),
(session, val) ->
session.get(
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value", val.getId()),
(session, val) -> session.get(Value.class, val.getId()));
return Stream.of(
Arguments.of(
named(
"lock",
new Parameter(
"lock",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(0),
null))),
Arguments.of(
named(
"lock with entity name",
new Parameter("lock", "Value", null, sessionMethodTests.get(1), null))),
Arguments.of(
named(
"lock with null name",
new Parameter(
"lock",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(2),
null))),
Arguments.of(
named(
"buildLockRequest",
new Parameter(
"lock",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(3),
null))),
Arguments.of(
named(
"refresh",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(4),
null))),
Arguments.of(
named(
"refresh with entity name",
new Parameter("refresh", "Value", null, sessionMethodTests.get(5), null))),
Arguments.of(
named(
"get with entity name",
new Parameter(
"get",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(6),
null))),
Arguments.of(
named(
"get with entity class",
new Parameter(
"get",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(7),
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.v6_0.Value", val),
(statelessSession, val) ->
statelessSession.get(
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_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.v6_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.v6_0.Value", val);
},
(statelessSession, val) -> {
statelessSession.delete(val);
prepopulated.remove(val);
},
(statelessSession, val) -> {
statelessSession.delete(
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value", val);
prepopulated.remove(val);
});
return Stream.of(
Arguments.of(
named(
"refresh",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(0)))),
Arguments.of(
named(
"refresh with entity name",
new Parameter(
"refresh",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(1)))),
Arguments.of(
named(
"get with entity name",
new Parameter(
"get",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(2)))),
Arguments.of(
named(
"get with entity class",
new Parameter(
"get",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(3)))),
Arguments.of(
named(
"insert",
new Parameter(
"insert",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(4)))),
Arguments.of(
named(
"insert with entity name",
new Parameter(
"insert",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(5)))),
Arguments.of(
named(
"insert with null entity name",
new Parameter(
"insert",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(6)))),
Arguments.of(
named(
"update (StatelessSession)",
new Parameter(
"update",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(7)))),
Arguments.of(
named(
"update with entity name (StatelessSession)",
new Parameter(
"update",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(8)))),
Arguments.of(
named(
"delete (Session)",
new Parameter(
"delete",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
null,
statelessSessionMethodTests.get(9)))),
Arguments.of(
named(
"delete with entity name (Session)",
new Parameter(
"delete",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_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.v6_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.save(new Value("Another value")),
(session, val) -> session.save("Value", new Value("Another value")),
(session, val) -> session.saveOrUpdate(new Value("Value")),
(session, val) -> session.saveOrUpdate("Value", new Value("Value")),
(session, val) -> {
val.setName("New name");
session.saveOrUpdate("Value", val);
},
(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) -> {
val.setName("New name");
session.update(val);
},
(session, val) -> {
val.setName("New name");
session.update("Value", val);
},
(session, val) -> {
session.delete(val);
prepopulated.remove(val);
},
(session, val) -> {
session.delete("Value", val);
prepopulated.remove(val);
});
return Stream.of(
Arguments.of(
named(
"save",
new Parameter(
"save",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(0),
null))),
Arguments.of(
named(
"save with entity name",
new Parameter("save", "Value", null, sessionMethodTests.get(1), null))),
Arguments.of(
named(
"saveOrUpdate save",
new Parameter(
"saveOrUpdate",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(2),
null))),
Arguments.of(
named(
"saveOrUpdate save with entity name",
new Parameter("saveOrUpdate", "Value", null, sessionMethodTests.get(3), null))),
Arguments.of(
named(
"saveOrUpdate update with entity name",
new Parameter("saveOrUpdate", "Value", null, sessionMethodTests.get(4), null))),
Arguments.of(
named(
"merge",
new Parameter(
"merge",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(5),
null))),
Arguments.of(
named(
"merge with entity name",
new Parameter("merge", "Value", null, sessionMethodTests.get(6), null))),
Arguments.of(
named(
"persist",
new Parameter(
"persist",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(7),
null))),
Arguments.of(
named(
"persist with entity name",
new Parameter("persist", "Value", null, sessionMethodTests.get(8), null))),
Arguments.of(
named(
"persist with null entity name",
new Parameter(
"persist",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(9),
null))),
Arguments.of(
named(
"update (Session)",
new Parameter(
"update",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(10),
null))),
Arguments.of(
named(
"update by entityName (Session)",
new Parameter("update", "Value", null, sessionMethodTests.get(11), null))),
Arguments.of(
named(
"delete (Session)",
new Parameter(
"delete",
"io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value",
null,
sessionMethodTests.get(12),
null))),
Arguments.of(
named(
"delete by entityName (Session)",
new Parameter("delete", "Value", null, sessionMethodTests.get(13), 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.v6_0.Value",
queryBuildMethods.get(0),
null,
null))),
Arguments.of(
named(
"getNamedQuery",
new Parameter(
"getNamedQuery",
"SELECT io.opentelemetry.javaagent.instrumentation.hibernate.v6_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.v6_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));
}
private static SpanDataAssert assertClientSpan(SpanDataAssert span, SpanData parent) {
return span.hasKind(SpanKind.CLIENT)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(SemanticAttributes.DB_STATEMENT, val -> val.isInstanceOf(String.class)),
satisfies(SemanticAttributes.DB_OPERATION, val -> val.isInstanceOf(String.class)),
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value"));
}
private static SpanDataAssert assertClientSpan(
SpanDataAssert span, SpanData parent, String verb) {
return span.hasName(verb.concat(" db1.Value"))
.hasKind(SpanKind.CLIENT)
.hasParent(parent)
.hasAttributesSatisfyingExactly(
equalTo(SemanticAttributes.DB_SYSTEM, "h2"),
equalTo(SemanticAttributes.DB_NAME, "db1"),
equalTo(SemanticAttributes.DB_USER, "sa"),
equalTo(SemanticAttributes.DB_CONNECTION_STRING, "h2:mem:"),
satisfies(
SemanticAttributes.DB_STATEMENT,
stringAssert -> stringAssert.startsWith(verb.toLowerCase())),
equalTo(SemanticAttributes.DB_OPERATION, verb),
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value"));
}
}

View File

@ -3,6 +3,8 @@
* 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;

View File

@ -4,7 +4,7 @@
version="2.0">
<persistence-unit name="test-pu">
<class>Value</class>
<class>io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

View File

@ -22,7 +22,7 @@
<property name="hbm2ddl.auto">create</property>
<!-- Objects -->
<mapping class="Value"/>
<mapping class="io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value"/>
</session-factory>

View File

@ -17,7 +17,7 @@
<property name="hibernate.hbm2ddl.auto">create</property>
<!-- Objects -->
<mapping class="Value"/>
<mapping class="io.opentelemetry.javaagent.instrumentation.hibernate.v6_0.Value"/>
</session-factory>