Merge pull request #769 from DataDog/willgittoes-dd/hibernate-3.5

Support Hibernate 3.5
This commit is contained in:
Will Gittoes 2019-03-20 15:53:29 +11:00 committed by GitHub
commit 143abcbcf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 1762 additions and 45 deletions

View File

@ -0,0 +1,62 @@
/*
* Integration for Hibernate between 3.5 and 4.
* Has the same logic as the Hibernate 4+ integration, but is copied rather than sharing a codebase. This is because
* the root interface for Session/StatelessSession - SharedSessionContract - isn't present before version 4. So the
* instrumentation isn't able to reference it.
*/
// Set properties before any plugins get loaded
project.ext {
// Execute tests on all JVMs, even rare and outdated ones
coreJavaInstrumentation = true
minJavaVersionForTests = JavaVersion.VERSION_1_7
}
muzzle {
pass {
group = "org.hibernate"
module = "hibernate-core"
versions = "[3.5.0-Final,4.0.0.Final)"
}
}
apply from: "${rootDir}/gradle/java.gradle"
apply plugin: 'org.unbroken-dome.test-sets'
testSets {
latestDepTest {
dirName = 'test'
}
}
dependencies {
compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '3.5.0-Final'
compile project(':dd-java-agent:agent-tooling')
compile project(':dd-java-agent:instrumentation:hibernate')
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:jdbc')
testCompile group: 'org.hibernate', name: 'hibernate-core', version: '3.5.0-Final'
testCompile group: 'org.hibernate', name: 'hibernate-annotations', version: '+'
testCompile group: 'javassist', name: 'javassist', version: '+'
testCompile group: 'com.h2database', name: 'h2', version: '1.4.197'
testCompile "javax.xml.bind:jaxb-api:2.2.11"
testCompile "com.sun.xml.bind:jaxb-core:2.2.11"
testCompile "com.sun.xml.bind:jaxb-impl:2.2.11"
testCompile "javax.activation:activation:1.1.1"
latestDepTestCompile group: 'org.hibernate', name: 'hibernate-core', version: '3.+'
}
configurations {
// Needed for test, but for latestDepTest this would otherwise bundle a second incompatible version of hibernate-core.
latestDepTestCompile.exclude group: 'org.hibernate', module: 'hibernate-annotations'
}

View File

@ -1,4 +1,4 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate.core.v3_5;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
@ -11,6 +11,8 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -34,13 +36,13 @@ public class CriteriaInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".SessionMethodUtils", "datadog.trace.instrumentation.hibernate.SessionMethodUtils",
packageName + ".SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
packageName + ".HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate.core.v3_5;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.hibernate.v4_0.HibernateDecorator.DECORATOR; import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -12,6 +12,8 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -36,13 +38,13 @@ public class QueryInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".SessionMethodUtils", "datadog.trace.instrumentation.hibernate.SessionMethodUtils",
packageName + ".SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
packageName + ".HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -0,0 +1,96 @@
package datadog.trace.instrumentation.hibernate.core.v3_5;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionState;
import io.opentracing.Span;
import io.opentracing.util.GlobalTracer;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
@AutoService(Instrumenter.class)
public class SessionFactoryInstrumentation extends Instrumenter.Default {
public SessionFactoryInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> contextStore() {
final Map<String, String> stores = new HashMap<>();
stores.put("org.hibernate.Session", SessionState.class.getName());
stores.put("org.hibernate.StatelessSession", SessionState.class.getName());
stores.put("org.hibernate.SharedSessionContract", SessionState.class.getName());
return stores;
}
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.HibernateDecorator",
};
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return not(isInterface()).and(safeHasSuperType(named("org.hibernate.SessionFactory")));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod()
.and(named("openSession").or(named("openStatelessSession")))
.and(takesArguments(0))
.and(
returns(
named("org.hibernate.Session")
.or(named("org.hibernate.StatelessSession"))
.or(safeHasSuperType(named("org.hibernate.Session"))))),
SessionFactoryAdvice.class.getName());
}
public static class SessionFactoryAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void openSession(@Advice.Return final Object session) {
final Span span = GlobalTracer.get().buildSpan("hibernate.session").start();
DECORATOR.afterStart(span);
DECORATOR.onConnection(span, session);
if (session instanceof Session) {
final ContextStore<Session, SessionState> contextStore =
InstrumentationContext.get(Session.class, SessionState.class);
contextStore.putIfAbsent((Session) session, new SessionState(span));
} else if (session instanceof StatelessSession) {
final ContextStore<StatelessSession, SessionState> contextStore =
InstrumentationContext.get(StatelessSession.class, SessionState.class);
contextStore.putIfAbsent((StatelessSession) session, new SessionState(span));
}
}
}
}

View File

@ -0,0 +1,257 @@
package datadog.trace.instrumentation.hibernate.core.v3_5;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import static datadog.trace.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import io.opentracing.Span;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
@AutoService(Instrumenter.class)
public class SessionInstrumentation extends Instrumenter.Default {
public SessionInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> contextStore() {
final Map<String, String> map = new HashMap<>();
map.put("org.hibernate.Session", SessionState.class.getName());
map.put("org.hibernate.StatelessSession", SessionState.class.getName());
map.put("org.hibernate.Query", SessionState.class.getName());
map.put("org.hibernate.Transaction", SessionState.class.getName());
map.put("org.hibernate.Criteria", SessionState.class.getName());
return Collections.unmodifiableMap(map);
}
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.instrumentation.hibernate.SessionMethodUtils",
"datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.HibernateDecorator",
};
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return not(isInterface())
.and(
safeHasSuperType(
named("org.hibernate.Session").or(named("org.hibernate.StatelessSession"))));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
final Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
transformers.put(
isMethod().and(named("close")).and(takesArguments(0)), SessionCloseAdvice.class.getName());
// Session synchronous methods we want to instrument.
transformers.put(
isMethod()
.and(
named("save")
.or(named("replicate"))
.or(named("saveOrUpdate"))
.or(named("update"))
.or(named("merge"))
.or(named("persist"))
.or(named("lock"))
.or(named("refresh"))
.or(named("insert"))
.or(named("delete"))
// Iterator methods.
.or(named("iterate"))
// Lazy-load methods.
.or(named("immediateLoad"))
.or(named("internalLoad"))),
SessionMethodAdvice.class.getName());
// Handle the non-generic 'get' separately.
transformers.put(
isMethod()
.and(named("get"))
.and(returns(named("java.lang.Object")))
.and(takesArgument(0, named("java.lang.String"))),
SessionMethodAdvice.class.getName());
// These methods return some object that we want to instrument, and so the Advice will pin the
// current Span to the returned object using a ContextStore.
transformers.put(
isMethod()
.and(named("beginTransaction").or(named("getTransaction")))
.and(returns(named("org.hibernate.Transaction"))),
GetTransactionAdvice.class.getName());
transformers.put(
isMethod().and(returns(safeHasSuperType(named("org.hibernate.Query")))),
GetQueryAdvice.class.getName());
transformers.put(
isMethod().and(returns(safeHasSuperType(named("org.hibernate.Criteria")))),
GetCriteriaAdvice.class.getName());
return transformers;
}
public static class SessionCloseAdvice {
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void closeSession(
@Advice.This final Object session, @Advice.Thrown final Throwable throwable) {
SessionState state = null;
if (session instanceof Session) {
final ContextStore<Session, SessionState> contextStore =
InstrumentationContext.get(Session.class, SessionState.class);
state = contextStore.get((Session) session);
} else if (session instanceof StatelessSession) {
final ContextStore<StatelessSession, SessionState> contextStore =
InstrumentationContext.get(StatelessSession.class, SessionState.class);
state = contextStore.get((StatelessSession) session);
}
if (state == null || state.getSessionSpan() == null) {
return;
}
if (state.getMethodScope() != null) {
state.getMethodScope().close();
}
final Span span = state.getSessionSpan();
DECORATOR.onError(span, throwable);
DECORATOR.beforeFinish(span);
span.finish();
}
}
public static class SessionMethodAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static SessionState startMethod(
@Advice.This final Object session,
@Advice.Origin("#m") final String name,
@Advice.Argument(0) final Object entity) {
final boolean startSpan = !SCOPE_ONLY_METHODS.contains(name);
if (session instanceof Session) {
final ContextStore<Session, SessionState> contextStore =
InstrumentationContext.get(Session.class, SessionState.class);
return SessionMethodUtils.startScopeFrom(
contextStore, (Session) session, "hibernate." + name, entity, startSpan);
} else if (session instanceof StatelessSession) {
final ContextStore<StatelessSession, SessionState> contextStore =
InstrumentationContext.get(StatelessSession.class, SessionState.class);
return SessionMethodUtils.startScopeFrom(
contextStore, (StatelessSession) session, "hibernate." + name, entity, startSpan);
}
return null;
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endMethod(
@Advice.Enter final SessionState sessionState,
@Advice.Thrown final Throwable throwable,
@Advice.Return(typing = Assigner.Typing.DYNAMIC) final Object returned) {
SessionMethodUtils.closeScope(sessionState, throwable, returned);
}
}
public static class GetQueryAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void getQuery(
@Advice.This final Object session, @Advice.Return final Query query) {
final ContextStore<Query, SessionState> queryContextStore =
InstrumentationContext.get(Query.class, SessionState.class);
if (session instanceof Session) {
final ContextStore<Session, SessionState> sessionContextStore =
InstrumentationContext.get(Session.class, SessionState.class);
SessionMethodUtils.attachSpanFromStore(
sessionContextStore, (Session) session, queryContextStore, query);
} else if (session instanceof StatelessSession) {
final ContextStore<StatelessSession, SessionState> sessionContextStore =
InstrumentationContext.get(StatelessSession.class, SessionState.class);
SessionMethodUtils.attachSpanFromStore(
sessionContextStore, (StatelessSession) session, queryContextStore, query);
}
}
}
public static class GetTransactionAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void getTransaction(
@Advice.This final Object session, @Advice.Return final Transaction transaction) {
final ContextStore<Transaction, SessionState> transactionContextStore =
InstrumentationContext.get(Transaction.class, SessionState.class);
if (session instanceof Session) {
final ContextStore<Session, SessionState> sessionContextStore =
InstrumentationContext.get(Session.class, SessionState.class);
SessionMethodUtils.attachSpanFromStore(
sessionContextStore, (Session) session, transactionContextStore, transaction);
} else if (session instanceof StatelessSession) {
final ContextStore<StatelessSession, SessionState> sessionContextStore =
InstrumentationContext.get(StatelessSession.class, SessionState.class);
SessionMethodUtils.attachSpanFromStore(
sessionContextStore, (StatelessSession) session, transactionContextStore, transaction);
}
}
}
public static class GetCriteriaAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void getCriteria(
@Advice.This final Object session, @Advice.Return final Criteria criteria) {
final ContextStore<Criteria, SessionState> criteriaContextStore =
InstrumentationContext.get(Criteria.class, SessionState.class);
if (session instanceof Session) {
final ContextStore<Session, SessionState> sessionContextStore =
InstrumentationContext.get(Session.class, SessionState.class);
SessionMethodUtils.attachSpanFromStore(
sessionContextStore, (Session) session, criteriaContextStore, criteria);
} else if (session instanceof StatelessSession) {
final ContextStore<StatelessSession, SessionState> sessionContextStore =
InstrumentationContext.get(StatelessSession.class, SessionState.class);
SessionMethodUtils.attachSpanFromStore(
sessionContextStore, (StatelessSession) session, criteriaContextStore, criteria);
}
}
}
}

View File

@ -1,4 +1,4 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate.core.v3_5;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
@ -12,6 +12,8 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -34,13 +36,13 @@ public class TransactionInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".SessionMethodUtils", "datadog.trace.instrumentation.hibernate.SessionMethodUtils",
packageName + ".SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
packageName + ".HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -0,0 +1,35 @@
import datadog.trace.agent.test.AgentTestRunner
import org.hibernate.Session
import org.hibernate.SessionFactory
import org.hibernate.cfg.AnnotationConfiguration
import spock.lang.Shared
abstract class AbstractHibernateTest extends AgentTestRunner {
@Shared
protected SessionFactory sessionFactory
@Shared
protected List<Value> prepopulated
def setupSpec() {
sessionFactory = new AnnotationConfiguration().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 < 2; i++) {
prepopulated.add(new Value("Hello :) " + i))
writer.save(prepopulated.get(i))
}
writer.getTransaction().commit()
writer.close()
}
def cleanupSpec() {
if (sessionFactory != null) {
sessionFactory.close()
}
}
}

View File

@ -0,0 +1,627 @@
import datadog.trace.api.DDSpanTypes
import io.opentracing.Scope
import io.opentracing.Tracer
import io.opentracing.tag.Tags
import io.opentracing.util.GlobalTracer
import org.hibernate.*
import spock.lang.Shared
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) {
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:
assertTraces(sessionImplementations.size()) {
for (int i = 0; i < sessionImplementations.size(); i++) {
trace(i, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName resource
operationName "hibernate.$methodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(3) {
serviceName "h2"
spanType "sql"
childOf span(2)
}
}
}
}
where:
testName | methodName | resource | sessionImplementations | sessionMethodTest
"lock" | "lock" | "Value" | [sessionBuilder] | { sesh, val ->
sesh.lock(val, LockMode.READ)
}
"refresh" | "refresh" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val ->
sesh.refresh(val)
}
"get" | "get" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val ->
sesh.get("Value", val.getId())
}
}
def "test hibernate statless action #testName"() {
setup:
// Test for each implementation of Session.
def session = statelessSessionBuilder()
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:
assertTraces(1) {
trace(0, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "h2"
spanType "sql"
childOf span(1)
}
span(3) {
serviceName "hibernate"
resourceName resource
operationName "hibernate.$methodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
}
}
where:
testName | methodName | resource | sessionMethodTest
"insert" | "insert" | "Value" | { sesh, val ->
sesh.insert("Value", new Value("insert me"))
}
"update" | "update" | "Value" | { sesh, val ->
val.setName("New name")
sesh.update(val)
}
"update by entityName" | "update" | "Value" | { sesh, val ->
val.setName("New name")
sesh.update("Value", val)
}
"delete" | "delete" | "Value" | { sesh, val ->
sesh.delete(val)
}
}
def "test hibernate replicate: #testName"() {
setup:
// Test for each implementation of Session.
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:
assertTraces(1) {
trace(0, 5) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "h2"
spanType "sql"
childOf span(1)
}
span(3) {
serviceName "hibernate"
resourceName resource
operationName "hibernate.$methodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(4) {
serviceName "h2"
spanType "sql"
childOf span(3)
}
}
}
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.
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:
assertTraces(1) {
trace(0, 3) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName "hibernate.replicate"
operationName "hibernate.replicate"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
errored(true)
tags {
errorTags(MappingException, "Unknown entity: java.lang.Long")
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
}
}
}
def "test hibernate commit action #testName"() {
setup:
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:
assertTraces(1) {
trace(0, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "h2"
spanType "sql"
childOf span(1)
}
span(3) {
serviceName "hibernate"
resourceName resource
operationName "hibernate.$methodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
}
}
where:
testName | methodName | resource | sessionMethodTest
"save" | "save" | "Value" | { sesh, val ->
sesh.save(new Value("Another value"))
}
"saveOrUpdate save" | "saveOrUpdate" | "Value" | { sesh, val ->
sesh.saveOrUpdate(new Value("Value"))
}
"saveOrUpdate update" | "saveOrUpdate" | "Value" | { sesh, val ->
val.setName("New name")
sesh.saveOrUpdate(val)
}
"merge" | "merge" | "Value" | { sesh, val ->
sesh.merge(new Value("merge me in"))
}
"persist" | "persist" | "Value" | { sesh, val ->
sesh.persist(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)
}
}
def "test attaches State to query created via #queryMethodName"() {
setup:
Session session = sessionFactory.openSession()
session.beginTransaction()
Query query = queryBuildMethod(session)
query.list()
session.getTransaction().commit()
session.close()
expect:
assertTraces(1) {
trace(0, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName "$resource"
operationName "hibernate.query.list"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(3) {
serviceName "h2"
spanType "sql"
childOf span(2)
}
}
}
where:
queryMethodName | resource | queryBuildMethod
"createQuery" | "Value" | { sess -> sess.createQuery("from Value") }
"getNamedQuery" | "Value" | { sess -> sess.getNamedQuery("TestNamedQuery") }
"createSQLQuery" | "SELECT * FROM Value" | { sess -> sess.createSQLQuery("SELECT * FROM Value") }
}
def "test hibernate overlapping Sessions"() {
setup:
Tracer tracer = GlobalTracer.get()
Scope scope = tracer.buildSpan("overlapping Sessions").startActive(true)
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()
scope.close()
expect:
assertTraces(1) {
trace(0, 11) {
span(0) {
serviceName "unnamed-java-app"
operationName "overlapping Sessions"
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(3) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(2)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(4) {
serviceName "h2"
spanType "sql"
childOf span(3)
}
span(5) {
serviceName "h2"
spanType "sql"
childOf span(3)
}
span(6) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(7) {
serviceName "hibernate"
resourceName "Value"
operationName "hibernate.delete"
spanType DDSpanTypes.HIBERNATE
childOf span(2)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(8) {
serviceName "hibernate"
resourceName "Value"
operationName "hibernate.save"
spanType DDSpanTypes.HIBERNATE
childOf span(1)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(9) {
serviceName "hibernate"
resourceName "Value"
operationName "hibernate.insert"
spanType DDSpanTypes.HIBERNATE
childOf span(6)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(10) {
serviceName "hibernate"
resourceName "Value"
operationName "hibernate.save"
spanType DDSpanTypes.HIBERNATE
childOf span(2)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
}
}
}
}

View File

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

View File

@ -27,6 +27,7 @@ dependencies {
compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '4.0.0.Final' compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '4.0.0.Final'
compile project(':dd-java-agent:agent-tooling') compile project(':dd-java-agent:agent-tooling')
compile project(':dd-java-agent:instrumentation:hibernate')
compile deps.bytebuddy compile deps.bytebuddy
compile deps.opentracing compile deps.opentracing
@ -47,5 +48,5 @@ dependencies {
latestDepTestCompile group: 'org.hibernate', name: 'hibernate-core', version: '+' latestDepTestCompile group: 'org.hibernate', name: 'hibernate-core', version: '+'
latestDepTestCompile group: 'com.h2database', name: 'h2', version: '1.4.197' latestDepTestCompile group: 'com.h2database', name: 'h2', version: '1.4.197'
// Test that the incremental instrumentation for hibernate 4.3 doesn't cause issues. // Test that the incremental instrumentation for hibernate 4.3 doesn't cause issues.
latestDepTestCompile project(':dd-java-agent:instrumentation:hibernate-4.3') latestDepTestCompile project(':dd-java-agent:instrumentation:hibernate:core-4.3')
} }

View File

@ -0,0 +1,83 @@
package datadog.trace.instrumentation.hibernate.core.v4_0;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Criteria;
@AutoService(Instrumenter.class)
public class CriteriaInstrumentation extends Instrumenter.Default {
public CriteriaInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Criteria", SessionState.class.getName());
}
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.instrumentation.hibernate.SessionMethodUtils",
"datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.HibernateDecorator",
};
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return not(isInterface()).and(safeHasSuperType(named("org.hibernate.Criteria")));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod().and(named("list").or(named("uniqueResult")).or(named("scroll"))),
CriteriaMethodAdvice.class.getName());
}
public static class CriteriaMethodAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static SessionState startMethod(
@Advice.This final Criteria criteria, @Advice.Origin("#m") final String name) {
final ContextStore<Criteria, SessionState> contextStore =
InstrumentationContext.get(Criteria.class, SessionState.class);
return SessionMethodUtils.startScopeFrom(
contextStore, criteria, "hibernate.criteria." + name, null, true);
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endMethod(
@Advice.Enter final SessionState state,
@Advice.Thrown final Throwable throwable,
@Advice.Return(typing = Assigner.Typing.DYNAMIC) final Object entity) {
SessionMethodUtils.closeScope(state, throwable, entity);
}
}
}

View File

@ -0,0 +1,102 @@
package datadog.trace.instrumentation.hibernate.core.v4_0;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
@AutoService(Instrumenter.class)
public class QueryInstrumentation extends Instrumenter.Default {
public QueryInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Query", SessionState.class.getName());
}
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.instrumentation.hibernate.SessionMethodUtils",
"datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.HibernateDecorator",
};
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return not(isInterface()).and(safeHasSuperType(named("org.hibernate.Query")));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod()
.and(
named("list")
.or(named("executeUpdate"))
.or(named("uniqueResult"))
.or(named("scroll"))),
QueryMethodAdvice.class.getName());
}
public static class QueryMethodAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static SessionState startMethod(
@Advice.This final Query query, @Advice.Origin("#m") final String name) {
final ContextStore<Query, SessionState> contextStore =
InstrumentationContext.get(Query.class, SessionState.class);
// Note: We don't know what the entity is until the method is returning.
final SessionState state =
SessionMethodUtils.startScopeFrom(
contextStore, query, "hibernate.query." + name, null, true);
DECORATOR.onStatement(state.getMethodScope().span(), query.getQueryString());
return state;
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endMethod(
@Advice.This final Query query,
@Advice.Enter final SessionState state,
@Advice.Thrown final Throwable throwable,
@Advice.Return(typing = Assigner.Typing.DYNAMIC) final Object returned) {
Object entity = returned;
if (returned == null || query instanceof SQLQuery) {
// Not a method that returns results, or the query returns a table rather than an ORM
// object.
entity = query.getQueryString();
}
SessionMethodUtils.closeScope(state, throwable, entity);
}
}
}

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate.core.v4_0;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.hibernate.v4_0.HibernateDecorator.DECORATOR; import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -14,6 +14,7 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionState;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.Map; import java.util.Map;
@ -38,12 +39,12 @@ public class SessionFactoryInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
packageName + ".HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -1,8 +1,8 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate.core.v4_0;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.hibernate.v4_0.HibernateDecorator.DECORATOR; import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import static datadog.trace.instrumentation.hibernate.v4_0.SessionMethodUtils.SCOPE_ONLY_METHODS; import static datadog.trace.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -15,6 +15,8 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import io.opentracing.Span; import io.opentracing.Span;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -49,13 +51,13 @@ public class SessionInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".SessionMethodUtils", "datadog.trace.instrumentation.hibernate.SessionMethodUtils",
packageName + ".SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
packageName + ".HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -0,0 +1,82 @@
package datadog.trace.instrumentation.hibernate.core.v4_0;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Transaction;
@AutoService(Instrumenter.class)
public class TransactionInstrumentation extends Instrumenter.Default {
public TransactionInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Transaction", SessionState.class.getName());
}
@Override
public String[] helperClassNames() {
return new String[] {
"datadog.trace.instrumentation.hibernate.SessionMethodUtils",
"datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.HibernateDecorator",
};
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return not(isInterface()).and(safeHasSuperType(named("org.hibernate.Transaction")));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod().and(named("commit")).and(takesArguments(0)),
TransactionCommitAdvice.class.getName());
}
public static class TransactionCommitAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static SessionState startCommit(@Advice.This final Transaction transaction) {
final ContextStore<Transaction, SessionState> contextStore =
InstrumentationContext.get(Transaction.class, SessionState.class);
return SessionMethodUtils.startScopeFrom(
contextStore, transaction, "hibernate.transaction.commit", null, true);
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endCommit(
@Advice.This final Transaction transaction,
@Advice.Enter final SessionState state,
@Advice.Thrown final Throwable throwable) {
SessionMethodUtils.closeScope(state, throwable, null);
}
}
}

View File

@ -0,0 +1,74 @@
import datadog.trace.api.DDSpanTypes
import io.opentracing.tag.Tags
import org.hibernate.Criteria
import org.hibernate.Session
import org.hibernate.criterion.Order
import org.hibernate.criterion.Restrictions
class CriteriaTest extends AbstractHibernateTest {
def "test criteria.#methodName"() {
setup:
Session session = sessionFactory.openSession()
session.beginTransaction()
Criteria criteria = session.createCriteria(Value)
.add(Restrictions.like("name", "Hello"))
.addOrder(Order.desc("name"))
interaction.call(criteria)
session.getTransaction().commit()
session.close()
expect:
assertTraces(1) {
trace(0, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName "hibernate.criteria.$methodName"
operationName "hibernate.criteria.$methodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(3) {
serviceName "h2"
spanType "sql"
childOf span(2)
}
}
}
where:
methodName | interaction
"list" | { c -> c.list() }
"uniqueResult" | { c -> c.uniqueResult() }
"scroll" | { c -> c.scroll() }
}
}

View File

@ -0,0 +1,192 @@
import datadog.trace.api.DDSpanTypes
import io.opentracing.tag.Tags
import org.hibernate.Query
import org.hibernate.Session
class QueryTest extends AbstractHibernateTest {
def "test hibernate query.#queryMethodName single call"() {
setup:
// With Transaction
Session session = sessionFactory.openSession()
session.beginTransaction()
queryInteraction(session)
session.getTransaction().commit()
session.close()
// Without Transaction
if (!requiresTransaction) {
session = sessionFactory.openSession()
queryInteraction(session)
session.close()
}
expect:
assertTraces(requiresTransaction ? 1 : 2) {
// With Transaction
trace(0, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName "$resource"
operationName "hibernate.$queryMethodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(3) {
serviceName "h2"
spanType "sql"
childOf span(2)
}
}
if (!requiresTransaction) {
// Without Transaction
trace(1, 3) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "$resource"
operationName "hibernate.$queryMethodName"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "h2"
spanType "sql"
childOf span(1)
}
}
}
}
where:
queryMethodName | resource | requiresTransaction | queryInteraction
"query.list" | "Value" | false | { sess ->
Query q = sess.createQuery("from Value")
q.list()
}
"query.executeUpdate" | "update Value set name = 'alyx'" | true | { sess ->
Query q = sess.createQuery("update Value set name = 'alyx'")
q.executeUpdate()
}
"query.uniqueResult" | "Value" | false | { sess ->
Query q = sess.createQuery("from Value where id = 1")
q.uniqueResult()
}
"iterate" | "from Value" | false | { sess ->
Query q = sess.createQuery("from Value")
q.iterate()
}
"query.scroll" | "from Value" | false | { sess ->
Query q = sess.createQuery("from Value")
q.scroll()
}
}
def "test hibernate query.iterate"() {
setup:
Session session = sessionFactory.openSession()
session.beginTransaction()
Query q = session.createQuery("from Value")
Iterator it = q.iterate()
while (it.hasNext()) {
it.next()
}
session.getTransaction().commit()
session.close()
expect:
assertTraces(1) {
trace(0, 4) {
span(0) {
serviceName "hibernate"
resourceName "hibernate.session"
operationName "hibernate.session"
spanType DDSpanTypes.HIBERNATE
parent()
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(1) {
serviceName "hibernate"
resourceName "hibernate.transaction.commit"
operationName "hibernate.transaction.commit"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(2) {
serviceName "hibernate"
resourceName "from Value"
operationName "hibernate.iterate"
spanType DDSpanTypes.HIBERNATE
childOf span(0)
tags {
"$Tags.COMPONENT.key" "java-hibernate"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
span(3) {
serviceName "h2"
spanType "sql"
childOf span(2)
}
}
}
}
}

View File

@ -27,7 +27,7 @@ dependencies {
compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '4.3.0.Final' compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '4.3.0.Final'
compile project(':dd-java-agent:agent-tooling') compile project(':dd-java-agent:agent-tooling')
compile project(':dd-java-agent:instrumentation:hibernate-4.0') compile project(':dd-java-agent:instrumentation:hibernate:core-4.0')
compile deps.bytebuddy compile deps.bytebuddy
compile deps.opentracing compile deps.opentracing

View File

@ -1,4 +1,4 @@
package datadog.trace.instrumentation.hibernate.v4_3; package datadog.trace.instrumentation.hibernate.core.v4_3;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
@ -11,8 +11,8 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.v4_0.SessionMethodUtils; import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.v4_0.SessionState; import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -35,13 +35,13 @@ public class ProcedureCallInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
"datadog.trace.instrumentation.hibernate.v4_0.SessionMethodUtils", "datadog.trace.instrumentation.hibernate.SessionMethodUtils",
"datadog.trace.instrumentation.hibernate.v4_0.SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.v4_0.HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -1,4 +1,4 @@
package datadog.trace.instrumentation.hibernate.v4_3; package datadog.trace.instrumentation.hibernate.core.v4_3;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
@ -11,8 +11,8 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import datadog.trace.instrumentation.hibernate.v4_0.SessionMethodUtils; import datadog.trace.instrumentation.hibernate.SessionMethodUtils;
import datadog.trace.instrumentation.hibernate.v4_0.SessionState; import datadog.trace.instrumentation.hibernate.SessionState;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -41,13 +41,13 @@ public class SessionInstrumentation extends Instrumenter.Default {
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
"datadog.trace.instrumentation.hibernate.v4_0.SessionMethodUtils", "datadog.trace.instrumentation.hibernate.SessionMethodUtils",
"datadog.trace.instrumentation.hibernate.v4_0.SessionState", "datadog.trace.instrumentation.hibernate.SessionState",
"datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
"datadog.trace.agent.decorator.OrmClientDecorator", "datadog.trace.agent.decorator.OrmClientDecorator",
"datadog.trace.instrumentation.hibernate.v4_0.HibernateDecorator", "datadog.trace.instrumentation.hibernate.HibernateDecorator",
}; };
} }

View File

@ -0,0 +1,42 @@
import datadog.trace.api.Trace;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.NamedQuery;
@Entity
@Table
@NamedQuery(name = "TestNamedQuery", query = "from Value")
public class Value {
private Long id;
private String name;
public Value() {}
public Value(final String name) {
this.name = name;
}
@Id
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
public Long getId() {
return id;
}
private void setId(final Long id) {
this.id = id;
}
@Trace
public String getName() {
return name;
}
public void setName(final String title) {
this.name = title;
}
}

View File

@ -0,0 +1,14 @@
/*
* Classes that are common to all versions of the Hibernate instrumentation.
*/
apply from: "${rootDir}/gradle/java.gradle"
dependencies {
compile project(':dd-java-agent:agent-tooling')
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
}

View File

@ -1,9 +1,11 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate;
import datadog.trace.agent.decorator.OrmClientDecorator; import datadog.trace.agent.decorator.OrmClientDecorator;
import datadog.trace.api.DDSpanTypes; import datadog.trace.api.DDSpanTypes;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.List; import java.util.List;
import javax.persistence.Entity; import java.util.Set;
public class HibernateDecorator extends OrmClientDecorator { public class HibernateDecorator extends OrmClientDecorator {
public static final HibernateDecorator DECORATOR = new HibernateDecorator(); public static final HibernateDecorator DECORATOR = new HibernateDecorator();
@ -46,16 +48,22 @@ public class HibernateDecorator extends OrmClientDecorator {
@Override @Override
public String entityName(final Object entity) { public String entityName(final Object entity) {
String name = null; String name = null;
final Set<String> annotations = new HashSet<>();
for (final Annotation annotation : entity.getClass().getDeclaredAnnotations()) {
annotations.add(annotation.annotationType().getName());
}
if (entity instanceof String) { if (entity instanceof String) {
// We were given an entity name, not the entity itself. // We were given an entity name, not the entity itself.
name = (String) entity; name = (String) entity;
} else if (entity.getClass().isAnnotationPresent(Entity.class)) { } else if (annotations.contains("javax.persistence.Entity")) {
// We were given an instance of an entity. // We were given an instance of an entity.
name = entity.getClass().getName(); name = entity.getClass().getName();
} else if (entity instanceof List && ((List) entity).size() > 0) { } else if (entity instanceof List && ((List) entity).size() > 0) {
// We have a list of entities. // We have a list of entities.
name = entityName(((List) entity).get(0)); name = entityName(((List) entity).get(0));
} }
return name; return name;
} }
} }

View File

@ -1,6 +1,6 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate;
import static datadog.trace.instrumentation.hibernate.v4_0.HibernateDecorator.DECORATOR; import static datadog.trace.instrumentation.hibernate.HibernateDecorator.DECORATOR;
import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;

View File

@ -1,4 +1,4 @@
package datadog.trace.instrumentation.hibernate.v4_0; package datadog.trace.instrumentation.hibernate;
import io.opentracing.Scope; import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;

View File

@ -40,8 +40,10 @@ include ':dd-java-agent:instrumentation:elasticsearch:transport-5'
include ':dd-java-agent:instrumentation:elasticsearch:transport-5.3' include ':dd-java-agent:instrumentation:elasticsearch:transport-5.3'
include ':dd-java-agent:instrumentation:elasticsearch:transport-6' include ':dd-java-agent:instrumentation:elasticsearch:transport-6'
include ':dd-java-agent:instrumentation:grpc-1.5' include ':dd-java-agent:instrumentation:grpc-1.5'
include ':dd-java-agent:instrumentation:hibernate-4.0' include ':dd-java-agent:instrumentation:hibernate'
include ':dd-java-agent:instrumentation:hibernate-4.3' include ':dd-java-agent:instrumentation:hibernate:core-3.5'
include ':dd-java-agent:instrumentation:hibernate:core-4.0'
include ':dd-java-agent:instrumentation:hibernate:core-4.3'
include ':dd-java-agent:instrumentation:http-url-connection' include ':dd-java-agent:instrumentation:http-url-connection'
include ':dd-java-agent:instrumentation:hystrix-1.4' include ':dd-java-agent:instrumentation:hystrix-1.4'
include ':dd-java-agent:instrumentation:jax-rs-annotations' include ':dd-java-agent:instrumentation:jax-rs-annotations'