JDK-8046148 : JEP 158: Unified JVM Logging
  • Type: JEP
  • Component: hotspot
  • Sub-Component: svc
  • Priority: P2
  • Status: Closed
  • Resolution: Delivered
  • Fix Versions: 9
  • Submitted: 2012-02-27
  • Updated: 2024-09-10
  • Resolved: 2016-10-05
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Sub Tasks
JDK-8059747 :  
JDK-8061219 :  
JDK-8061221 :  
JDK-8073329 :  
Description
Summary
-------

Introduce a common logging system for all components of the JVM.


Goals
-----

  - Common command-line options for all logging
  - Log messages are categorized using tags (e.g. compiler,
    gc, classload, metaspace, svc, jfr, ...). One message can have
    multiple tags (_tag-set_)
  - Logging is performed at different levels: `error, warning, info,
    debug, trace, develop`.
  - Possible to select what messages that are logged based on level.
  - Possible to redirect logging to console or file.
  - The default configuration is that all messages using warning and
    error level are output to stderr.
  - File rotation of log files by size and number of files to keep
    (similar to what is available for GC logs today)
  - Print line-at-a-time (no interleaving within same line)
  - Logging messages are in human-readable plain text
  - Messages can be "decorated". The default decorations are: **`uptime,
    level, tags`**.
  - Ability to configure **which** decorations that will be printed.
  - Existing '`tty->print...`' logging should use unified logging as output
  - Logging can be configured dynamically at runtime via jcmd or MBeans
  - Tested and supported -- should not crash if/when enabled by
    user/customer

Stretch goals:

  - Multi-line logging: several lines can be logged in a way that keeps
    them together (non interleaved) when output
  - Enable/disable individual log messages (for example by
    using  `__FILE__` / `__LINE__`)
  - Implement syslog and Windows Event Viewer output
  - Ability to configure in **which order** decorations should be printed

Non-Goals
---------

It is outside the scope of this JEP to add the actual logging calls from
all JVM components. This JEP will only provide the infrastructure to do
the logging.

It is also outside the scope of the JEP to enforce a logging format,
apart from the format of the decorations and the use of human-readable
plain text.

This JEP will not add logging to Java code in the JDK.

Motivation
----------

The JVM is complex system-level component where root-cause analysis is
often a difficult and time-consuming task. Without extensive
serviceability features it is often close to impossible to find the root
cause of intermittent crashes or performance quirks in a production
environment. Fine-grained, easy-to-configure JVM logging available for
use by support and sustaining engineering is one such feature.

JRockit has a similar feature and it has been instrumental in providing
support to customers.

Description
-----------

### Tags

The logging framework defines a set of _tags_ in the JVM. Each
tag is identified by its name (for example: `gc`, `compiler`,
`threads`, etc). The set of tags can be changed in the source code
as required. When a log message is added it should be associated with
a _tag-set_ classifying the information logged. A _tag-set_ consists of one
or more tags.

### Levels

Each log message has a logging _level_ associated with it. The available
levels are `error`, `warning`, `info`, `debug`, `trace` and `develop` in
increasing order of verbosity. The `develop` level is only available in non-product builds.

For each output, a logging level can be configured to control the
amount of information written to that output.
The alternative `off` disables logging completely.

### Decorations

Logging messages are _decorated_ with information about the
message. Here is a list of the possible decorations:

  - `time` -- Current time and date in ISO-8601 format
  - `uptime` -- Time since the start of the JVM in seconds and
    milliseconds (e.g., `6.567s`)
  - `timemillis` -- The same value as generated by `System.currentTimeMillis()`
  - `uptimemillis` -- Milliseconds since the JVM started
  - `timenanos` -- The same value as generated by System.nanoTime()
  - `uptimenanos` -- Nanoseconds since the JVM started
  - `pid` -- The process identifier
  - `tid` -- The thread identifier
  - `level` -- The level associated with the log message
  - `tags` -- The tag-set associated with the log message

Each output can be configured to use a custom set of decorators.
The order of them is always the one above though.
The decorations to be used can be configured by the user in runtime.
Decorations will be prepended to the log message

Example: `[6.567s][info][gc,old] Old collection complete`

### Output

There are currently three types of output supported:

  - stdout -- Outputs to stdout.

  - stderr -- Outputs to stderr.

  - text file -- Outputs to text file(s).

    Can be configured to handle file rotation based on written size and
    a number of files to rotate.
    Example: rotate log file each 10MB, keep 5 files in rotation.
    The files names will be appended with their number in the rotation.
    Example: `hotspot.log.1, hotspot.log.2, ..., hotspot.log.5`
    Currently open file will not have any number appended.
    Example: `hotspot.log`.
    The size of the files is not guaranteed to be exactly the size
    configured. The size can overflow at most the size of the last log
    message written.

Some output types may require additional configuration.
Additional output types could be easily implemented using a simple and
well defined interface.

### Command-line options

A new command-line option will be added, to control logging from
all components of the JVM.

  - `-Xlog`

Multiple arguments will be applied in the order they appear on
command line. Multiple ´-Xlog´ arguments for the same output will
override each other in their given order. Last configuration rules.

The following syntax will be used to configure the logging:

    -Xlog[:option]
        option         :=  [<what>][:[<output>][:[<decorators>][:<output-options>]]]
                           'help'
                           'disable'
        what           :=  <selector>[,...]
        selector       :=  <tag-set>[*][=<level>]
        tag-set        :=  <tag>[+...]
                           'all'
        tag            :=  name of tag
        level          :=  trace
                           debug
                           info
                           warning
                           error
        output         :=  'stderr'
                           'stdout'
                           [file=]<filename>
        decorators     :=  <decorator>[,...]
                           'none'
        decorator      :=  time
                           uptime
                           timemillis
                           uptimemillis
                           timenanos
                           uptimenanos
                           pid
                           tid
                           level
                           tags
        output-options :=  <output_option>[,...]
        output-option  :=  filecount=<file count>
                           filesize=<file size>
                           parameter=value

The '`all`' tag is a meta tag consisting of all tag-sets available.
'`*`' in ´tag-set´ definition denotes 'wildcard' tag match. Not using
'`*`' means 'all messages matching exactly the specified tags'.

Omitting 'what' alltogether will default to tag-set `all` and level `info` .

Omitting 'level' will default to `info`

Omitting 'output' will default to `stdout`

Omitting 'decorators' will default to `uptime, level, tags`

The '`none`' decorator is special and used to turn off all decorations.

Levels provided are aggregated.
Example, if an output is configured to use ´level´ `info`. All messages
matching tags in ´what´ with log level `info`, `warning` and `error`
will be output.

    -Xlog:disable
        this turns off all logging and clears all configuration of the
        logging framework. Even warnings and errors.

    -Xlog:help
        prints -Xlog usage syntax and available tags, levels, decorators
        along with some example command lines.


#### Default configuration:

    -Xlog:all=warning:stderr:uptime,level,tags
        - default configuration if nothing is configured on command line
        - 'all' is a special tag name aliasing all existing tags
        - this configuration will log all messages with a level that
        matches ´warning´ or ´error´ regardless of what tags the
        message is associated with

#### Simple Examples:

    -Xlog

is the same as

    -Xlog:all
        - log messages using 'info' level to stdout
        - level 'info' and output 'stdout' are default if nothing else
        is provided
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc
        - log messages tagged with 'gc' tag using 'info' level to
        'stdout'
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc=debug:file=gc.txt:none
        - log messages tagged with 'gc' tag using 'debug' level to
        a file called 'gc.txt' with no decorations
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc=trace:file=gctrace.txt:uptimemillis,pid:filecount=5,filesize=1M
        - log messages tagged with 'gc' tag using 'trace' level to
        a rotating fileset with 5 files with size 1MB with base name
        'gctrace.txt' and use decorations 'uptimemillis' and 'pid'
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc::uptime,tid
        - log messages tagged with 'gc' tag using default 'info' level to
        default output 'stdout' and use decorations 'uptime' and 'tid'
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc*=info,rt*=off
        - log messages tagged with at least 'gc' using 'info' level but turn
        off logging of messages tagged with 'rt'
        - messages tagged with both 'gc' and 'rt' will not be logged
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:disable -Xlog:rt=trace:rttrace.txt
        - turn off 'all' logging, even warnings and errors, except
        messages tagged with 'rt' using 'trace' level
        - output to a file called 'rttrace.txt'

#### Complex examples:
    -Xlog:gc+rt*=debug
        - log messages tagged with at least 'gc' and 'rt' tag using 'debug'
        level to 'stdout'
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc+meta*=trace,rt*=off:file=gcmetatrace.txt
        - log messages tagged with at least 'gc' and 'meta' tag using 'trace'
        level to file 'metatrace.txt' but turn off all messages tagged
        with 'rt'
        - again, messages tagged with 'gc', 'meta' and 'rt' will not be logged
        since 'rt' is set to off
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc+meta=trace
        - log messages tagged with exactly 'gc' and 'meta' tag using 'trace'
        level to 'stdout'
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect

    -Xlog:gc+rt+compiler*=debug,meta*=warning,svc*=off
        - log messages tagged with at least 'gc' and 'rt' and 'compiler' tag
        using 'trace' level to 'stdout' but only log messages tagged
        with 'meta' with level 'warning' or 'error' and turn off all
        messages tagged with 'svc'
        - default output of all messages at level 'warning' to 'stderr'
        will still be in effect



### Controlling at runtime

Logging can be controlled at runtime through Diagnostic Commands (the `jcmd`
utility). Everything that can be specified on the command line can also
be specified dynamically with Diagnostic Commands. Since diagnostic
commands are automatically exposed as MBeans it will be possible to use
JMX to change logging configuration in runtime.

Aditional support to enumerate over logging configuration and parameters
will be added to the list of runtime control commands.

### JVM interface

In the JVM a set of macros will be created with an API **similar** to:

    log_<level>(Tag1[,...])(fmtstr, ...)
        syntax for the log macro

#### Example:

    log_info(gc, rt, classloading)("Loaded %d objects.", object_count)
        the macro is checking the log level to avoid uneccessary
        calls and allocations.

    log_debug(svc, debugger)("Debugger interface listening at port %d.", port_number)

#### Level information:

    LogHandle(gc, meta, classunloading) log;
    if (log.is_trace()) {
        ...
    }

    if (log.is_debug()) {
        ...
    }

To avoid executing code that produces data only used for logging it is
possible to ask a Log class about what log level it currently is configured
as.

### Performance

The different log levels should have guidelines that define the expected
performance overhead for the level. For example: "warning level
shouldn't affect performance; info level should be acceptable for
production; debug, trace and error levels do not have performance requirements."
Running with logging disabled should have as little performance impact
as possible. It will always cost to log though.


### Future possible extensions

In the future, it may make sense to add a Java API for writing log
messages to this infrastructure, for use from classes in the JDK.

Initially, only three backends will be developed: stdout, stderr and file.
Future projects could add other backends. For example: syslog, Windows Event
Viewer, socket, etc.

### Open issues

  - Should we provide an alternative in the API to have the level
    provided as a parameter to the macro?
  - Should decorations be surrounded by something else than `[]` to make
    it easier to parse the output?
  - What is the exact format of the datestamp decorations?
    ISO 8601 is proposed.

Testing
-------

It is extremely important that logging in itself does not cause any
instabilities, thus extensive testing is required.

Functional testing will have to be done by enabling certain log messages
and checking for their presence on stderr or files.

Because it will be possible to dynamically enable logging, we need to
stress test this by continuously enabling and disabling logging while
running applications.

The logging framework will be tested using unit tests.

Risks and Assumptions
---------------------

The design outlined above may not satisfy all uses of logging in the JVM
today. If that is the case, the design will have to be revisited.


Impact
------

  - Compatibility: Log message formats will change and possibly the
    meaning of some JVM options.
  - Security: File permissions need to be verified.
  - Performance/scalability: Performance will be impacted if lots of
    logging is enabled.
  - User experience: Command-line options will change. Logging output
    will change.
  - I18n/L10n: Log messages will not be localized or internationalized.
  - Documentation: The new options and their usage will have to be documented.


Comments
Fixed minor typo in example - see JDK-8225049
10-09-2024

There was no integration issue associated with this JEP so we have no record of the changeset used to integrate it - so here it is: http://hg.openjdk.java.net/jdk/jdk/rev/96e348cb0442 Review thread: https://mail.openjdk.org/pipermail/hotspot-dev/2015-September/019782.html
05-10-2022

There are a few points of disconnect from the present tty/xtty mechanism and the proposed logging. Although the JEP does not call for the demolition of the old logging mechanisms, the differences will need to be resolved some way or other if the new mechanisms are to have their maximum benefit. Here are some notes that may help us do the resolution. 1. Logging events are produced by threads but are merged up into a linear sequence (in the tty/xtty stream). De-merging will require the "tid" decoration to be present on every line/record. The existing xtty mechanism inserts non-records (xml markup) between output from different threads. This is (usually) easier to work with when reading logs, and does not present the user with the choice between suppressing noise and seeing thread output boundaries. 2. If logs are directed to multiple output files, interleaving of events will be lost, unless timestamps are extracted and records re-merged after execution. This is probably OK if done at user request, but is a risk of information loss. This may happen if unsupported XML-based logging mechanisms are split from the new log streams. The merged sequencing is (currently) often important for debugging. For example, compiler-related de-optimization events (formatted as XML records) are sequenced with ordinary JVM "tty" output. Let's continue to provide for sequencing by some other means if those streams are separated. 3. The PrintAssembly and similar dump options produce large amounts of output. Will they also be supported by configurable output options, or is that only for log events that are oriented towards decorated single lines? 4. Some dump options (PrintAssembly again) produce XML markup as well as flat text, to mark JVM-introduced annotations on object code. A mix of flat text and markup is important in such cases. Can the logging mechanism be made compatible with such markup? The previous mechanism was made compatible, by the expedient of escaping markup characters (like < > &) in the log file, leaving room for unambiguous insertion of markup. 5. Existing XML-based logging uses XML element attributes to convey decorations, especially threads and (VM-relative) timestamps. These decorations should be upgraded to be compatible with the new decorations, allowing post-processing to "see" common artifacts that affect event interleaving or partitioning. 6. Single-thread logs appear to be important, at least for JIT compiler thread logs produced by -XX:+LogCompilation. JIT logs are per-thread, so that the volume of logged information does not perturb concurrency. Log data is buffered per thread and assembled into "hotspot.log" only at JVM exit. Such per-thread buffered design is perhaps implicit in the "lots of loggers" design proposed by this JEP, but the efficient binding to threads may impact the internal design of the new loggers. 7. Multi-line transactional log events are proposed by this JEP. The current expression of this (besides per-thread logging) is the ttyLocker syntax in the HotSpot sources, which does not buffer transactions but blocks racers; this is not always a good idea but works for infrequent dumps which contain begin/end markup spans or have similar integrity requirements. Will ttyLocker be retrofitted? 8. Multi-line log events in the current system heavily use locally contextual information to maintain their integrity. This allows lines to be "naked" of per-line decorations, making logged data far easier to read. It seems there should be similar provision for such multi-line sharing of decorations, in the new scheme, at least for XML-based log data, which naturally subdivide into nested scopes, each consisting of "naked" lines of data, or singled "decorated" XML elements. 9. Perhaps the most extreme application of contextual markup is the use of "id" style attributes to allow the JIT logger to name a metadatum just once per scope (compilation task). This allows a small-internal ID number to refer locally to a class, method, field, etc., with the name being spelled out once per scope, at first use. This leads to special "id definition" log events which mix in with the nest of compiler-generated events. Example of third-party post-processing tool interacting with log markup: http://mail.openjdk.java.net/pipermail/hotspot-dev/2014-February/012686.html Example of interleaved thread events (including internal JIT signals and JVM printed output): <writer thread='7171'/> <task_queued compile_id='2' method='java/lang/Integer rotateLeft (II)I' bytes='9' count='5632' iicount='5632' level='1' blocking='1' stamp='1.605' comment='tiered' hot_count='5632'/> <writer thread='17667'/> 1605 2 b 1 java.lang.Integer::rotateLeft (9 bytes) <nmethod compile_id='2' compiler='C1' level='1' entry='0x000000010cfb8be0' size='752' address='0x000000010cfb8a90' relocation_offset='288' insts_offset='336' stub_offset='496' scopes_data_offset='688' scopes_pcs_offset='696' dependencies_offset='744' oops_offset='680' method='java/lang/Integer rotateLeft (II)I' bytes='9' count='5632' iicount='5632' stamp='1.608'/> <make_not_entrant thread='17667' compile_id='1' compiler='C1' level='3' stamp='1.608'/> 1607 1 3 java.lang.Integer::rotateLeft (9 bytes) made not entrant Example of compile task log segment: <task compile_id='56' method='java/util/HashMap addEntry (ILjava/lang/Object;Ljava/lang/Object;I)V' bytes='69' count='256' iicount='256' level='3' blocking='1' stamp='2.423'> <klass id='712' name='java/util/HashMap' flags='1'/> <type id='616' name='void'/> <type id='614' name='int'/> <method id='717' holder='712' name='resize' return='616' arguments='614' flags='0' bytes='57' iicount='10'/> <dependency type='unique_concrete_method' ctxk='712' x='717'/> <dependency type='unique_concrete_method' ctxk='712' x='717'/> <task_done success='1' nmsize='1872' count='256' inlined_bytes='6' stamp='2.438'/> </task> Example of flat-text disassembly with embedded XML entities (&apos;): Decoding compiled method 0x00007f9230e15550: Code: [Entry Point] [Verified Entry Point] [Constants] # {method} {0x00007f922f3a2a18} &apos;spread&apos; &apos;(I)I&apos; in public synchronized &apos;java/util/concurrent/ConcurrentHashMap&apos; # parm0: rsi = int # [sp+0x40] (sp of caller) ;; block B1 [0, 0] 0x00007f9230e156a0: mov %eax,-0x16000(%rsp) 0x00007f9230e156a7: push %rbp 0x00007f9230e156a8: sub $0x30,%rsp 0x00007f9230e156ac: movabs $0x7f922f4911d8,%rax ; {metadata(method data for {method} {0x00007f922f3a2a18} &apos;spread&apos; &apos;(I)I&apos; in public synchronized &apos;java/util/concurrent/ConcurrentHashMap&apos;)}
10-09-2015

Currently we have support for listing tags, levels and decorators via DCMD. Similar functionality probably should be added to the command line along with some examples, like you suggest.
20-07-2015

See http://cr.openjdk.java.net/~farvidsson/JEP-158/JEP-158_Illustration.png for some illustrations of the new tag based system. EDIT: This is no longer accurate, a new illustration will be updated to reflect the latest changes.
20-07-2015

The command line syntax is missing the list of possible tags, levels, and decorators.
17-07-2015

Providing "help" for this features seems like it will be a challenge. The user will want quick access to the set of all tags, levels, and decorators (not have to reference a wiki), and also want basic examples readily available. To date -X options have been pretty easily documented (syntax and usage) with one line of help output. -Xlog will not be. What will the -Xlog help line look like? Will there be a way to get detailed help from the java command line? I was thinking the help line might simply be: -Xlog:<opts> control JVM logging. Use -Xlog:help for details. That leaves an opening for providing more help from the command line, without polluting the "java -X" help output.
17-07-2015

The illustration has an example "@A+B". This equates to the set of everything in both A and B, but not in anything else. I see no description in this JEP of what '@' means.
17-07-2015

The syntax for set operations (in the illustration) seems somewhat unintuitive. A+B would normally be a union not intersection. And using "off" rather than something algebraic seems inconsistent.
28-05-2015

The JEP was updated with an Integration Date and tasks were created for implementation and test implementation. Implementation is feature complete and tests are added to have a test coverage above 85%.
16-10-2014