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
LOG4J2-2986: introduce filters.startFrames config element to specifc starting frame(s) during Throwable rendering #460
Conversation
ronosaurus
commented
Jan 17, 2021
- Allow frame (package + method name) specific starting point on stack traces to suppress boilerplate web container, vendor framework, etc frames
- filters.startFrames(frame1,frame2) name selected because its related to filters(package1,package2)
- Suppress web container frames beneath the servlet entry point using filters.startFrame(javax.servlet.http.HttpServlet.service)
- Updated various packages, ignorePackages, hasPackages variables to more descriptive and consistent filterPackages
- Change a few signatures to accept new filterStartFrames parameter alongside filterPackages
- Future: combine both Lists into some kind of FilterConfig object to support future filters and reduce arguments to methods
Keeping fork up to date
…starting frame(s) during Throwable rendering
@ronosaurus I am really not sure how you can do something wrong in a pull request, except maybe commit code for the wrong project or something. Sorry, I am in a busy period at work again and just haven't had much time to look at stuff. |
@ronosaurus, mind updating Keep in mind that this change set needs to be backported to |
private final List<String> filterPackages; | ||
|
||
private final List<String> filterStartFrames; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filterPackages
suppresses the stack frames, whereas filterStartFrames
truncates the stringified stack trace after any occurrence of the given package name. Correct me if I am wrong.
IMHO, filter here is already used in the wrong context. It is generally used for selecting something, not excluding it, e.g., Stream#filter()
. I would have called it discardPackages
. That said, I am probably more than a decade late to share this great wisdom. But maybe we can do something better for filterStartFrames
. Here I see two options:
- Stick to the historical context and go with
filterStartFrames
. - Try to improve the current state with the cost of some inconsistency in the syntax.
discardAfterPackages
?
if (filterStr.length() > 0) { | ||
final String[] array = filterStr.split(Patterns.COMMA_SEPARATOR); | ||
if (array.length > 0) { | ||
packages = new ArrayList<>(array.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this totally discard the initial content of the packages
?
* Common code for extracting packages from "filters(com.example)" and "filters.startFrames(com.example)" | ||
* | ||
*/ | ||
private static List<String> extractFilters(List<String> packages, String option, String conversionWord) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't want to get @garydgregory on your neck, you better have final
modifiers here. 😜
for (String token : array) { | ||
token = token.trim(); | ||
if (token.length() > 0) { | ||
packages.add(token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should move the earlier initialization of packages
here?
final String className = element.getClassName(); | ||
for (final String pkg : ignorePackages) { | ||
if (className.startsWith(pkg)) { | ||
private static boolean elementStartsWith(final StackTraceElement element, final List<String> packagesOrStartFrames, boolean includeMethodName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I am allergic to these kind of unions. Why not simply having two arguments: packages
and startFrames
? (Please mind the final
modifiers.)
@@ -287,7 +287,7 @@ public void testSeparator_getExtendedStackTraceAsString() throws Exception { | |||
final ThrowableProxy proxy = new ThrowableProxy(throwable); | |||
|
|||
final String separator = " | "; | |||
final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString(null, | |||
final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString(null,null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing whitespace.
@@ -132,6 +132,55 @@ public void testFiltering() { | |||
assertTrue(result.contains(" suppressed "), "No suppressed lines"); | |||
} | |||
|
|||
@Test | |||
public void testFiltersStartFrames() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test indeed checks that the given filter pattern should not be found in the output. Though I would also check if the filter is not provided, the pattern indeed can be found.
final LogEvent event = Log4jLogEvent.newBuilder() // | ||
.setLoggerName("testLogger") // | ||
.setLoggerFqcn(this.getClass().getName()) // | ||
.setLevel(Level.DEBUG) // | ||
.setMessage(new SimpleMessage("test exception")) // | ||
.setThrown(thrown).build(); | ||
final StringBuilder sb = new StringBuilder(); | ||
converter.format(event, sb); | ||
final String parentToString = toString(thrown); | ||
// System.out.println(parentToString); | ||
final String result = sb.toString(); | ||
// System.out.println(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind removing these empty comment line starts and commented out lines, please?
String result = sb.toString(); | ||
result = result.replaceAll(" ~?\\[.*\\]", Strings.EMPTY); | ||
final String expected = sw.toString(); //.replaceAll("\r", Strings.EMPTY); | ||
final String expected = toString(parent); //.replaceAll("\r", Strings.EMPTY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the commented out replaceAll
?
assertEquals(expected, result); | ||
} | ||
|
||
private String toString(Throwable ex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind the final
modifier, please.
if (includeMethodName) { // support startFrames | ||
className += "." + element.getMethodName(); | ||
} | ||
for (final String item : packagesOrStartFrames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer an index-based iteration instead if you want to avoid the iterator allocation at each call.
Is anything happening with this? |
Didn't realize this PR is 11 months old. I'm going to close, review the feedback, then eventually submit another PR from more current code. |