= Quarkus Google Cloud JSON Logging Matthias Andreas Benkard // Meta :experimental: :data-uri: :sectnums: :toc: :stem: :toclevels: 2 :description: Quarkus Google Cloud JSON Logging Manual :keywords: mulk // Settings :icons: font :source-highlighter: rouge Structured logging to standard output according to the Google Cloud Logging specification. == Summary This package contains a log formatter for JBoss Logging in the form of a Quarkus plugin that implements the https://cloud.google.com/logging/docs/structured-logging[Google Cloud Logging JSON format] on standard output. It is possible to log unstructured text, structured data, or a mixture of both depending on the situation. == Activation (Quarkus) Add the runtime POM to your dependency list. As long as the JAR is on the classpath at both build time and runtime, the log formatter automatically registers itself on startup. If you are using Maven: [source,xml] ---- eu.mulk.quarkus-googlecloud-jsonlogging quarkus-googlecloud-jsonlogging 4.0.0 ---- If you are using Gradle: [source,groovy] ---- dependencies { implementation("eu.mulk.quarkus-googlecloud-jsonlogging:quarkus-googlecloud-jsonlogging:4.0.0") } ---- == Activation (Other Frameworks) If you are not using Quarkus, you can still make use of the `-core` module and wire it into your application in a custom way. Read this section for hints on how to do so. === Installation If you are using Maven: [source,xml] ---- eu.mulk.quarkus-googlecloud-jsonlogging quarkus-googlecloud-jsonlogging-core 4.0.0 ---- If you are using Gradle: [source,groovy] ---- dependencies { implementation("eu.mulk.quarkus-googlecloud-jsonlogging:quarkus-googlecloud-jsonlogging-core:4.0.0") } ---- === Wiring (Spring Boot) If you are using Spring Boot, the easiest way to integrate the log formatter is by relying on `spring-boot-starter-logging` (which is pulled in by `spring-boot-starter`), excluding Logback, and pulling in JBoss Log Manager as the back end for SLF4J: [source,xml] ---- eu.mulk.quarkus-googlecloud-jsonlogging quarkus-googlecloud-jsonlogging-core 4.0.0 org.jboss.slf4j slf4j-jboss-logmanager 1.1.0.Final org.springframework.boot spring-boot-starter ch.qos.logback logback-classic ---- Create a text file called `META-INF/services/org.jboss.logmanager.EmbeddedConfigurator` in your `resources` directory and put the fully qualified name of `DefaultEmbeddedConfigurator` into it: [source] ---- eu.mulk.quarkus.googlecloud.jsonlogging.logmanager.DefaultEmbeddedConfigurator ---- To configure `java.util.logging`, which is used by Tomcat by default, create an entry in `application.properties` that points to `logging.properties`: [source,properties] ---- logging.config = classpath:logging.properties ---- Create the `logging.properties` file in your `resources` directory and name `DefaultConsoleHandler` as a handler: [source,properties] ---- handlers = eu.mulk.quarkus.googlecloud.jsonlogging.logmanager.ConsoleHandler ---- == Usage Logging unstructured data requires no code changes. All logs are automatically converted to Google-Cloud-Logging-compatible JSON. Structured data can be logged in one of 3 different ways: by passing https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/Label.html[Label]s and https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/StructuredParameter.html[StructuredParameter]s as parameters to individual log entries, by supplying https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/LabelProvider.html[LabelProvider]s and https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/StructuredParameterProvider.html[StructuredParameterProvider]s, or by using the Mapped Diagnostic Context. === Using Label and StructuredParameter Instances of https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/Label.html[Label] and https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/StructuredParameter.html[StructuredParameter] can be passed as log parameters to the `*f` family of logging functions on JBoss Logging's https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html[Logger]. Simple key–value pairs are represented by https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/KeyValueParameter.html[KeyValueParameter]. **Example:** [source,java] ---- logger.logf( "Request rejected: unauthorized.", Label.of("requestId", "123"), KeyValueParameter.of("resource", "/users/mulk"), KeyValueParameter.of("method", "PATCH"), KeyValueParameter.of("reason", "invalid token")); ---- Result: [source,json] ---- { "jsonPayload": { "message": "Request rejected: unauthorized.", "resource": "/users/mulk", "method": "PATCH", "reason": "invalid token" }, "labels": { "requestId": "123" } } ---- === Using LabelProvider and StructuredParameterProvider Any CDI beans that implement https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/LabelProvider.html[LabelProvider] and https://javadocs.dev/eu.mulk.quarkus-googlecloud-jsonlogging/quarkus-googlecloud-jsonlogging/3.1.0/eu.mulk.quarkus.googlecloud.jsonlogging/eu/mulk/quarkus/googlecloud/jsonlogging/StructuredParameterProvider.html[StructuredParameterProvider] are discovered at build time and consulted to provide labels and parameters for each message that is logged. This can be used to provide contextual information such as tracing and request IDs stored in thread-local storage. Alternatively, you can also register providers through the Java https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html[ServiceLoader] mechanism. **Example:** [source,java] ---- @Singleton @Unremovable public final class TraceLogParameterProvider implements StructuredParameterProvider, LabelProvider { @Override public StructuredParameter getParameter() { var b = Json.createObjectBuilder(); b.add("traceId", Span.current().getSpanContext().getTraceId()); b.add("spanId", Span.current().getSpanContext().getSpanId()); return () -> b; } @Override public Collection