summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2022-01-15 16:13:01 +0100
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2022-01-15 21:14:23 +0100
commit348f2055bfb000633bb80e89bcf62ea037a5af0b (patch)
tree9ad5b0436a7fc24af466508a552366a1f867c7cb /core
parent93ecfd1e0c1d1e40fb17e580a7a11de35383ef79 (diff)
Add a Spring Boot example and integration code.
Change-Id: Ia11dea607c74d9b4cc9a698e9ec92e930bd03f37
Diffstat (limited to 'core')
-rw-r--r--core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java24
-rw-r--r--core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultConsoleHandler.java68
-rw-r--r--core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultEmbeddedConfigurator.java46
-rw-r--r--core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/package-info.java18
-rw-r--r--core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/package-info.java4
5 files changed, 153 insertions, 7 deletions
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java
index 61a2dea..e759ff0 100644
--- a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java
@@ -8,7 +8,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
import java.util.logging.Level;
+import java.util.stream.Collectors;
import org.jboss.logmanager.ExtFormatter;
import org.jboss.logmanager.ExtLogRecord;
@@ -34,7 +36,7 @@ public class Formatter extends ExtFormatter {
private final List<LabelProvider> labelProviders;
/**
- * Constructs a {@link Formatter}.
+ * Constructs a {@link Formatter} with custom configuration.
*
* <p><strong>Note:</strong> This constructor does not automatically discover providers using the
* {@link ServiceLoader} mechanism. See {@link #load} for this case use.
@@ -59,21 +61,33 @@ public class Formatter extends ExtFormatter {
*
* @param parameterProviders the {@link StructuredParameterProvider}s to apply to each log entry.
* @param labelProviders the {@link LabelProvider}s to apply to each log entry.
+ * @return a new formatter.
*/
public static Formatter load(
Collection<StructuredParameterProvider> parameterProviders,
Collection<LabelProvider> labelProviders) {
parameterProviders = new ArrayList<>(parameterProviders);
- ServiceLoader.load(StructuredParameterProvider.class, Formatter.class.getClassLoader())
- .forEach(parameterProviders::add);
+ parameterProviders.addAll(loadStructuredParameterProviders());
labelProviders = new ArrayList<>(labelProviders);
- ServiceLoader.load(LabelProvider.class, Formatter.class.getClassLoader())
- .forEach(labelProviders::add);
+ labelProviders.addAll(loadLabelProviders());
return new Formatter(parameterProviders, labelProviders);
}
+ private static List<StructuredParameterProvider> loadStructuredParameterProviders() {
+ return ServiceLoader.load(StructuredParameterProvider.class, Formatter.class.getClassLoader())
+ .stream()
+ .map(Provider::get)
+ .collect(Collectors.toList());
+ }
+
+ private static List<LabelProvider> loadLabelProviders() {
+ return ServiceLoader.load(LabelProvider.class, Formatter.class.getClassLoader()).stream()
+ .map(Provider::get)
+ .collect(Collectors.toList());
+ }
+
@Override
public String format(ExtLogRecord logRecord) {
var message = formatMessageWithStackTrace(logRecord);
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultConsoleHandler.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultConsoleHandler.java
new file mode 100644
index 0000000..a1dbde7
--- /dev/null
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultConsoleHandler.java
@@ -0,0 +1,68 @@
+package eu.mulk.quarkus.googlecloud.jsonlogging.logmanager;
+
+import eu.mulk.quarkus.googlecloud.jsonlogging.Formatter;
+import java.io.InputStream;
+import java.util.Collections;
+import org.jboss.logmanager.handlers.ConsoleHandler;
+
+/**
+ * A {@link ConsoleHandler} preconfigured with {@link Formatter}.
+ *
+ * <p>Useful as a handler for {@link java.util.logging}.
+ *
+ * <p>If you have a {@code logging.properties} file (see {@link
+ * java.util.logging.LogManager#readConfiguration(InputStream)}), you can use this handler by
+ * setting the following properties:
+ *
+ * <pre>{@code
+ * handlers = eu.mulk.quarkus.googlecloud.jsonlogging.logmanager.ConsoleHandler
+ * }</pre>
+ *
+ * <p><strong>Note:</strong> You can use {@code org.slf4j.bridge.SLF4JBridgeHandler} from {@code
+ * org.slf4j:jul-to-slf4j} instead if you also have {@code org.jboss.slf4j:slf4j-jboss-logmanager}
+ * on the class path. In comparison to this class, which relies on the relatively efficient {@link
+ * org.jboss.logmanager.ExtLogRecord#wrap}, routing through SLF4J incurs additional overhead because
+ * of the necessary conversions between SLF4J's log entry structure and {@link
+ * java.util.logging.LogRecord}.
+ *
+ * <h2>Usage with Spring Boot</h2>
+ *
+ * <p>In case you are using Spring Boot, note that in addition to ensuring that {@code
+ * org.springframework.boot.logging.java.JavaLoggingSystem} is the logging system in use (see
+ * below), you need to accompany this with an entry in {@code application.properties} that points to
+ * your {@code logging.properties} file:
+ *
+ * <pre>{@code
+ * logging.config = classpath:logging.properties
+ * }</pre>
+ *
+ * <p>In order to ensure that Spring Boot chooses {@code JavaLoggingSystem} over other
+ * implementations, make sure that no other logging backends are present on the class path. A simple
+ * way of doing this is by relying on {@code spring-boot-starter-logging} while excluding Logback:
+ *
+ * <pre>{@code
+ * <dependency>
+ * <groupId>org.springframework.boot</groupId>
+ * <artifactId>spring-boot-starter</artifactId>
+ * <exclusions>
+ * <exclusion>
+ * <groupId>ch.qos.logback</groupId>
+ * <artifactId>logback-classic</artifactId>
+ * </exclusion>
+ * </exclusions>
+ * </dependency>
+ * }</pre>
+ *
+ * <p>You will probably want to include at least {@code org.jboss.slf4j:slf4j-jboss-logmanager} as
+ * well. In addition, {@code org.slf4j:jcl-over-slf4j}, {@code
+ * org.jboss.logmanager:log4j-jboss-logmanager}, and {@code
+ * org.jboss.logmanager:log4j2-jboss-logmanager} may be useful, but are not required.
+ */
+@SuppressWarnings("java:S110")
+public final class DefaultConsoleHandler extends ConsoleHandler {
+
+ /** Constructs console handler with a formatter created by {@link Formatter#load}. */
+ public DefaultConsoleHandler() {
+ super(Formatter.load(Collections.emptyList(), Collections.emptyList()));
+ }
+}
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultEmbeddedConfigurator.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultEmbeddedConfigurator.java
new file mode 100644
index 0000000..8d9d4d8
--- /dev/null
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/DefaultEmbeddedConfigurator.java
@@ -0,0 +1,46 @@
+package eu.mulk.quarkus.googlecloud.jsonlogging.logmanager;
+
+import eu.mulk.quarkus.googlecloud.jsonlogging.Formatter;
+import java.util.logging.Handler;
+import org.jboss.logmanager.EmbeddedConfigurator;
+import org.jboss.logmanager.handlers.ConsoleHandler;
+
+/**
+ * A convenient {@link EmbeddedConfigurator} for JBoss Log Manager.
+ *
+ * <p>You can register this class through the {@link java.util.ServiceLoader} mechanism as a
+ * provider of the {@link EmbeddedConfigurator} interface (under the name of {@code
+ * org.jboss.logmanager.EmbeddedConfigurator}) to automatically register a {@link ConsoleHandler}
+ * using {@link Formatter} as the default log output method for the application.
+ */
+public final class DefaultEmbeddedConfigurator implements EmbeddedConfigurator {
+
+ private final Handler[] rootHandlers;
+
+ /**
+ * Constructs a JBoss Log Manager configuration that uses {@link Formatter} and {@link
+ * ConsoleHandler} for log output.
+ */
+ @SuppressWarnings("java:S2095")
+ public DefaultEmbeddedConfigurator() {
+ rootHandlers = new Handler[] {createConsoleHandler()};
+ }
+
+ /**
+ * Creates a {@link ConsoleHandler} that uses {@link Formatter} for formatting.
+ *
+ * @return a preconfigured {@link ConsoleHandler}.
+ */
+ public static ConsoleHandler createConsoleHandler() {
+ return new DefaultConsoleHandler();
+ }
+
+ @Override
+ public Handler[] getHandlersOf(String loggerName) {
+ if (loggerName.isEmpty()) {
+ return rootHandlers;
+ } else {
+ return EmbeddedConfigurator.NO_HANDLERS;
+ }
+ }
+}
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/package-info.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/package-info.java
new file mode 100644
index 0000000..87eb71e
--- /dev/null
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/logmanager/package-info.java
@@ -0,0 +1,18 @@
+/**
+ * Integration with JBoss Log Manager and {@link java.util.logging}.
+ *
+ * <p>Provides classes that can be used to conveniently configure the JBoss Log Manager ({@link
+ * org.jboss.logmanager.LogManager}) as well as {@link java.util.logging} to use the Google Cloud
+ * JSON Logging formatter ({@link eu.mulk.quarkus.googlecloud.jsonlogging.Formatter}).
+ *
+ * <p>{@link eu.mulk.quarkus.googlecloud.jsonlogging.logmanager.DefaultEmbeddedConfigurator} can be
+ * set as a provided implementation of {@link org.jboss.logmanager.EmbeddedConfigurator} via the
+ * standard {@link java.util.ServiceLoader} mechanism.
+ *
+ * <p>{@link eu.mulk.quarkus.googlecloud.jsonlogging.logmanager.DefaultConsoleHandler} can be used
+ * as the target of the {@code handlers} property key in {@link
+ * java.util.logging.LogManager#readConfiguration(java.io.InputStream)}. This is particularly useful
+ * when used in conjunction with frameworks other than Quarkus (such as Spring Boot). See the class
+ * documentation for details.
+ */
+package eu.mulk.quarkus.googlecloud.jsonlogging.logmanager;
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/package-info.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/package-info.java
index 3617b8c..e684bfd 100644
--- a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/package-info.java
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/package-info.java
@@ -4,7 +4,7 @@
*
* <ul>
* <li><a href="#sect-summary">Summary</a>
- * <li><a href="#sect-activation">Activation</a>
+ * <li><a href="#sect-installation">Installation</a>
* <li><a href="#sect-usage">Usage</a>
* </ul>
*
@@ -17,7 +17,7 @@
* <p>It is possible to log unstructured text, structured data, or a mixture of both depending on
* the situation.
*
- * <h2 id="sect-activation">Installation</h2>
+ * <h2 id="sect-installation">Installation</h2>
*
* <ul>
* <li><a href="#sect-installation-maven">Installation with Maven</a>