Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make hibernate-* indy compatible #11553

Merged
merged 8 commits into from
Aug 22, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.util.VirtualField;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperation;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperationScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionInfo;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
Expand Down Expand Up @@ -50,17 +50,12 @@ public void transform(TypeTransformer transformer) {
public static class CriteriaMethodAdvice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void startMethod(
@Advice.This Criteria criteria,
@Advice.Origin("#m") String name,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {

callDepth = CallDepth.forClass(HibernateOperation.class);
public static HibernateOperationScope startMethod(
@Advice.This Criteria criteria, @Advice.Origin("#m") String name) {

CallDepth callDepth = CallDepth.forClass(HibernateOperation.class);
if (callDepth.getAndIncrement() > 0) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

String entityName = null;
Expand All @@ -73,31 +68,21 @@ public static void startMethod(
SessionInfo sessionInfo = criteriaVirtualField.get(criteria);

Context parentContext = Java8BytecodeBridge.currentContext();
hibernateOperation = new HibernateOperation("Criteria." + name, entityName, sessionInfo);
HibernateOperation hibernateOperation =
new HibernateOperation("Criteria." + name, entityName, sessionInfo);
if (!instrumenter().shouldStart(parentContext, hibernateOperation)) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

context = instrumenter().start(parentContext, hibernateOperation);
scope = context.makeCurrent();
return HibernateOperationScope.startNew(
callDepth, hibernateOperation, parentContext, instrumenter());
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endMethod(
@Advice.Thrown Throwable throwable,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {

if (callDepth.decrementAndGet() > 0) {
return;
}
@Advice.Thrown Throwable throwable, @Advice.Enter HibernateOperationScope enterScope) {

if (scope != null) {
scope.close();
instrumenter().end(context, hibernateOperation, null, throwable);
}
HibernateOperationScope.end(enterScope, instrumenter(), throwable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
import java.util.List;
import net.bytebuddy.matcher.ElementMatcher;

@AutoService(InstrumentationModule.class)
public class HibernateInstrumentationModule extends InstrumentationModule {
public class HibernateInstrumentationModule extends InstrumentationModule
implements ExperimentalInstrumentationModule {

public HibernateInstrumentationModule() {
super("hibernate", "hibernate-3.3");
Expand All @@ -30,6 +32,11 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
"org.hibernate.transaction.JBossTransactionManagerLookup");
}

@Override
public String getModuleGroup() {
return "hibernate";
}

@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.util.VirtualField;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperation;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperationScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionInfo;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
Expand Down Expand Up @@ -50,49 +50,33 @@ public void transform(TypeTransformer transformer) {
public static class QueryMethodAdvice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void startMethod(
@Advice.This Query query,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
public static HibernateOperationScope startMethod(@Advice.This Query query) {

callDepth = CallDepth.forClass(HibernateOperation.class);
CallDepth callDepth = CallDepth.forClass(HibernateOperation.class);
if (callDepth.getAndIncrement() > 0) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, hibernate does a lot of method overload delegation which leads to fairly heavy usage of the CallDepth checks, it may be worth avoiding these allocations and conditionally returning CallDepth or HibernateOperationScope

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've switched to less wrapping in cd99412, should be better now.

Is there a usual benchmark to measure extra allocation created by the instrumentation/sdk ?

}

VirtualField<Query, SessionInfo> queryVirtualField =
VirtualField.find(Query.class, SessionInfo.class);
SessionInfo sessionInfo = queryVirtualField.get(query);

Context parentContext = Java8BytecodeBridge.currentContext();
hibernateOperation =
HibernateOperation hibernateOperation =
new HibernateOperation(getOperationNameForQuery(query.getQueryString()), sessionInfo);
if (!instrumenter().shouldStart(parentContext, hibernateOperation)) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

context = instrumenter().start(parentContext, hibernateOperation);
scope = context.makeCurrent();
return HibernateOperationScope.startNew(
callDepth, hibernateOperation, parentContext, instrumenter());
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endMethod(
@Advice.Thrown Throwable throwable,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
@Advice.Thrown Throwable throwable, @Advice.Enter HibernateOperationScope enterScope) {

if (callDepth.decrementAndGet() > 0) {
return;
}

if (scope != null) {
scope.close();
instrumenter().end(context, hibernateOperation, null, throwable);
}
HibernateOperationScope.end(enterScope, instrumenter(), throwable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.util.VirtualField;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperation;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperationScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionInfo;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
Expand Down Expand Up @@ -92,52 +92,37 @@ public void transform(TypeTransformer transformer) {
public static class SessionMethodAdvice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void startMethod(
public static HibernateOperationScope startMethod(
@Advice.This Object session,
@Advice.Origin("#m") String name,
@Advice.Origin("#d") String descriptor,
@Advice.Argument(0) Object arg0,
@Advice.Argument(value = 1, optional = true) Object arg1,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
@Advice.Argument(value = 1, optional = true) Object arg1) {

callDepth = CallDepth.forClass(HibernateOperation.class);
CallDepth callDepth = CallDepth.forClass(HibernateOperation.class);
if (callDepth.getAndIncrement() > 0) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

Context parentContext = Java8BytecodeBridge.currentContext();
SessionInfo sessionInfo = SessionUtil.getSessionInfo(session);
String entityName =
getEntityName(descriptor, arg0, arg1, EntityNameUtil.bestGuessEntityName(session));
hibernateOperation =
HibernateOperation hibernateOperation =
new HibernateOperation(getSessionMethodOperationName(name), entityName, sessionInfo);
if (!instrumenter().shouldStart(parentContext, hibernateOperation)) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

context = instrumenter().start(parentContext, hibernateOperation);
scope = context.makeCurrent();
return HibernateOperationScope.startNew(
callDepth, hibernateOperation, parentContext, instrumenter());
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endMethod(
@Advice.Thrown Throwable throwable,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {

if (callDepth.decrementAndGet() > 0) {
return;
}
@Advice.Thrown Throwable throwable, @Advice.Enter HibernateOperationScope enterScope) {

if (scope != null) {
scope.close();
instrumenter().end(context, hibernateOperation, null, throwable);
}
HibernateOperationScope.end(enterScope, instrumenter(), throwable);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.util.VirtualField;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperation;
import io.opentelemetry.javaagent.instrumentation.hibernate.HibernateOperationScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionInfo;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
Expand Down Expand Up @@ -49,48 +49,33 @@ public void transform(TypeTransformer transformer) {
public static class TransactionCommitAdvice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void startCommit(
@Advice.This Transaction transaction,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
public static HibernateOperationScope startCommit(@Advice.This Transaction transaction) {

callDepth = CallDepth.forClass(HibernateOperation.class);
CallDepth callDepth = CallDepth.forClass(HibernateOperation.class);
if (callDepth.getAndIncrement() > 0) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

VirtualField<Transaction, SessionInfo> transactionVirtualField =
VirtualField.find(Transaction.class, SessionInfo.class);
SessionInfo sessionInfo = transactionVirtualField.get(transaction);

Context parentContext = Java8BytecodeBridge.currentContext();
hibernateOperation = new HibernateOperation("Transaction.commit", sessionInfo);
HibernateOperation hibernateOperation =
new HibernateOperation("Transaction.commit", sessionInfo);
if (!instrumenter().shouldStart(parentContext, hibernateOperation)) {
return;
return HibernateOperationScope.wrapCallDepth(callDepth);
}

context = instrumenter().start(parentContext, hibernateOperation);
scope = context.makeCurrent();
return HibernateOperationScope.startNew(
callDepth, hibernateOperation, parentContext, instrumenter());
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void endCommit(
@Advice.Thrown Throwable throwable,
@Advice.Local("otelCallDepth") CallDepth callDepth,
@Advice.Local("otelHibernateOperation") HibernateOperation hibernateOperation,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
@Advice.Thrown Throwable throwable, @Advice.Enter HibernateOperationScope enterScope) {

if (callDepth.decrementAndGet() > 0) {
return;
}

if (scope != null) {
scope.close();
instrumenter().end(context, hibernateOperation, null, throwable);
}
HibernateOperationScope.end(enterScope, instrumenter(), throwable);
}
}
}
Loading
Loading