Skip to content

Commit e7ad9de

Browse files
authored
4.x: JSON Formatter for JUL (#9260)
JSON Formatter for JUL and tests. A fix of escaping when writing in HSON. Switched one packaging test to use JSON format. Signed-off-by: Tomas Langer <[email protected]>
1 parent c91a232 commit e7ad9de

File tree

9 files changed

+539
-52
lines changed

9 files changed

+539
-52
lines changed

logging/jul/etc/spotbugs/exclude.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
4-
Copyright (c) 2021 Oracle and/or its affiliates.
4+
Copyright (c) 2021, 2024 Oracle and/or its affiliates.
55
66
Licensed under the Apache License, Version 2.0 (the "License");
77
you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
2525
<Match>
2626
<!-- Stack trace is written to log file -->
2727
<Class name="io.helidon.logging.jul.HelidonFormatter"/>
28-
<Method name="formatRow"/>
28+
<Method name="parameters"/>
2929
<Bug pattern="INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE"/>
3030
</Match>
3131

logging/jul/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
<groupId>io.helidon.common</groupId>
4545
<artifactId>helidon-common</artifactId>
4646
</dependency>
47+
<dependency>
48+
<groupId>io.helidon.metadata</groupId>
49+
<artifactId>helidon-metadata-hson</artifactId>
50+
</dependency>
4751
<dependency>
4852
<groupId>org.junit.jupiter</groupId>
4953
<artifactId>junit-jupiter-api</artifactId>
@@ -54,6 +58,11 @@
5458
<artifactId>hamcrest-all</artifactId>
5559
<scope>test</scope>
5660
</dependency>
61+
<dependency>
62+
<groupId>io.helidon.common.testing</groupId>
63+
<artifactId>helidon-common-testing-junit5</artifactId>
64+
<scope>test</scope>
65+
</dependency>
5766
</dependencies>
5867

5968

logging/jul/src/main/java/io/helidon/logging/jul/HelidonConsoleHandler.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020 Oracle and/or its affiliates.
2+
* Copyright (c) 2020, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717
package io.helidon.logging.jul;
1818

1919
import java.util.logging.Level;
20+
import java.util.logging.LogManager;
2021
import java.util.logging.LogRecord;
2122
import java.util.logging.StreamHandler;
2223

@@ -35,9 +36,15 @@ public class HelidonConsoleHandler extends StreamHandler {
3536
* </ul>.
3637
*/
3738
public HelidonConsoleHandler() {
39+
super();
3840
setOutputStream(System.out);
39-
setLevel(Level.ALL); // Handlers should not filter, loggers should
40-
setFormatter(new HelidonFormatter());
41+
if (LogManager.getLogManager().getProperty(HelidonConsoleHandler.class.getName() + ".level") == null) {
42+
setLevel(Level.ALL); // Handlers should not filter, loggers should
43+
}
44+
// only set this if none set
45+
if (LogManager.getLogManager().getProperty(HelidonConsoleHandler.class.getName() + ".formatter") == null) {
46+
setFormatter(new HelidonFormatter());
47+
}
4148
}
4249

4350
@Override

logging/jul/src/main/java/io/helidon/logging/jul/HelidonFormatter.java

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021 Oracle and/or its affiliates.
2+
* Copyright (c) 2020, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,12 +36,13 @@
3636
* It also supports replacement of {@code "!thread!"} with the current thread.
3737
*/
3838
public class HelidonFormatter extends SimpleFormatter {
39-
private static final String THREAD = "thread";
40-
private static final String THREAD_TOKEN = "!" + THREAD + "!";
41-
private static final Pattern THREAD_PATTERN = Pattern.compile(THREAD_TOKEN);
42-
private static final Pattern X_VALUE = Pattern.compile("(\\s?%X\\{)(\\S*?)(})");
43-
private static final Map<String, Pattern> PATTERN_CACHE = new HashMap<>();
44-
private static final String JUL_FORMAT_PROP_KEY = "java.util.logging.SimpleFormatter.format";
39+
static final String THREAD = "thread";
40+
static final String THREAD_TOKEN = "!" + THREAD + "!";
41+
static final Pattern THREAD_PATTERN = Pattern.compile(THREAD_TOKEN);
42+
static final Pattern X_VALUE = Pattern.compile("(\\s?%X\\{)(\\S*?)(})");
43+
static final Map<String, Pattern> PATTERN_CACHE = new HashMap<>();
44+
static final String JUL_FORMAT_PROP_KEY = "java.util.logging.SimpleFormatter.format";
45+
4546
private final String format = LogManager.getLogManager().getProperty(JUL_FORMAT_PROP_KEY);
4647
private final Set<String> parsedProps = new HashSet<>();
4748
private final boolean thread;
@@ -57,28 +58,22 @@ public HelidonFormatter() {
5758
}
5859
}
5960

60-
@Override
61-
public String format(LogRecord record) {
62-
String message = thread ? thread() : format;
63-
for (String parsedKey : parsedProps) {
64-
String value = HelidonMdc.get(parsedKey).orElse("");
65-
message = PATTERN_CACHE.computeIfAbsent(parsedKey, key -> Pattern.compile("%X\\{" + key + "}"))
66-
.matcher(message).replaceAll(value);
67-
}
68-
return formatRow(record, message);
69-
}
70-
71-
private String thread() {
61+
/*
62+
Replace the thread pattern in the format with the current thread value
63+
*/
64+
static String thread(String format) {
7265
String currentThread = Thread.currentThread().toString();
7366
String message = PATTERN_CACHE.computeIfAbsent(THREAD, key -> Pattern.compile("%X\\{" + THREAD + "}"))
7467
.matcher(format).replaceAll(currentThread);
7568
message = THREAD_PATTERN.matcher(message).replaceAll(currentThread);
7669
return message;
7770
}
7871

79-
//Copied from SimpleFormatter
80-
private String formatRow(LogRecord record, String format) {
81-
ZonedDateTime zdt = ZonedDateTime.ofInstant(
72+
/*
73+
All parameters expected by simple formatter (and json formatter as well)
74+
*/
75+
static Object[] parameters(LogRecord record, String formattedMessage) {
76+
var timestamp = ZonedDateTime.ofInstant(
8277
record.getInstant(), ZoneId.systemDefault());
8378
String source;
8479
if (record.getSourceClassName() != null) {
@@ -89,7 +84,7 @@ private String formatRow(LogRecord record, String format) {
8984
} else {
9085
source = record.getLoggerName();
9186
}
92-
String message = formatMessage(record);
87+
9388
String throwable = "";
9489
if (record.getThrown() != null) {
9590
StringWriter sw = new StringWriter();
@@ -99,12 +94,31 @@ private String formatRow(LogRecord record, String format) {
9994
pw.close();
10095
throwable = sw.toString();
10196
}
97+
98+
Object[] result = new Object[6];
99+
result[0] = timestamp;
100+
result[1] = source;
101+
result[2] = record.getLoggerName();
102+
result[3] = record.getLevel().getName();
103+
result[4] = formattedMessage;
104+
result[5] = throwable;
105+
106+
return result;
107+
}
108+
109+
@Override
110+
public String format(LogRecord record) {
111+
String message = thread ? thread(format) : format;
112+
for (String parsedKey : parsedProps) {
113+
String value = HelidonMdc.get(parsedKey).orElse("");
114+
message = PATTERN_CACHE.computeIfAbsent(parsedKey, key -> Pattern.compile("%X\\{" + key + "}"))
115+
.matcher(message).replaceAll(value);
116+
}
117+
return formatRow(record, message);
118+
}
119+
120+
private String formatRow(LogRecord record, String format) {
102121
return String.format(format,
103-
zdt,
104-
source,
105-
record.getLoggerName(),
106-
record.getLevel().getLocalizedName(),
107-
message,
108-
throwable);
122+
parameters(record, super.formatMessage(record)));
109123
}
110124
}

0 commit comments

Comments
 (0)