Skip to content

Commit

Permalink
count errors handled by exception handler
Browse files Browse the repository at this point in the history
  • Loading branch information
amarziali committed Jan 25, 2024
1 parent 6625916 commit fb5c464
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import datadog.trace.api.InstrumenterConfig;
import datadog.trace.bootstrap.ExceptionLogger;
import java.util.concurrent.atomic.AtomicLong;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.Advice.ExceptionHandler;
import net.bytebuddy.implementation.Implementation;
Expand All @@ -19,8 +20,11 @@ public class ExceptionHandlers {
// Bootstrap ExceptionHandler.class will always be resolvable, so we'll use it in the log name
private static final String HANDLER_NAME = ExceptionLogger.class.getName().replace('.', '/');

private static final ExceptionHandler EXCEPTION_STACK_HANDLER =
new ExceptionHandler.Simple(
public static final class DefaultExceptionHandler extends ExceptionHandler.Simple {
private final AtomicLong errorCounter = new AtomicLong();

public DefaultExceptionHandler() {
super(
new StackManipulation() {
// Pops one Throwable off the stack. Maxes the stack to at least 3.
private final Size size = new StackManipulation.Size(-1, 3);
Expand Down Expand Up @@ -63,9 +67,14 @@ public Size apply(final MethodVisitor mv, final Implementation.Context context)
context.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6);

mv.visitTryCatchBlock(logStart, logEnd, eatException, "java/lang/Throwable");

// stack: (top) throwable
mv.visitLabel(logStart);
// invoke incrementAndGet on our exception counter
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
"datadog/trace/agent/tooling/bytebuddy/ExceptionHandlers",
"countError",
"()V");
// stack: (top) throwable
mv.visitLdcInsn(Type.getType("L" + HANDLER_NAME + ";"));
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
Expand All @@ -82,6 +91,7 @@ public Size apply(final MethodVisitor mv, final Implementation.Context context)
logMethod,
"(Ljava/lang/String;Ljava/lang/Throwable;)V",
true);

if (exitOnFailure) {
mv.visitInsn(Opcodes.ICONST_1);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "exit", "(I)V", false);
Expand All @@ -107,8 +117,22 @@ public Size apply(final MethodVisitor mv, final Implementation.Context context)
return size;
}
});
}

public AtomicLong getErrorCounter() {
return errorCounter;
}
}

@SuppressWarnings("unused")
public static void countError() {
EXCEPTION_STACK_HANDLER.errorCounter.incrementAndGet();
}

private static final DefaultExceptionHandler EXCEPTION_STACK_HANDLER =
new DefaultExceptionHandler();

public static ExceptionHandler defaultExceptionHandler() {
public static DefaultExceptionHandler defaultExceptionHandler() {
return EXCEPTION_STACK_HANDLER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ abstract class BaseExceptionHandlerTest extends DDSpecification {
]
URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null)
when:
loader.loadClass(LoggerFactory.getName())
loader.loadClass(ExceptionHandlers.getName())
then:
thrown ClassNotFoundException

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import datadog.trace.agent.test.timer.TestTimer
import datadog.trace.agent.tooling.AgentInstaller
import datadog.trace.agent.tooling.Instrumenter
import datadog.trace.agent.tooling.TracerInstaller
import datadog.trace.agent.tooling.bytebuddy.ExceptionHandlers
import datadog.trace.agent.tooling.bytebuddy.matcher.GlobalIgnores
import datadog.trace.api.*
import datadog.trace.api.config.GeneralConfig
Expand Down Expand Up @@ -280,6 +281,7 @@ abstract class AgentTestRunner extends DDSpecification implements AgentBuilder.L

@SuppressForbidden
void setupSpec() {

// If this fails, it's likely the result of another test loading Config before it can be
// injected into the bootstrap classpath. If one test extends AgentTestRunner in a module, all tests must extend
assert Config.getClassLoader() == null: "Config must load on the bootstrap classpath."
Expand Down Expand Up @@ -402,7 +404,6 @@ abstract class AgentTestRunner extends DDSpecification implements AgentBuilder.L
protected void configurePreAgent() {
injectSysConfig(TracerConfig.SCOPE_ITERATION_KEEP_ALIVE, "1") // don't let iteration spans linger
injectSysConfig(GeneralConfig.DATA_STREAMS_ENABLED, String.valueOf(isDataStreamsEnabled()))
injectSysConfig(GeneralConfig.INTERNAL_EXIT_ON_FAILURE, "true")
}

void setup() {
Expand Down Expand Up @@ -443,6 +444,7 @@ abstract class AgentTestRunner extends DDSpecification implements AgentBuilder.L
if (forceAppSecActive) {
ActiveSubsystems.APPSEC_ACTIVE = true
}
ExceptionHandlers.defaultExceptionHandler().getErrorCounter().set(0)
}

@Override
Expand Down Expand Up @@ -479,6 +481,7 @@ abstract class AgentTestRunner extends DDSpecification implements AgentBuilder.L
spanFinishLocations.clear()
originalToSpySpan.clear()
}
assert ExceptionHandlers.defaultExceptionHandler().getErrorCounter().get()
}

private void doCheckRepeatedFinish() {
Expand Down

0 comments on commit fb5c464

Please sign in to comment.