Skip to content

Consolidate stack trace rendering in Pattern Layout #2691

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

Merged
merged 81 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
7d7c559
fix: LOG4J2-3627 and gh issue 1729
alan0428a Jun 25, 2024
9f8af82
update naming and add final
alan0428a Jun 26, 2024
dbefb4f
add final
alan0428a Jun 26, 2024
66212e0
update core version to 3.0.0
alan0428a Jun 26, 2024
f7e1632
Merge branch 'apache:2.x' into 2.x
alan0428a Jun 26, 2024
de83163
update as per comment
alan0428a Jun 26, 2024
38cd7fe
add StringBuilders
alan0428a Jun 26, 2024
26dbdff
update
alan0428a Jun 26, 2024
8d3f7e4
add tests
alan0428a Jun 27, 2024
f17e6da
Fix OSGi failures
ppkarwasz Jun 27, 2024
42459ed
create tests programmatically
alan0428a Jun 28, 2024
659f7e5
fix style
alan0428a Jun 28, 2024
efc126a
update as comment
alan0428a Jul 3, 2024
e4fa223
Add ThrowableRenderer
alan0428a Jul 12, 2024
4016239
Add ThrowableRenderer.Context and update ThrowablePatternConverter su…
alan0428a Jul 12, 2024
0cd5f6b
Make ThrowableRenderer instance variable of ThrowablePatternConverter
alan0428a Jul 13, 2024
4e89d67
add RootThrowableRenderer and add missing "at"
alan0428a Jul 13, 2024
0975f5d
Fix ThrowableRenderer
alan0428a Jul 16, 2024
cf28898
Remove redundant method
alan0428a Jul 16, 2024
ca14ed1
Merge methods
alan0428a Jul 16, 2024
ca8ab05
Visibility related cosmetic changes to `ThrowableRender` (#2691)
vy Jul 16, 2024
7e57942
Arrange method order in `ThrowableRender` (#2691)
vy Jul 16, 2024
ce80b72
First (untested) draft of `ExtendedThrowableRenderer` (#2691)
vy Jul 17, 2024
4962f43
Fix import
alan0428a Jul 18, 2024
44d6c51
add render about suppressedThrowables
alan0428a Aug 8, 2024
54c8e2b
update for %xEx
alan0428a Aug 8, 2024
8bf1d29
update render
alan0428a Aug 12, 2024
2ec0bc4
Inline `TAB`
vy Aug 12, 2024
1b16ec1
Add comments
vy Aug 12, 2024
75e24b5
Rename `WRAPPED_BY_LABEL` to `WRAPPED_BY_CAPTION`
vy Aug 12, 2024
b4630b9
Make `ThrowableRenderer` more strict
vy Aug 12, 2024
cf55e42
Fix stack trace indentation in `ExtendedThrowableRenderer`
vy Aug 12, 2024
a3ccf35
Fix map key conflict in `ExtendedThrowableRenderer`
vy Aug 12, 2024
91e6110
Fix Spotless failures
vy Aug 12, 2024
f91620a
Add `ThrowableTestMain` test application
vy Aug 12, 2024
7d9e87b
fix rEx
alan0428a Aug 12, 2024
4b5325a
fix formatting
alan0428a Aug 12, 2024
2009888
Update `ThrowableTestMain`
vy Aug 12, 2024
ede1cd9
add visited for rendering
alan0428a Aug 13, 2024
bd4e2f2
set %xEx using ExtendedThrowableRenderer
alan0428a Aug 13, 2024
1e8fae1
Merge branch '2.x' of github.com:alan0428a/logging-log4j2 into 2.x
alan0428a Aug 13, 2024
36a812b
Merge remote-tracking branch 'origin/2.x' into 2.x-alan
vy Aug 13, 2024
c489190
Fix `bnd-baseline` failures
vy Aug 13, 2024
2afc7fa
fix tests and add suffix for every line
alan0428a Aug 13, 2024
0d6aedc
update suffix and separator
alan0428a Aug 14, 2024
1e3dbcf
Simplify `ThrowablePatternConverter` and document the awesome Log4j f…
vy Aug 14, 2024
deb2513
Fix Spotless failures
vy Aug 14, 2024
e15c48f
Fix `bnd-baseline` failures
vy Aug 14, 2024
483ed39
fix tests related to separator
alan0428a Aug 15, 2024
5bee486
add tests
alan0428a Aug 17, 2024
b3d53ca
Deprecate ThrowableProxy related classes and tests
alan0428a Aug 17, 2024
c0b06b6
add golden samples
alan0428a Aug 21, 2024
08ba30d
fix tests
alan0428a Aug 21, 2024
feea2db
Merge remote-tracking branch 'origin/2.x' into 2.x-alan
vy Sep 19, 2024
0a36a46
Add tests
vy Sep 23, 2024
dc4f8a2
Merge remote-tracking branch 'origin/2.x' into 2.x-alan
vy Sep 23, 2024
3fa309d
Fix `bnd-baseline` failures
vy Sep 23, 2024
9f9da1a
Remove deprecated `ThrowableFullTest`
vy Sep 23, 2024
97fd136
Add changelog entries
vy Sep 23, 2024
9e55f5c
Revert redundant `ThrowableProxy` and `ThrowableProxyRenderer` fixes
vy Sep 24, 2024
2e47d49
remove unused tests
alan0428a Sep 24, 2024
27d4663
fix: tests
alan0428a Sep 24, 2024
980da42
style: fix style
alan0428a Sep 24, 2024
1728fa9
tests: fix line separator
alan0428a Sep 25, 2024
d07e14a
Rework `ThrowablePatternConverter` et al.
vy Sep 25, 2024
be1639e
Merge remote-tracking branch 'alan0428a/2.x' into 2.x-alan
vy Sep 25, 2024
f3b13af
Revamp tests
vy Sep 26, 2024
7108d36
Improve docs
vy Sep 26, 2024
7161ed7
Merge remote-tracking branch 'origin/2.x' into 2.x-alan
vy Sep 26, 2024
8c57109
Remove redundant changelog entries
vy Sep 26, 2024
2cf6d36
Add circular reference support
vy Sep 27, 2024
e52fe1f
Fix newline handling in tests
vy Sep 27, 2024
7719098
Improve changelog
vy Sep 27, 2024
e4f34b6
Merge remote-tracking branch 'origin/2.x' into 2.x-alan
vy Sep 27, 2024
f3e89d3
Remove redundant `toString()` calls
vy Sep 29, 2024
b788206
Test module name serialization (LOG4J2-2170)
vy Sep 30, 2024
cf42de7
Merge remote-tracking branch 'origin/2.x' into 2.x-alan
vy Sep 30, 2024
d853ec0
Update changelog (LOG4J2-2170)
vy Sep 30, 2024
a419ea8
Normalize extended stack trace suffixes
vy Sep 30, 2024
beede50
Add `ThrowVsReturnBenchmark`
vy Oct 1, 2024
663a9e7
Fix Spotless failures
vy Oct 1, 2024
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
5 changes: 5 additions & 0 deletions log4j-api-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<scope>test</scope>
</dependency>
<!-- Used by ServiceLoaderUtilTest -->
<dependency>
<groupId>org.osgi</groupId>
Expand Down
5 changes: 5 additions & 0 deletions log4j-core-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@
<artifactId>javax.jms-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
Expand Down
155 changes: 155 additions & 0 deletions log4j-core-test/src/test/java/foo/TestFriendlyException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package foo;

import static org.assertj.core.api.Assertions.assertThat;

import java.net.Socket;
import java.util.Arrays;
import java.util.stream.Stream;
import org.apache.logging.log4j.util.Constants;

/**
* A testing friendly exception featuring
* <ul>
* <li>Distinct localized message</li>
* <li>Non-Log4j package origin<sup>1</sup></li>
* <li>Sufficient causal chain depth</li>
* <li>Cyclic causal chain</li>
* <li>Suppressed exceptions</li>
* <li>Clutter-free stack trace (i.e., elements from JUnit, JDK, etc.)</li>
* <li>Stack trace elements from named modules<sup>2</sup></li>
* </ul>
* <p>
* <sup>1</sup> Helps with observing stack trace manipulation effects of Log4j.
* </p>
* <p>
* <sup>2</sup> Helps with testing module name serialization.
* </p>
*/
public final class TestFriendlyException extends RuntimeException {

static {
// Ensure the distinct packaging
assertThat(TestFriendlyException.class.getPackage().getName()).doesNotStartWith("org.apache");
}

public static final StackTraceElement NAMED_MODULE_STACK_TRACE_ELEMENT = namedModuleStackTraceElement();

@SuppressWarnings("resource")
private static StackTraceElement namedModuleStackTraceElement() {
try {
new Socket("0.0.0.0", -1);
} catch (final Exception error) {
final StackTraceElement[] stackTraceElements = error.getStackTrace();
final String socketClassName = Socket.class.getCanonicalName();
for (final StackTraceElement stackTraceElement : stackTraceElements) {
if (stackTraceElement.getClassName().equals(socketClassName)) {
if (Constants.JAVA_MAJOR_VERSION > 8) {
final String stackTraceElementString = stackTraceElement.toString();
assertThat(stackTraceElementString).startsWith("java.base/");
}
return stackTraceElement;
}
}
}
throw new IllegalStateException("should not have reached here");
}

private static final String[] EXCLUDED_CLASS_NAME_PREFIXES = {
"java.lang", "jdk.internal", "org.junit", "sun.reflect"
};

public static final TestFriendlyException INSTANCE = create("r", 0, 2, new boolean[] {false}, new boolean[] {true});

private static TestFriendlyException create(
final String name,
final int depth,
final int maxDepth,
final boolean[] circular,
final boolean[] namedModuleAllowed) {
final TestFriendlyException error = new TestFriendlyException(name, namedModuleAllowed);
if (depth < maxDepth) {
final TestFriendlyException cause = create(name + "_c", depth + 1, maxDepth, circular, namedModuleAllowed);
error.initCause(cause);
final TestFriendlyException suppressed =
create(name + "_s", depth + 1, maxDepth, circular, namedModuleAllowed);
error.addSuppressed(suppressed);
final boolean circularAllowed = depth + 1 == maxDepth && !circular[0];
if (circularAllowed) {
cause.initCause(error);
suppressed.initCause(error);
circular[0] = true;
}
}
return error;
}

private TestFriendlyException(final String message, final boolean[] namedModuleAllowed) {
super(message);
removeExcludedStackTraceElements(namedModuleAllowed);
}

private void removeExcludedStackTraceElements(final boolean[] namedModuleAllowed) {
final StackTraceElement[] oldStackTrace = getStackTrace();
final boolean[] seenExcludedStackTraceElement = {false};
final StackTraceElement[] newStackTrace = Arrays.stream(oldStackTrace)
.flatMap(stackTraceElement ->
mapStackTraceElement(stackTraceElement, namedModuleAllowed, seenExcludedStackTraceElement))
.toArray(StackTraceElement[]::new);
setStackTrace(newStackTrace);
}

private static Stream<StackTraceElement> mapStackTraceElement(
final StackTraceElement stackTraceElement,
final boolean[] namedModuleAllowed,
final boolean[] seenExcludedStackTraceElement) {
final Stream<StackTraceElement> filteredStackTraceElement =
filterStackTraceElement(stackTraceElement, seenExcludedStackTraceElement);
final Stream<StackTraceElement> javaBaseIncludedStackTraceElement =
namedModuleIncludedStackTraceElement(namedModuleAllowed);
return Stream.concat(javaBaseIncludedStackTraceElement, filteredStackTraceElement);
}

private static Stream<StackTraceElement> filterStackTraceElement(
final StackTraceElement stackTraceElement, final boolean[] seenExcludedStackTraceElement) {
if (seenExcludedStackTraceElement[0]) {
return Stream.empty();
}
final String className = stackTraceElement.getClassName();
for (final String excludedClassNamePrefix : EXCLUDED_CLASS_NAME_PREFIXES) {
if (className.startsWith(excludedClassNamePrefix)) {
seenExcludedStackTraceElement[0] = true;
return Stream.empty();
}
}
return Stream.of(stackTraceElement);
}

private static Stream<StackTraceElement> namedModuleIncludedStackTraceElement(final boolean[] namedModuleAllowed) {
if (!namedModuleAllowed[0]) {
return Stream.of();
}
namedModuleAllowed[0] = false;
return Stream.of(NAMED_MODULE_STACK_TRACE_ELEMENT);
}

@Override
public String getLocalizedMessage() {
return getMessage() + " [localized]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -63,15 +64,20 @@ public void testParametersAreNotLeaked() throws Exception {
final String line1 = reader.readLine();
final String line2 = reader.readLine();
final String line3 = reader.readLine();
// line4 is empty line because of the line separator after throwable pattern
final String line4 = reader.readLine();
final String line5 = reader.readLine();
final String line6 = reader.readLine();
final String line7 = reader.readLine();
reader.close();
file.delete();
assertThat(line1, containsString("Message with parameter paramValue"));
assertThat(line2, containsString("paramValue"));
assertThat(line3, containsString("paramValue"));
assertThat(line4, containsString("paramValue"));
assertNull(line5, "Expected only three lines");
assertThat(line4, is(""));
assertThat(line5, containsString("paramValue"));
assertThat(line6, is(""));
assertNull(line7, "Expected only six lines");
final GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
gcHelper.run();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class RollingAppenderOnStartupTest {
@BeforeAll
public static void setup() throws Exception {
final Path target = loggingPath.resolve(FILENAME);
Files.copy(Paths.get(SOURCE, FILENAME), target, StandardCopyOption.COPY_ATTRIBUTES);
Files.copy(Paths.get(SOURCE, FILENAME), target, StandardCopyOption.REPLACE_EXISTING);
final FileTime newTime = FileTime.from(Instant.now().minus(1, ChronoUnit.DAYS));
final BasicFileAttributeView attrs = Files.getFileAttributeView(target, BasicFileAttributeView.class);
attrs.setTimes(newTime, newTime, newTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void testNestedLoggingInLastArgument() throws Exception {
final Set<String> lines2 = readUniqueLines(file2);

assertEquals("Expected the same data from both appenders", lines1, lines2);
assertEquals(2, lines1.size());
assertEquals(3, lines1.size());
assertTrue(lines1.contains("INFO NestedLoggingFromThrowableMessageTest Logging in getMessage "));
assertTrue(lines1.contains("ERROR NestedLoggingFromThrowableMessageTest Test message"));
}
Expand Down

This file was deleted.

Loading