Java Util Logging (JUL) integration
Java Util Logging integration is provided as part of the artifact:
<dependency>
<groupId>io.yupiik.logging</groupId>
<artifactId>yupiik-logging-jul</artifactId>
<version>${yupiik-logging.version}</version>
</dependency>
Use globally
java .... -Djava.util.logging.manager=io.yupiik.logging.jul.YupiikLogManager ...
Configuration
Configuration is close to default JUL one with small differences:
-
handlers don't need to configure themselves in their constructor or so for common properties (formatter, level, ...), the framework does it automatically
-
InlineFormatter
andJsonFormatter
support aliases (reflection free instantiation) withinline
andjson
you can use in the configuration
Standard handler
io.yupiik.logging.jul.handler.StandardHandler
enables to log on stdout and stderr. For all level from finest/debug to info it will go on stdout and others (warnings, errors/severes) will go on stderr.
It can be configured with the std
or standard
alias too.
There is also its companion stdout
or io.yupiik.logging.jul.handler.StdoutHandler
which only outputs on stdout.
File Handler
A io.yupiik.logging.jul.handler.LocalFileHandler
is also provided to be able to log in a file and rotate the log file. Indeed you can use JVM FileHandler
but this one is a bit more powerful in practise if you don't run in a container and can't use a docker logging driver or equivalent.
Here is its configuration - all are prefixed with io.yupiik.logging.jul.handler.LocalFileHandler.
and the standard configuration (encoding, level, ...) is still supported even if not listed.
Name | Default Value | Description |
---|---|---|
filenamePattern |
$/logs/logs.%s.%03d.log |
where log files are created, it uses String.format() and gives you the date and file number - in this order. If you replace `%s` by `%sH` you will append the hour in the filename. `%sHm` adds the minutes (a more precise pattern is not needed nor recommended). |
noRotation | false | if `true`, once a log file is opened, it is kept for the life of the process. |
overwrite | false | if `true`, existing files are reused. |
truncateIfExists | false | if `true`, opening a file is not in append mode (previous content is erased). |
limit | 10 Megabytes | limit size indicating the file should be rotated - in long format |
dateCheckInterval | 5 seconds | how often the date should be computed to rotate the file (don't do it each time for performances reason, means you can get few records of next day in a file name with current day). In java Duration format (ex: `PT5S`). |
bufferSize | -1 | if positive the in memory buffer used to store data before flushing them to the disk (in bytes) |
archiveDirectory |
$/logs/archives/ |
where compressed logs are put. |
archiveFormat | gzip | zip or gzip. |
archiveOlderThan | -1 | how many days files are kept before being compressed (in Duration Format) |
purgeOlderThan | -1 | how many days files are kept before being deleted, note: it applies on archives and not log files so 2 days of archiving and 3 days of purge makes it deleted after 5 days (in Duration Format). |
compressionLevel | -1 | In case of zip archiving the zip compression level (-1 for off or 0-9). |
maxArchives | -1 | Max number of archives (zip/gzip) to keep, ignored if negative (you can review `io.yupiik.logging.jul.handler.LocalFileHandlerTest.purgeMaxArchive` for some sample configuration). |
Duration Format
The format for the String to be parsed is PnDTnHnMn.nS
where nD
means n
number of Days, nH
means n
number of Hours, nM
means n
number of Minutes, nS
means n
number of Seconds and T
is a prefix that must be used before the part consisting of nHnMn.nS
.
Async handler
io.yupiik.logging.jul.handler.AsyncHandler
enables to handle asynchronously in a background thread log events (LogRecord
).
io.yupiik.logging.jul.handler.AsyncHandler.delegate.class
enables to configure the delegate class name.
The properties like io.yupiik.logging.jul.handler.AsyncHandler.formatter
etc are forwarded to the delegate if set - and generally override the default ones.
IMPORTANT
|
logging asynchronously means you are loosing the context related to threads - if you are using a |
Pattern formatter
The library also provides a pattern formatter. It does not use String.format
as SimpleFormatter
does and can be configured either with io.yupiik.logging.jul.formatter.PatternFormatter.pattern
property or passing the pattern to the formatter alias (reflection free mode): pattern(<pattern to use>)
. Its syntax uses %
to mark elements of the log record. Here is the list:
Name | Description |
---|---|
%% | Escapes `%` character. |
%n | End of line. |
%l or %level | Log record level. |
%m or %message | Log record message. |
%c or %logger | Logger name. |
%C or %class | Class name if exists or empty. |
%M or %method | Method name if exists or empty. |
%d or %date | The instant value. Note it can be followed by a date time formatter pattern between braces. |
%x or %exception | The exception. It will be preceeded by a new line if existing to ensure it integrates well in log output. |
%T or %threadId | Thread ID. |
%t or %thread or %threadName | Thread name - only works in synchronous mode. |
%r | Duration (in ms) since the startup of the application (creating of the pattern formatter actually). |
%uuid | Random UUID. |
Pattern example value: %d [%l][%c][%C][%M] %m%x%n
, it will output lines like 1970-01-01T00:00:00Z [INFO][the.logger][the.source][the.method] test message\n
.
JSON formatter
JSON formatter relies on JSON-B until 1.0.2, JSON-P starting with 1.0.3 and no dependency starting with 1.0.8 so ensure to add the related dependencies. It can be done with this list for example:
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-json_1.1_spec</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.apache.johnzon</groupId>
<artifactId>johnzon-core</artifactId>
<version>1.2.19</version>
</dependency>
TIP
|
the JSON formatter can be configured passing |
Sample Configuration Files
As with native JUL LogManager
, you can configure the runtime logging with the following system property: -Djava.util.logging.config.file=<path to config file>
.
NOTE
|
don't forget |
Here is a sample configuration switching to JSON logging:
.handlers = io.yupiik.logging.jul.handler.StandardHandler
io.yupiik.logging.jul.handler.StandardHandler.formatter = json
The same configuration for a standard inline logging (text style) but tuning the log level:
.handlers = io.yupiik.logging.jul.handler.StandardHandler
io.yupiik.logging.jul.handler.StandardHandler.level = FINEST
com.app.level = FINEST
Here is a configuration using a pattern:
.handlers = standard
standard.formatter = pattern(%d [%l][%c][%C][%M] %m%x%n)
And finally a configuration using file output instead of standard one:
.handlers = file
file.formatter = inline
TIP
|
you can set all properties as system properties and also environment variables (in uppercase and dots replaced by underscores). |