convert hibernate 6 tests from groovy to java (#8304)
This commit is contained in:
parent
aef70d2f63
commit
f7c7004250
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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() }
|
||||
}
|
||||
}
|
|
@ -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") }
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"))))));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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"))))));
|
||||
}
|
||||
}
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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"/>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in New Issue