|
| 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] |
0 commit comments