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

Add "caused by" section(s) when forwarding logs #1857

Merged
merged 2 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

package com.nr.agent.instrumentation.log4j1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class Log4j1ExceptionUtil {
public static final int MAX_STACK_SIZE = 300;

Expand All @@ -15,25 +20,19 @@ public static String getErrorStack(Throwable throwable) {
return null;
}

StackTraceElement[] stack = throwable.getStackTrace();
return getErrorStack(stack);
}

public static String getErrorStack(StackTraceElement[] stack) {
return getErrorStack(stack, MAX_STACK_SIZE);
}

public static String getErrorStack(StackTraceElement[] stack, Integer maxStackSize) {
if (stack == null || stack.length == 0) {
return null;
Throwable t = throwable;
List<String> lines = new ArrayList<>();
boolean inner = false;
while (t != null) {
if (inner) {
lines.add(" caused by: " + t.getClass().getName() + ": " + t.getMessage());
}
lines.addAll(stackTracesToStrings(t.getStackTrace()));
t = t.equals(t.getCause()) ? null : t.getCause();
inner = true;
}

StringBuilder stackBuilder = new StringBuilder();
int stackSizeLimit = Math.min(maxStackSize, stack.length);
for (int i = 0; i < stackSizeLimit; i++) {
stackBuilder.append(" at ").append(stack[i].toString()).append("\n");
}
return stackBuilder.toString();
return String.join("\n", lines.subList(0, Math.min(lines.size(), MAX_STACK_SIZE)));
}

public static String getErrorMessage(Throwable throwable) {
Expand All @@ -49,4 +48,16 @@ public static String getErrorClass(Throwable throwable) {
}
return throwable.getClass().getName();
}

private static Collection<String> stackTracesToStrings(StackTraceElement[] stackTraces) {
if (stackTraces == null || stackTraces.length == 0) {
return Collections.emptyList();
}
List<String> lines = new ArrayList<>(stackTraces.length);
for (StackTraceElement e : stackTraces) {
lines.add(" at " + e.toString());
}

return lines;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.nr.agent.instrumentation.log4j1;

import org.junit.Test;

import static org.junit.Assert.*;

public class Log4j1ExceptionUtilTest {
@Test
public void getErrorStack_withThrowable_generatesFullStacktrace() {
assertFalse(Log4j1ExceptionUtil.getErrorStack(createTestException()).contains("caused by: java.lang.Exception: inner exception"));

assertTrue(Log4j1ExceptionUtil.getErrorStack(createTestExceptionWithCausedBy()).contains("caused by: java.lang.Exception: inner exception"));
}

@Test
public void getErrorStack_withNullThrowable_returnsNull() {
assertNull(Log4j1ExceptionUtil.getErrorStack(null));
}

@Test
public void getErrorMessage_withThrowable_returnsErrorMessage() {
assertEquals("test exception", Log4j1ExceptionUtil.getErrorMessage(createTestException()));
}

@Test
public void getErrorMessage_withNullThrowable_returnsNull() {
assertNull(Log4j1ExceptionUtil.getErrorMessage(null));
}

@Test
public void getErrorClass_withThrowable_returnsErrorMessage() {
assertEquals("java.lang.Exception", Log4j1ExceptionUtil.getErrorClass(createTestException()));
}

@Test
public void getErrorClass_withNullThrowable_returnsNull() {
assertNull(Log4j1ExceptionUtil.getErrorClass(null));
}

private Exception createTestException() {
return new Exception("test exception");
}

private Exception createTestExceptionWithCausedBy() {
return new Exception("test exception", new Exception("inner exception"));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.nr.agent.instrumentation.log4j2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class ExceptionUtil {
public static final int MAX_STACK_SIZE = 300;

Expand All @@ -8,42 +13,48 @@ public static boolean isThrowableNull(Throwable throwable) {
}

public static String getErrorStack(Throwable throwable) {
if (isThrowableNull(throwable)) {
if (throwable == null) {
return null;
}

StackTraceElement[] stack = throwable.getStackTrace();
return getErrorStack(stack);
}

public static String getErrorStack(StackTraceElement[] stack) {
return getErrorStack(stack, MAX_STACK_SIZE);
}

public static String getErrorStack(StackTraceElement[] stack, Integer maxStackSize) {
if (stack == null || stack.length == 0) {
return null;
Throwable t = throwable;
List<String> lines = new ArrayList<>();
boolean inner = false;
while (t != null) {
if (inner) {
lines.add(" caused by: " + t.getClass().getName() + ": " + t.getMessage());
}
lines.addAll(stackTracesToStrings(t.getStackTrace()));
t = t.equals(t.getCause()) ? null : t.getCause();
inner = true;
}

StringBuilder stackBuilder = new StringBuilder();
int stackSizeLimit = Math.min(maxStackSize, stack.length);
for (int i = 0; i < stackSizeLimit; i++) {
stackBuilder.append(" at ").append(stack[i].toString()).append("\n");
}
return stackBuilder.toString();
return String.join("\n", lines.subList(0, Math.min(lines.size(), MAX_STACK_SIZE)));
}

public static String getErrorMessage(Throwable throwable) {
if (isThrowableNull(throwable)) {
if (throwable == null) {
return null;
}
return throwable.getMessage();
}

public static String getErrorClass(Throwable throwable) {
if (isThrowableNull(throwable)) {
if (throwable == null) {
return null;
}
return throwable.getClass().getName();
}

private static Collection<String> stackTracesToStrings(StackTraceElement[] stackTraces) {
if (stackTraces == null || stackTraces.length == 0) {
return Collections.emptyList();
}
List<String> lines = new ArrayList<>(stackTraces.length);
for (StackTraceElement e : stackTraces) {
lines.add(" at " + e.toString());
}

return lines;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@

public class ExceptionUtilTest {

@Test
public void getErrorStack_withThrowable_generatesFullStacktrace() {
assertFalse(ExceptionUtil.getErrorStack(createTestException()).contains("caused by: java.lang.Exception: inner exception"));

assertTrue(ExceptionUtil.getErrorStack(createTestExceptionWithCausedBy()).contains("caused by: java.lang.Exception: inner exception"));
}

@Test
public void getErrorStack_withNullThrowable_returnsNull() {
assertNull(ExceptionUtil.getErrorStack(null));
}

@Test
public void testIsThrowableNull() {
Throwable nullThrowable = null;
Expand All @@ -19,43 +31,30 @@ public void testIsThrowableNull() {
}

@Test
public void testGetErrorStack() {
int maxStackSize = 3;
StackTraceElement stackTraceElement1 = new StackTraceElement("Class1", "method1", "File1", 1);
StackTraceElement stackTraceElement2 = new StackTraceElement("Class2", "method2", "File2", 2);
StackTraceElement stackTraceElement3 = new StackTraceElement("Class3", "method3", "File3", 3);
StackTraceElement stackTraceElement4 = new StackTraceElement("Class4", "method4", "File4", 4);
StackTraceElement stackTraceElement5 = new StackTraceElement("Class5", "method5", "File5", 5);
StackTraceElement[] stack = new StackTraceElement[] { stackTraceElement1, stackTraceElement2, stackTraceElement3, stackTraceElement4,
stackTraceElement5 };
String errorStack = ExceptionUtil.getErrorStack(stack, maxStackSize);

// Processed stack should be limited to only the first three lines
assertTrue(errorStack.contains(stackTraceElement1.toString()));
assertTrue(errorStack.contains(stackTraceElement2.toString()));
assertTrue(errorStack.contains(stackTraceElement3.toString()));
// Processed stack should omit the last two lines
assertFalse(errorStack.contains(stackTraceElement4.toString()));
assertFalse(errorStack.contains(stackTraceElement5.toString()));
public void getErrorMessage_withThrowable_returnsErrorMessage() {
assertEquals("test exception", ExceptionUtil.getErrorMessage(createTestException()));
}

@Test
public void testGetErrorMessage() {
String expectedMessage = "Hi";
Throwable nullThrowable = null;
Throwable nonNullThrowable = new Throwable(expectedMessage);
public void getErrorMessage_withNullThrowable_returnsNull() {
assertNull(ExceptionUtil.getErrorMessage(null));
}

assertNull(ExceptionUtil.getErrorMessage(nullThrowable));
assertEquals(expectedMessage, ExceptionUtil.getErrorMessage(nonNullThrowable));
@Test
public void getErrorClass_withThrowable_returnsErrorMessage() {
assertEquals("java.lang.Exception", ExceptionUtil.getErrorClass(createTestException()));
}

@Test
public void testGetErrorClass() {
String expectedExceptionClass = "java.lang.RuntimeException";
Throwable nullThrowable = null;
RuntimeException runtimeException = new RuntimeException("Hi");
public void getErrorClass_withNullThrowable_returnsNull() {
assertNull(ExceptionUtil.getErrorClass(null));
}

private Exception createTestException() {
return new Exception("test exception");
}

assertNull(ExceptionUtil.getErrorClass(nullThrowable));
assertEquals(expectedExceptionClass, ExceptionUtil.getErrorClass(runtimeException));
private Exception createTestExceptionWithCausedBy() {
return new Exception("test exception", new Exception("inner exception"));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.nr.agent.instrumentation.log4j2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class ExceptionUtil {
public static final int MAX_STACK_SIZE = 300;

Expand All @@ -8,42 +13,48 @@ public static boolean isThrowableNull(Throwable throwable) {
}

public static String getErrorStack(Throwable throwable) {
if (isThrowableNull(throwable)) {
if (throwable == null) {
return null;
}

StackTraceElement[] stack = throwable.getStackTrace();
return getErrorStack(stack);
}

public static String getErrorStack(StackTraceElement[] stack) {
return getErrorStack(stack, MAX_STACK_SIZE);
}

public static String getErrorStack(StackTraceElement[] stack, Integer maxStackSize) {
if (stack == null || stack.length == 0) {
return null;
Throwable t = throwable;
List<String> lines = new ArrayList<>();
boolean inner = false;
while (t != null) {
if (inner) {
lines.add(" caused by: " + t.getClass().getName() + ": " + t.getMessage());
}
lines.addAll(stackTracesToStrings(t.getStackTrace()));
t = t.equals(t.getCause()) ? null : t.getCause();
inner = true;
}

StringBuilder stackBuilder = new StringBuilder();
int stackSizeLimit = Math.min(maxStackSize, stack.length);
for (int i = 0; i < stackSizeLimit; i++) {
stackBuilder.append(" at ").append(stack[i].toString()).append("\n");
}
return stackBuilder.toString();
return String.join("\n", lines.subList(0, Math.min(lines.size(), MAX_STACK_SIZE)));
}

public static String getErrorMessage(Throwable throwable) {
if (isThrowableNull(throwable)) {
if (throwable == null) {
return null;
}
return throwable.getMessage();
}

public static String getErrorClass(Throwable throwable) {
if (isThrowableNull(throwable)) {
if (throwable == null) {
return null;
}
return throwable.getClass().getName();
}

private static Collection<String> stackTracesToStrings(StackTraceElement[] stackTraces) {
if (stackTraces == null || stackTraces.length == 0) {
return Collections.emptyList();
}
List<String> lines = new ArrayList<>(stackTraces.length);
for (StackTraceElement e : stackTraces) {
lines.add(" at " + e.toString());
}

return lines;
}
}
Loading
Loading