Skip to content

Commit 68e093a

Browse files
committed
Add SE logging guide
1 parent b0750a8 commit 68e093a

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
///////////////////////////////////////////////////////////////////////////////
2+
3+
Copyright (c) 2025 Oracle and/or its affiliates.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
///////////////////////////////////////////////////////////////////////////////
18+
19+
= Helidon SE Logging Guide
20+
:description: Helidon logging guide
21+
:keywords: helidon, logging, MDC, jul, log4j, logback, slf4j
22+
:rootdir: {docdir}/../..
23+
24+
include::{rootdir}/includes/se.adoc[]
25+
26+
This guide describes various aspects of logging support in Helidon.
27+
28+
== Contents
29+
30+
* <<Helidon Logging,Helidon Logging>>
31+
* <<Customizing Logging with Java Util Logging,Customizing Logging with Java Util Logging>>
32+
* <<log4j and slf4j support,log4j and slf4j support>>
33+
* <<Mapped Diagnostic Context (MDC) support,Mapped Diagnostic Context (MDC) support>>
34+
* <<Additional Information,Additional Information>>
35+
36+
== Helidon Logging
37+
38+
Helidon modules use the Java Platform Logging API (`System.Logger`) for logging. Therefore,
39+
Helidon applications will use Java Util Logging (JUL) as the default log framework.
40+
41+
If in your application you wish to use another logging framework such as log4j or slf4j,
42+
then you can do so. See section <<log4j and slf4j support,log4j and slf4j support>>
43+
44+
== Customizing Logging with Java Util Logging
45+
46+
Since by default Helidon uses the Java Util Logging framework, you will see a
47+
`logging.properties` file in most Helidon examples. It will be similar to this:
48+
49+
[source]
50+
----
51+
handlers=io.helidon.logging.jul.HelidonConsoleHandler
52+
53+
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$s %3$s !thread!: %5$s%6$s%n
54+
55+
# Global logging level. Can be overridden by specific loggers
56+
.level=FINE
57+
----
58+
59+
`HelidonConsoleHandler` is similar to the JUL `ConsoleHandler` with these additional capabilities:
60+
61+
1. Defaults the Handler log level to ALL so level filtering is performed only by the Logger
62+
2. Uses `HelidonFormatter` which is compatible with JUL `SimpleFormatter` and adds support for MDC tags and the `!thread!` keyword
63+
64+
Helidon's internal loggers are usually defined per-class. So to enable finer grained logging in a specific Helidon package, you can add entries like the following to `logging.properties`:
65+
66+
[source]
67+
----
68+
io.helidon.webserver.level=INFO
69+
----
70+
71+
== log4j and slf4j support
72+
73+
If you wish to use another log framework, such has log4j or slf4j, and you wish to consolidate Helidon logging
74+
with that framework, then you have a couple options:
75+
76+
1. Use the log framework's support for Java Platform Logging (such as `log4j-jp` or `slf4j-jdk-platform-logging`)
77+
2. Use the log framework's bridge for Java Util Logging (such as `log4j-jul` or `jul-to-slf4j`)
78+
79+
This section focuses on the second option as it aligns with what most Helidon examples use and leverages some of Helidon's JUL specific features.
80+
81+
=== log4j
82+
83+
To use `log4j` with your Helidon application add the following dependencies:
84+
85+
[source]
86+
----
87+
<dependency>
88+
<groupId>io.helidon.logging</groupId>
89+
<artifactId>helidon-logging-log4j</artifactId>
90+
</dependency>
91+
<dependency>
92+
<groupId>org.apache.logging.log4j</groupId>
93+
<artifactId>log4j-api</artifactId>
94+
</dependency>
95+
<dependency>
96+
<groupId>org.apache.logging.log4j</groupId>
97+
<artifactId>log4j-core</artifactId>
98+
</dependency>
99+
<dependency>
100+
<groupId>org.apache.logging.log4j</groupId>
101+
<artifactId>log4j-jul</artifactId>
102+
</dependency>
103+
----
104+
105+
This achieves four things:
106+
107+
1. Makes the log4j API available to your application.
108+
2. Bridges all of Helidon's Java Util Logging to log4j.
109+
3. Enables the use of MDC with log4j (see <<Mapped Diagnostic Context (MDC) support,Mapped Diagnostic Context (MDC) support>>).
110+
4. Ensures GraalVM native-image support for log4j.
111+
112+
For more information see link:{helidon-github-examples-url}/logging/log4j[Helidon log4j example]
113+
114+
=== slf4j
115+
116+
To use `slf4j` with your Helidon application add the following dependencies:
117+
118+
[source]
119+
----
120+
<dependency>
121+
<groupId>io.helidon.logging</groupId>
122+
<artifactId>helidon-logging-slf4j</artifactId>
123+
</dependency>
124+
<dependency>
125+
<groupId>org.slf4j</groupId>
126+
<artifactId>slf4j-api</artifactId>
127+
</dependency>
128+
<dependency>
129+
<groupId>org.slf4j</groupId>
130+
<artifactId>jul-to-slf4j</artifactId>
131+
</dependency>
132+
<dependency>
133+
<groupId>ch.qos.logback</groupId>
134+
<artifactId>logback-classic</artifactId>
135+
<version>${version.lib.logback}</version>
136+
</dependency>
137+
----
138+
139+
The above snippet uses logback as the slf4j logging provider.
140+
141+
This achieves four things:
142+
143+
1. Makes the slf4j API available to your application.
144+
2. Bridges all of Helidon's Java Util Logging to slf4j
145+
3. Enables the use of MDC with slf4j
146+
4. Ensures GraalVM native-image support for slf4j
147+
148+
For more information see link:{helidon-github-examples-url}/logging/slf4j[Helidon slf4j example]
149+
150+
== Mapped Diagnostic Context (MDC) support
151+
152+
The Mapped Diagnostic Context provides a mechanism for application code to store
153+
values in a context that are then included in log output. These values could
154+
be a tracing ID, the current user, or a similar contextual value, and they are
155+
propagated by Helidon across threads.
156+
157+
Some logging frameworks, such as slf4j and log4j, have support for MDC. But
158+
Java Util Logging does not. Therefore, Helidon provides an API, `HelidonMdc`,
159+
that you can use to store contextual values. `HelidonMdc` not only works with JUL
160+
but also works with the other supported frameworks (slf4j or log4j).
161+
162+
To use Helidon MDC, you need to do three things:
163+
164+
1. Add a dependencies on one of the supported logging frameworks. See previous sections.
165+
2. Store values in the MDC in your code.
166+
3. Configure logging to display the values in its output.
167+
168+
=== Storing values in MDC
169+
170+
To set values in the MDC you can use `io.helidon.logging.common.HelidonMdc` class:
171+
172+
[source]
173+
----
174+
HelidonMdc.set("name", "Joe");
175+
----
176+
177+
This will store an attribute named "name" with the value "Joe" in the MDC so that it can be
178+
extracted later in log output.
179+
180+
`HelidonMdc` works with the supported logging frameworks. But if you prefer, you can
181+
use a logging framework specific API. Such as `org.slf4j.MDC` or `org.apache.logging.log4j.ThreadContext` instead.
182+
183+
=== MDC output with Java Util Logging
184+
185+
You must use `HelidonConsoleHandler` or `HelidonFormatter` in order to reference MDC values in the
186+
log format string. To reference MDC values in your format string using the token `%X{name}` where
187+
`name` is the property used in MDC. For example:
188+
189+
[source]
190+
----
191+
handlers=io.helidon.logging.jul.HelidonConsoleHandler
192+
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s "%X{name}"%n
193+
.level=INFO
194+
----
195+
196+
=== MDC output with slf4j and logback
197+
198+
Logback expects `lockback.xml` on the classpath as one of the configuration
199+
options. You can reference MDC values using the token `%X{name}` where `name`
200+
is the property used in MDC. For example:
201+
202+
[source]
203+
----
204+
<configuration>
205+
<appender name="STDOUT"
206+
class="ch.qos.logback.core.ConsoleAppender">
207+
<encoder>
208+
<pattern>
209+
%d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg %X{name}%n
210+
</pattern>
211+
</encoder>
212+
</appender>
213+
214+
<root level="INFO">
215+
<appender-ref ref="STDOUT" />
216+
</root>
217+
</configuration>
218+
----
219+
220+
=== MDC output with log4j
221+
222+
There are a variety of ways to configure log4j, but once again the important part
223+
for MDC is you can use the token `%X{name}` to reference MDC values in the log output.
224+
225+
[source]
226+
----
227+
<PatternLayout pattern="%-5p [%t]: %X{name} %m%n"/>
228+
----
229+
230+
== Additional Information
231+
232+
* link:{helidon-github-examples-url}/logging[Helidon logging examples]
233+
* link:{https://medium.com/helidon/helidon-logging-and-mdc-5de272cf085d}[Helidon, Logging, and MDC Blog]
234+
* link:{javadoc-base-url}/io.helidon.logging.common/io/helidon/logging/common/HelidonMdc.html[HelidonMdc Javadoc]

docs/src/main/asciidoc/sitegen.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ backend:
322322
- "quickstart.adoc"
323323
- "config.adoc"
324324
- "health.adoc"
325+
- "logging.adoc"
325326
- "metrics.adoc"
326327
- "security-oidc.adoc"
327328
- "tracing.adoc"

0 commit comments

Comments
 (0)