Skip to content

Commit 475b883

Browse files
authored
Removing abs_path and adding module to serialized stack frames (#659)
1 parent ee727ac commit 475b883

File tree

3 files changed

+73
-9
lines changed

3 files changed

+73
-9
lines changed

apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonSerializer.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,14 @@ public String toJsonString(final ErrorCapture error) {
327327
return s;
328328
}
329329

330+
public String toJsonString(final StackTraceElement stackTraceElement) {
331+
jw.reset();
332+
serializeStackTraceElement(stackTraceElement);
333+
final String s = jw.toString();
334+
jw.reset();
335+
return s;
336+
}
337+
330338
public String toString() {
331339
return jw.toString();
332340
}
@@ -656,10 +664,20 @@ private void serializeStackTraceElement(StackTraceElement stacktrace) {
656664
writeField("function", stacktrace.getMethodName());
657665
writeField("library_frame", isLibraryFrame(stacktrace.getClassName()));
658666
writeField("lineno", stacktrace.getLineNumber());
659-
writeLastField("abs_path", stacktrace.getClassName());
667+
serializeStackFrameModule(stacktrace.getClassName());
660668
jw.writeByte(OBJECT_END);
661669
}
662670

671+
private void serializeStackFrameModule(final String fullyQualifiedClassName) {
672+
writeFieldName("module");
673+
replaceBuilder.setLength(0);
674+
final int lastDotIndex = fullyQualifiedClassName.lastIndexOf('.');
675+
if (lastDotIndex > 0) {
676+
replaceBuilder.append(fullyQualifiedClassName, 0, lastDotIndex);
677+
}
678+
writeStringBuilderValue(replaceBuilder, jw);
679+
}
680+
663681
private boolean isLibraryFrame(String className) {
664682
for (String applicationPackage : stacktraceConfiguration.getApplicationPackages()) {
665683
if (className.startsWith(applicationPackage)) {

apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import static org.assertj.core.api.Assertions.assertThat;
5353
import static org.assertj.core.api.SoftAssertions.assertSoftly;
5454
import static org.mockito.Mockito.mock;
55+
import static org.mockito.Mockito.when;
5556

5657

5758
class DslJsonSerializerTest {
@@ -61,7 +62,9 @@ class DslJsonSerializerTest {
6162

6263
@BeforeEach
6364
void setUp() {
64-
serializer = new DslJsonSerializer(mock(StacktraceConfiguration.class));
65+
StacktraceConfiguration stacktraceConfiguration = mock(StacktraceConfiguration.class);
66+
when(stacktraceConfiguration.getStackTraceLimit()).thenReturn(15);
67+
serializer = new DslJsonSerializer(stacktraceConfiguration);
6568
objectMapper = new ObjectMapper();
6669
}
6770

@@ -97,7 +100,15 @@ void testErrorSerialization() throws IOException {
97100
assertThat(context.get("tags").get("foo").textValue()).isEqualTo("bar");
98101
JsonNode exception = errorTree.get("exception");
99102
assertThat(exception.get("message").textValue()).isEqualTo("test");
100-
assertThat(exception.get("stacktrace")).isNotNull();
103+
JsonNode stacktrace = exception.get("stacktrace");
104+
assertThat(stacktrace).isNotNull();
105+
assertThat(stacktrace).hasSize(15);
106+
JsonNode stackTraceElement = stacktrace.get(0);
107+
assertThat(stackTraceElement.get("filename")).isNotNull();
108+
assertThat(stackTraceElement.get("function")).isNotNull();
109+
assertThat(stackTraceElement.get("library_frame")).isNotNull();
110+
assertThat(stackTraceElement.get("lineno")).isNotNull();
111+
assertThat(stackTraceElement.get("module")).isNotNull();
101112
assertThat(exception.get("type").textValue()).isEqualTo(Exception.class.getName());
102113
assertThat(errorTree.get("transaction").get("sampled").booleanValue()).isTrue();
103114
assertThat(errorTree.get("transaction").get("type").textValue()).isEqualTo("test-type");

apm-agent-core/src/test/java/org/example/stacktrace/StacktraceSerializationTest.java

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,17 @@ void setUp() throws IOException {
7373
void fillStackTrace() {
7474
assertThat(stacktrace).isNotEmpty();
7575
// even though the stacktrace is captured within our tracer class, the first method should be getStackTrace
76-
assertThat(stacktrace.get(0).get("abs_path").textValue()).doesNotStartWith("co.elastic");
76+
assertThat(stacktrace.get(0).get("module").textValue()).doesNotStartWith("co.elastic");
7777
assertThat(stacktrace.get(0).get("function").textValue()).isEqualTo("getStackTrace");
78-
assertThat(stacktrace.stream().filter(st -> st.get("abs_path").textValue().endsWith("StacktraceSerializationTest"))).isNotEmpty();
78+
assertThat(stacktrace.stream().filter(st -> st.get("filename").textValue().equals("StacktraceSerializationTest.java"))).isNotEmpty();
7979
}
8080

8181
@Test
8282
void testAppFrame() throws Exception {
8383
when(stacktraceConfiguration.getApplicationPackages()).thenReturn(Collections.singletonList("org.example.stacktrace"));
8484
stacktrace = getStackTrace();
8585
Optional<JsonNode> thisMethodsFrame = stacktrace.stream()
86-
.filter(st -> st.get("abs_path").textValue().startsWith(getClass().getName()))
86+
.filter(st -> st.get("module").textValue().equals(getClass().getPackageName()))
8787
.findAny();
8888
assertThat(thisMethodsFrame).isPresent();
8989
assertThat(thisMethodsFrame.get().get("library_frame").booleanValue()).isFalse();
@@ -92,7 +92,7 @@ void testAppFrame() throws Exception {
9292
@Test
9393
void testNoAppFrame() {
9494
Optional<JsonNode> thisMethodsFrame = stacktrace.stream()
95-
.filter(st -> st.get("abs_path").textValue().startsWith(getClass().getName()))
95+
.filter(st -> st.get("module").textValue().startsWith(getClass().getPackageName()))
9696
.findAny();
9797
assertThat(thisMethodsFrame).isPresent();
9898
assertThat(thisMethodsFrame.get().get("library_frame").booleanValue()).isTrue();
@@ -106,11 +106,46 @@ void testFileNamePresent() {
106106
@Test
107107
void testNoInternalStackFrames() {
108108
assertSoftly(softly -> {
109-
softly.assertThat(stacktrace.stream().filter(st -> st.get("abs_path").textValue().contains("java.lang.reflect."))).isEmpty();
110-
softly.assertThat(stacktrace.stream().filter(st -> st.get("abs_path").textValue().contains("sun."))).isEmpty();
109+
softly.assertThat(stacktrace.stream().filter(st -> st.get("module").textValue().startsWith("java.lang."))).isEmpty();
110+
softly.assertThat(stacktrace.stream().filter(st -> st.get("module").textValue().startsWith("sun."))).isEmpty();
111111
});
112112
}
113113

114+
@Test
115+
void testStackTraceElementSerialization() throws IOException {
116+
when(stacktraceConfiguration.getApplicationPackages()).thenReturn(Collections.singletonList("co.elastic.apm"));
117+
118+
StackTraceElement stackTraceElement = new StackTraceElement("co.elastic.apm.test.TestClass",
119+
"testMethod", "TestClass.java", 34);
120+
String json = serializer.toJsonString(stackTraceElement);
121+
JsonNode stackTraceElementParsed = objectMapper.readTree(json);
122+
assertThat(stackTraceElementParsed.get("filename").textValue()).isEqualTo("TestClass.java");
123+
assertThat(stackTraceElementParsed.get("function").textValue()).isEqualTo("testMethod");
124+
assertThat(stackTraceElementParsed.get("library_frame").booleanValue()).isFalse();
125+
assertThat(stackTraceElementParsed.get("lineno").intValue()).isEqualTo(34);
126+
assertThat(stackTraceElementParsed.get("module").textValue()).isEqualTo("co.elastic.apm.test");
127+
128+
stackTraceElement = new StackTraceElement("co.elastic.TestClass",
129+
"testMethod", "TestClass.java", 34);
130+
json = serializer.toJsonString(stackTraceElement);
131+
stackTraceElementParsed = objectMapper.readTree(json);
132+
assertThat(stackTraceElementParsed.get("library_frame").booleanValue()).isTrue();
133+
assertThat(stackTraceElementParsed.get("module").textValue()).isEqualTo("co.elastic");
134+
135+
stackTraceElement = new StackTraceElement(".TestClass",
136+
"testMethod", "TestClass.java", 34);
137+
json = serializer.toJsonString(stackTraceElement);
138+
stackTraceElementParsed = objectMapper.readTree(json);
139+
assertThat(stackTraceElementParsed.get("module").textValue()).isEqualTo("");
140+
141+
stackTraceElement = new StackTraceElement("TestClass",
142+
"testMethod", "TestClass.java", 34);
143+
json = serializer.toJsonString(stackTraceElement);
144+
stackTraceElementParsed = objectMapper.readTree(json);
145+
assertThat(stackTraceElementParsed.get("module").textValue()).isEqualTo("");
146+
}
147+
148+
114149
private List<JsonNode> getStackTrace() throws IOException {
115150
final Transaction transaction = tracer.startTransaction(TraceContext.asRoot(), null, getClass().getClassLoader());
116151
final Span span = transaction.createSpan();

0 commit comments

Comments
 (0)