blob: 494f44cfc8cdd0cd6098c877cf20ca881350c24d [file] [log] [blame]
Matthias Andreas Benkard37e804b2021-09-04 22:38:08 +02001= Quarkus Google Cloud JSON Logging
2Matthias Andreas Benkard
3// Meta
4:experimental:
5:data-uri:
6:sectnums:
7:toc:
8:stem:
9:toclevels: 2
10:description: Quarkus Google Cloud JSON Logging Manual
11:keywords: mulk
12// Settings
13:icons: font
14:source-highlighter: rouge
15
16
17Structured logging to standard output according to the Google Cloud
18Logging specification.
19
20
21== Summary
22
23This package contains a log formatter for JBoss Logging in the form of
24a Quarkus plugin that implements the
25https://cloud.google.com/logging/docs/structured-logging[Google Cloud
26Logging JSON format] on standard output.
27
28It is possible to log unstructured text, structured data, or a mixture
29of both depending on the situation.
30
31
Matthias Andreas Benkard37e804b2021-09-04 22:38:08 +020032== Activation
33
34Add the runtime POM to your dependency list. As long as the JAR is on
35the classpath at both build time and runtime, the log formatter
36automatically registers itself on startup.
37
38
39=== Activation with Maven
40
41[source,xml]
42----
43<project>
44 ...
45
46 <dependencies>
47 ...
48
49 <dependency>
50 <groupId>eu.mulk.quarkus-googlecloud-jsonlogging</groupId>
51 <artifactId>quarkus-googlecloud-jsonlogging</artifactId>
Matthias Andreas Benkard20210242022-01-15 10:39:30 +010052 <version>4.0.0</version>
Matthias Andreas Benkard37e804b2021-09-04 22:38:08 +020053 </dependency>
54
55 ...
56 </dependencies>
57
58 ...
59</project>
60----
61
62
63=== Activation with Gradle
64
65[source,groovy]
66----
67dependencies {
68 ...
69
Matthias Andreas Benkard20210242022-01-15 10:39:30 +010070 implementation("eu.mulk.quarkus-googlecloud-jsonlogging:quarkus-googlecloud-jsonlogging:4.0.0")
Matthias Andreas Benkard37e804b2021-09-04 22:38:08 +020071
72 ...
73}
74----
75
76
77== Usage
78
79Logging unstructured data requires no code changes. All logs are
80automatically converted to Google-Cloud-Logging-compatible JSON.
81
82Structured data can be logged in one of 3 different ways: by passing
83https://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
84and
85https://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
86as parameters to individual log entries, by supplying
87https://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
88and
89https://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,
90or by using the Mapped Diagnostic Context.
91
92
93=== Using Label and StructuredParameter
94
95Instances of
96https://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]
97and
98https://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]
99can be passed as log parameters to the `*f` family of logging
100functions on JBoss Logging's
101https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html[Logger].
102
103Simple key–value pairs are represented by
104https://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].
105
106**Example:**
107
108[source,java]
109----
110logger.logf(
111 "Request rejected: unauthorized.",
112 Label.of("requestId", "123"),
113 KeyValueParameter.of("resource", "/users/mulk"),
114 KeyValueParameter.of("method", "PATCH"),
115 KeyValueParameter.of("reason", "invalid token"));
116----
117
118Result:
119
120[source,json]
121----
122{
123 "jsonPayload": {
124 "message": "Request rejected: unauthorized.",
125 "resource": "/users/mulk",
126 "method": "PATCH",
127 "reason": "invalid token"
128 },
129 "labels": {
130 "requestId": "123"
131 }
132}
133----
134
135
136=== Using LabelProvider and StructuredParameterProvider
137
138Any CDI beans that implement
139https://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]
140and
141https://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]
142are discovered at build time and consulted to provide labels and
143parameters for each message that is logged. This can be used to
144provide contextual information such as tracing and request IDs stored
145in thread-local storage.
146
Matthias Andreas Benkard93ecfd12022-01-15 14:03:41 +0100147Alternatively, you can also register providers through the Java
148https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html[ServiceLoader]
149mechanism.
150
Matthias Andreas Benkard37e804b2021-09-04 22:38:08 +0200151**Example:**
152
153[source,java]
154----
155@Singleton
156@Unremovable
157public final class TraceLogParameterProvider implements StructuredParameterProvider, LabelProvider {
158
159 @Override
160 public StructuredParameter getParameter() {
161 var b = Json.createObjectBuilder();
162 b.add("traceId", Span.current().getSpanContext().getTraceId());
163 b.add("spanId", Span.current().getSpanContext().getSpanId());
164 return () -> b;
165 }
166
167 @Override
168 public Collection<Label> getLabels() {
169 return List.of(Label.of("requestId", "123"));
170 }
171}
172----
173
174Result:
175
176[source,json]
177----
178{
179 "jsonPayload": {
180 "message": "Request rejected: unauthorized.",
181 "traceId": "39f9a49a9567a8bd7087b708f8932550",
182 "spanId": "c7431b14630b633d"
183 },
184 "labels": {
185 "requestId": "123"
186 }
187}
188----
189
190
191=== Using the Mapped Diagnostic Context
192
193Any key–value pairs in JBoss Logging's thread-local
194https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/MDC.html[MDC]
195are added to the resulting JSON.
196
197**Example:**
198
199[source,java]
200----
201MDC.put("resource", "/users/mulk");
202MDC.put("method", "PATCH");
203logger.logf("Request rejected: unauthorized.");
204----
205
206Result:
207
208[source,json]
209----
210{
211 "jsonPayload": {
212 "message": "Request rejected: unauthorized.",
213 "resource": "/users/mulk",
214 "method": "PATCH"
215 }
216}
217----