Convert hibernate-4.0 groovy tests - part 1 (#9211)
This commit is contained in:
parent
c640169388
commit
4bdfbc95d8
|
@ -32,6 +32,8 @@ dependencies {
|
|||
|
||||
testImplementation("org.hibernate:hibernate-core:4.0.0.Final")
|
||||
testImplementation("org.hibernate:hibernate-entitymanager:4.0.0.Final")
|
||||
|
||||
testImplementation("org.javassist:javassist:3.28.0-GA")
|
||||
}
|
||||
|
||||
val latestDepTest = findProperty("testLatestDeps") as Boolean
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
||||
import io.opentelemetry.javaagent.instrumentation.hibernate.v4_0.Value
|
||||
import org.hibernate.Session
|
||||
import org.hibernate.SessionFactory
|
||||
import org.hibernate.cfg.Configuration
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import io.opentelemetry.javaagent.instrumentation.hibernate.v4_0.Value
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||
import org.hibernate.Criteria
|
||||
import org.hibernate.Session
|
||||
|
@ -39,7 +40,7 @@ class CriteriaTest extends AbstractHibernateTest {
|
|||
}
|
||||
}
|
||||
span(1) {
|
||||
name "Criteria.$methodName Value"
|
||||
name "Criteria.$methodName $Value.name"
|
||||
kind INTERNAL
|
||||
childOf span(0)
|
||||
attributes {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import io.opentelemetry.javaagent.instrumentation.hibernate.v4_0.Value
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||
import spock.lang.Shared
|
||||
import spock.lang.Unroll
|
||||
|
@ -143,23 +144,23 @@ class EntityManagerTest extends AbstractHibernateTest {
|
|||
|
||||
where:
|
||||
testName | methodName | resource | attach | flushOnCommit | sessionMethodTest
|
||||
"lock" | "lock" | "Value" | true | false | { em, val ->
|
||||
"lock" | "lock" | Value.name | true | false | { em, val ->
|
||||
em.lock(val, LockModeType.PESSIMISTIC_READ)
|
||||
}
|
||||
"refresh" | "refresh" | "Value" | true | false | { em, val ->
|
||||
"refresh" | "refresh" | Value.name | true | false | { em, val ->
|
||||
em.refresh(val)
|
||||
}
|
||||
"find" | "(get|find)" | "Value" | false | false | { em, val ->
|
||||
"find" | "(get|find)" | Value.name | false | false | { em, val ->
|
||||
em.find(Value, val.getId())
|
||||
}
|
||||
"persist" | "persist" | "Value" | false | true | { em, val ->
|
||||
"persist" | "persist" | Value.name | false | true | { em, val ->
|
||||
em.persist(new Value("insert me"))
|
||||
}
|
||||
"merge" | "merge" | "Value" | true | true | { em, val ->
|
||||
"merge" | "merge" | Value.name | true | true | { em, val ->
|
||||
val.setName("New name")
|
||||
em.merge(val)
|
||||
}
|
||||
"remove" | "delete" | "Value" | true | true | { em, val ->
|
||||
"remove" | "delete" | Value.name | true | true | { em, val ->
|
||||
em.remove(val)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,605 +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.MappingException
|
||||
import org.hibernate.Query
|
||||
import org.hibernate.ReplicationMode
|
||||
import org.hibernate.Session
|
||||
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(MappingException, "Unknown entity: 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()
|
||||
Query 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") }
|
||||
"createSQLQuery" | "SELECT Value" | { sess -> sess.createSQLQuery("SELECT * 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,50 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0;
|
||||
|
||||
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
abstract class AbstractHibernateTest {
|
||||
|
||||
@RegisterExtension
|
||||
protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
|
||||
|
||||
protected static SessionFactory sessionFactory;
|
||||
protected static List<Value> prepopulated;
|
||||
|
||||
@BeforeAll
|
||||
@SuppressWarnings("deprecation") // buildSessionFactory
|
||||
static void setUp() {
|
||||
sessionFactory = new Configuration().configure().buildSessionFactory();
|
||||
|
||||
// Pre-populate the DB, so delete/update can be tested.
|
||||
Session writer = sessionFactory.openSession();
|
||||
writer.beginTransaction();
|
||||
prepopulated = new ArrayList<>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
prepopulated.add(new Value("Hello :) " + i));
|
||||
writer.save(prepopulated.get(i));
|
||||
}
|
||||
writer.getTransaction().commit();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void cleanUp() {
|
||||
if (sessionFactory != null) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,846 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0;
|
||||
|
||||
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||
import static io.opentelemetry.api.trace.SpanKind.CLIENT;
|
||||
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.ThrowableAssert.catchThrowable;
|
||||
import static org.junit.jupiter.api.Named.named;
|
||||
|
||||
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.ReplicationMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
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") // 'lock' is a deprecated method in the Session class
|
||||
class SessionTest extends AbstractHibernateTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideArgumentsHibernateAction")
|
||||
void testHibernateAction(Parameter parameter) {
|
||||
testing.runWithSpan(
|
||||
"parent",
|
||||
() -> {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
parameter.sessionMethodTest.accept(session, prepopulated.get(0));
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
|
||||
span ->
|
||||
span.hasName("Session." + parameter.methodName + " " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class))),
|
||||
span ->
|
||||
span.hasKind(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)),
|
||||
satisfies(
|
||||
SemanticAttributes.DB_OPERATION,
|
||||
val -> val.isInstanceOf(String.class)),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id"))))));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideArgumentsHibernateAction() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
named(
|
||||
"lock",
|
||||
new Parameter(
|
||||
"lock",
|
||||
(Session session, Value val) -> session.lock(val, LockMode.READ),
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"lock with entity name",
|
||||
new Parameter(
|
||||
"lock",
|
||||
(Session session, Value val) ->
|
||||
session.lock(Value.class.getName(), val, LockMode.READ),
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"lock with null name",
|
||||
new Parameter(
|
||||
"lock",
|
||||
(Session session, Value val) -> session.lock(null, val, LockMode.READ),
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"buildLockRequest",
|
||||
new Parameter(
|
||||
"lock",
|
||||
(Session session, Value val) ->
|
||||
session.buildLockRequest(LockOptions.READ).lock(val),
|
||||
null))),
|
||||
Arguments.of(named("refresh", new Parameter("refresh", Session::refresh, null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"refresh with entity name",
|
||||
new Parameter(
|
||||
"refresh",
|
||||
(Session session, Value val) -> session.refresh(Value.class.getName(), val),
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"get with entity name",
|
||||
new Parameter(
|
||||
"get",
|
||||
(Session session, Value val) -> session.get(Value.class.getName(), val.getId()),
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"get with entity class",
|
||||
new Parameter(
|
||||
"get",
|
||||
(Session session, Value val) -> session.get(Value.class, val.getId()),
|
||||
null))));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideArgumentsHibernateActionStateless")
|
||||
void testHibernateActionStateless(Parameter parameter) {
|
||||
|
||||
testing.runWithSpan(
|
||||
"parent",
|
||||
() -> {
|
||||
StatelessSession session = sessionFactory.openStatelessSession();
|
||||
session.beginTransaction();
|
||||
parameter.statelessSessionMethodTest.accept(session, prepopulated.get(0));
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
|
||||
span ->
|
||||
span.hasName("Session." + parameter.methodName + " " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class))),
|
||||
span ->
|
||||
span.hasKind(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)),
|
||||
satisfies(
|
||||
SemanticAttributes.DB_OPERATION,
|
||||
val -> val.isInstanceOf(String.class)),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id"))))));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideArgumentsHibernateActionStateless() {
|
||||
return Stream.of(
|
||||
Arguments.of(named("refresh", new Parameter("refresh", null, StatelessSession::refresh))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"refresh with entity name",
|
||||
new Parameter(
|
||||
"refresh",
|
||||
null,
|
||||
(StatelessSession session, Value val) ->
|
||||
session.refresh(Value.class.getName(), val)))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"get with entity name",
|
||||
new Parameter(
|
||||
"get",
|
||||
null,
|
||||
(StatelessSession session, Value val) ->
|
||||
session.get(Value.class.getName(), val.getId())))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"get with entity class",
|
||||
new Parameter(
|
||||
"get",
|
||||
null,
|
||||
(StatelessSession session, Value val) ->
|
||||
session.get(Value.class, val.getId())))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"insert",
|
||||
new Parameter(
|
||||
"insert",
|
||||
null,
|
||||
(StatelessSession session, Value val) ->
|
||||
session.insert(new Value("insert me"))))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"insert with entity name",
|
||||
new Parameter(
|
||||
"insert",
|
||||
null,
|
||||
(StatelessSession session, Value val) ->
|
||||
session.insert(Value.class.getName(), new Value("insert me"))))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"insert with null entity name",
|
||||
new Parameter(
|
||||
"insert",
|
||||
null,
|
||||
(StatelessSession session, Value val) ->
|
||||
session.insert(null, new Value("insert me"))))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"update (StatelessSession)",
|
||||
new Parameter(
|
||||
"update",
|
||||
null,
|
||||
(StatelessSession session, Value val) -> {
|
||||
val.setName("New name");
|
||||
session.update(val);
|
||||
}))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"update with entity name (StatelessSession)",
|
||||
new Parameter(
|
||||
"update",
|
||||
null,
|
||||
(StatelessSession session, Value val) -> {
|
||||
val.setName("New name");
|
||||
session.update(Value.class.getName(), val);
|
||||
}))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"delete (Session)",
|
||||
new Parameter(
|
||||
"delete",
|
||||
null,
|
||||
(StatelessSession session, Value val) -> {
|
||||
session.delete(val);
|
||||
prepopulated.remove(val);
|
||||
}))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"delete with entity name (Session)",
|
||||
new Parameter(
|
||||
"delete",
|
||||
null,
|
||||
(StatelessSession session, Value val) -> {
|
||||
session.delete(Value.class.getName(), val);
|
||||
prepopulated.remove(val);
|
||||
}))));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideArgumentsHibernateReplicate")
|
||||
void testHibernateReplicate(Parameter parameter) {
|
||||
testing.runWithSpan(
|
||||
"parent",
|
||||
() -> {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
parameter.sessionMethodTest.accept(session, prepopulated.get(0));
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
|
||||
span ->
|
||||
span.hasName("Session." + parameter.methodName + " " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class))),
|
||||
span ->
|
||||
span.hasKind(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)),
|
||||
satisfies(
|
||||
SemanticAttributes.DB_OPERATION,
|
||||
val -> val.isInstanceOf(String.class)),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id")))),
|
||||
span ->
|
||||
span.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(3))
|
||||
.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 Stream<Arguments> provideArgumentsHibernateReplicate() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
named(
|
||||
"replicate",
|
||||
new Parameter(
|
||||
"replicate",
|
||||
(Session session, Value val) -> {
|
||||
Value replicated = new Value(val.getName() + " replicated");
|
||||
replicated.setId(val.getId());
|
||||
session.replicate(replicated, ReplicationMode.OVERWRITE);
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"replicate by entity name",
|
||||
new Parameter(
|
||||
"replicate",
|
||||
(Session session, Value val) -> {
|
||||
Value replicated = new Value(val.getName() + " replicated");
|
||||
replicated.setId(val.getId());
|
||||
session.replicate(
|
||||
Value.class.getName(), replicated, ReplicationMode.OVERWRITE);
|
||||
},
|
||||
null))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHibernateFailedReplicate() {
|
||||
Throwable mappingException =
|
||||
testing.runWithSpan(
|
||||
"parent",
|
||||
() -> {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
|
||||
Throwable exception =
|
||||
catchThrowable(
|
||||
() -> {
|
||||
session.replicate(123L /* Not a valid entity */, ReplicationMode.OVERWRITE);
|
||||
});
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
return exception;
|
||||
});
|
||||
|
||||
assertThat(mappingException.getClass()).isEqualTo(MappingException.class);
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
|
||||
span ->
|
||||
span.hasName("Session.replicate java.lang.Long")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasStatus(StatusData.error())
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id"))))
|
||||
.hasException(mappingException),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id"))))));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideArgumentsHibernateCommitAction")
|
||||
void testHibernateCommitAction(Parameter parameter) {
|
||||
|
||||
testing.runWithSpan(
|
||||
"parent",
|
||||
() -> {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
parameter.sessionMethodTest.accept(session, prepopulated.get(0));
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
|
||||
span ->
|
||||
span.hasName("Session." + parameter.methodName + " " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class))),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id")))),
|
||||
span ->
|
||||
span.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(2))
|
||||
.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 Stream<Arguments> provideArgumentsHibernateCommitAction() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
named(
|
||||
"save",
|
||||
new Parameter(
|
||||
"save",
|
||||
(Session session, Value val) -> {
|
||||
session.save(new Value("Another value"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"save with entity name",
|
||||
new Parameter(
|
||||
"save",
|
||||
(Session session, Value val) -> {
|
||||
session.save(Value.class.getName(), new Value("Another value"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"saveOrUpdate save",
|
||||
new Parameter(
|
||||
"saveOrUpdate",
|
||||
(Session session, Value val) -> {
|
||||
session.saveOrUpdate(new Value("Value"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"saveOrUpdate save with entity name",
|
||||
new Parameter(
|
||||
"saveOrUpdate",
|
||||
(Session session, Value val) -> {
|
||||
session.saveOrUpdate(Value.class.getName(), new Value("Value"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"saveOrUpdate update with entity name",
|
||||
new Parameter(
|
||||
"saveOrUpdate",
|
||||
(Session session, Value val) -> {
|
||||
val.setName("New name");
|
||||
session.saveOrUpdate(Value.class.getName(), val);
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"merge",
|
||||
new Parameter(
|
||||
"merge",
|
||||
(Session session, Value val) -> {
|
||||
session.merge(new Value("merge me in"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"merge with entity name",
|
||||
new Parameter(
|
||||
"merge",
|
||||
(Session session, Value val) -> {
|
||||
session.merge(Value.class.getName(), new Value("merge me in"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"persist",
|
||||
new Parameter(
|
||||
"persist",
|
||||
(Session session, Value val) -> {
|
||||
session.persist(new Value("merge me in"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"persist with entity name",
|
||||
new Parameter(
|
||||
"persist",
|
||||
(Session session, Value val) -> {
|
||||
session.persist(Value.class.getName(), new Value("merge me in"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"persist with null entity name",
|
||||
new Parameter(
|
||||
"persist",
|
||||
(Session session, Value val) -> {
|
||||
session.persist(null, new Value("merge me in"));
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"update (Session)",
|
||||
new Parameter(
|
||||
"update",
|
||||
(Session session, Value val) -> {
|
||||
val.setName("New name");
|
||||
session.update(val);
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"update by entityName (Session)",
|
||||
new Parameter(
|
||||
"update",
|
||||
(Session session, Value val) -> {
|
||||
val.setName("New name");
|
||||
session.update(Value.class.getName(), val);
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"delete (Session)",
|
||||
new Parameter(
|
||||
"delete",
|
||||
(Session session, Value val) -> {
|
||||
session.delete(val);
|
||||
prepopulated.remove(val);
|
||||
},
|
||||
null))),
|
||||
Arguments.of(
|
||||
named(
|
||||
"delete by entityName (Session)",
|
||||
new Parameter(
|
||||
"delete",
|
||||
(Session session, Value val) -> {
|
||||
session.delete(Value.class.getName(), val);
|
||||
prepopulated.remove(val);
|
||||
},
|
||||
null))));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideArgumentsStateQuery")
|
||||
void testAttachesStateToQueryCreated(Consumer<Session> queryBuilder) {
|
||||
|
||||
testing.runWithSpan(
|
||||
"parent",
|
||||
() -> {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
queryBuilder.accept(session);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
});
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
|
||||
span ->
|
||||
span.hasName("SELECT Value")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class))),
|
||||
span ->
|
||||
span.hasKind(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)),
|
||||
satisfies(
|
||||
SemanticAttributes.DB_OPERATION,
|
||||
val -> val.isInstanceOf(String.class)),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id"))))));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideArgumentsStateQuery() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
named(
|
||||
"createQuery",
|
||||
((Consumer<Session>) session -> session.createQuery("from Value").list())),
|
||||
Arguments.of(
|
||||
named(
|
||||
"getNamedQuery",
|
||||
((Consumer<Session>)
|
||||
session -> session.getNamedQuery("TestNamedQuery").list())),
|
||||
Arguments.of(
|
||||
named(
|
||||
"createSQLQuery",
|
||||
(Consumer<Session>)
|
||||
session -> session.createSQLQuery("SELECT * FROM Value").list())))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHibernateOverlappingSessions() {
|
||||
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();
|
||||
});
|
||||
|
||||
AtomicReference<String> sessionId1 = new AtomicReference<>();
|
||||
AtomicReference<String> sessionId2 = new AtomicReference<>();
|
||||
AtomicReference<String> sessionId3 = new AtomicReference<>();
|
||||
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span -> span.hasName("overlapping Sessions"),
|
||||
span -> {
|
||||
span.hasName("Session.save " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class)));
|
||||
sessionId1.set(
|
||||
trace.getSpan(1).getAttributes().get(stringKey("hibernate.session_id")));
|
||||
},
|
||||
span -> {
|
||||
span.hasName("Session.insert " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class)));
|
||||
sessionId2.set(
|
||||
trace.getSpan(2).getAttributes().get(stringKey("hibernate.session_id")));
|
||||
},
|
||||
span ->
|
||||
span.hasName("INSERT db1.Value")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(2))
|
||||
.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("insert")),
|
||||
equalTo(SemanticAttributes.DB_OPERATION, "INSERT"),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
|
||||
span -> {
|
||||
span.hasName("Session.save " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class)));
|
||||
sessionId3.set(
|
||||
trace.getSpan(4).getAttributes().get(stringKey("hibernate.session_id")));
|
||||
},
|
||||
span ->
|
||||
span.hasName("Session.delete " + Value.class.getName())
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
satisfies(
|
||||
stringKey("hibernate.session_id"),
|
||||
val -> val.isInstanceOf(String.class))),
|
||||
span ->
|
||||
span.hasName("Transaction.commit")
|
||||
.hasKind(INTERNAL)
|
||||
.hasParent(trace.getSpan(0))
|
||||
.hasAttributesSatisfyingExactly(
|
||||
equalTo(
|
||||
stringKey("hibernate.session_id"),
|
||||
trace
|
||||
.getSpan(1)
|
||||
.getAttributes()
|
||||
.get(stringKey("hibernate.session_id")))),
|
||||
span ->
|
||||
span.hasName("INSERT db1.Value")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(6))
|
||||
.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("insert")),
|
||||
equalTo(SemanticAttributes.DB_OPERATION, "INSERT"),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value")),
|
||||
span ->
|
||||
span.hasName("DELETE db1.Value")
|
||||
.hasKind(CLIENT)
|
||||
.hasParent(trace.getSpan(6))
|
||||
.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("delete")),
|
||||
equalTo(SemanticAttributes.DB_OPERATION, "DELETE"),
|
||||
equalTo(SemanticAttributes.DB_SQL_TABLE, "Value"))));
|
||||
|
||||
assertThat(sessionId1.get()).isNotEqualTo(sessionId2.get());
|
||||
assertThat(sessionId1.get()).isNotEqualTo(sessionId3.get());
|
||||
assertThat(sessionId2.get()).isNotEqualTo(sessionId3.get());
|
||||
}
|
||||
|
||||
private static class Parameter {
|
||||
public final String methodName;
|
||||
public final BiConsumer<Session, Value> sessionMethodTest;
|
||||
public final BiConsumer<StatelessSession, Value> statelessSessionMethodTest;
|
||||
|
||||
public Parameter(
|
||||
String methodName,
|
||||
BiConsumer<Session, Value> sessionMethodTest,
|
||||
BiConsumer<StatelessSession, Value> statelessSessionMethodTest) {
|
||||
this.methodName = methodName;
|
||||
this.sessionMethodTest = sessionMethodTest;
|
||||
this.statelessSessionMethodTest = statelessSessionMethodTest;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
|
@ -4,7 +4,7 @@
|
|||
version="2.0">
|
||||
|
||||
<persistence-unit name="test-pu">
|
||||
<class>Value</class>
|
||||
<class>io.opentelemetry.javaagent.instrumentation.hibernate.v4_0.Value</class>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
|
||||
|
@ -15,4 +15,4 @@
|
|||
<property name="javax.persistence.jdbc.password" value=""/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
</persistence>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<property name="hbm2ddl.auto">create</property>
|
||||
|
||||
<!-- Objects -->
|
||||
<mapping class="Value"/>
|
||||
<mapping class="io.opentelemetry.javaagent.instrumentation.hibernate.v4_0.Value"/>
|
||||
|
||||
</session-factory>
|
||||
|
||||
|
|
Loading…
Reference in New Issue