- Loggers, Appenders and Layouts
- Logger hierarchy
- Log level
- Layouts
- Configuration
- Usage
- Logging config migration
- Log record format changes
The way logging works in Kibana is inspired by log4j 2
logging framework used by Elasticsearch.
The main idea is to have consistent logging behaviour (configuration, log format etc.) across the entire Elastic Stack
where possible.
Kibana logging system has three main components: loggers, appenders and layouts. These components allow us to log messages according to message type and level, and to control how these messages are formatted and where the final logs will be displayed or stored.
Loggers define what logging settings should be applied at the particular context.
Appenders define where log messages are displayed (eg. stdout or console) and stored (eg. file on the disk).
Layouts define how log messages are formatted and what type of information they include.
Every logger has its unique name or context that follows hierarchical naming rule. The logger is considered to be an
ancestor of another logger if its name followed by a .
is a prefix of the descendant logger name. For example logger
with a.b
context is an ancestor of logger with a.b.c
context. All top-level loggers are descendants of special
logger with root
context that resides at the top of the logger hierarchy. This logger always exists and
fully configured.
Developer can configure log level and appenders that should be used within particular context. If logger configuration specifies only log level then appenders configuration will be inherited from the ancestor logger.
Note: in the current implementation log messages are only forwarded to appenders configured for a particular logger
context or to appenders of the closest ancestor if current logger doesn't have any appenders configured. That means that
we don't support so called appender additivity when log messages are forwarded to every distinct appender within
ancestor chain including root
.
Currently we support the following log levels: all, fatal, error, warn, info, debug, trace, off. Levels are ordered, so all > fatal > error > warn > info > debug > trace > off. A log record is being logged by the logger if its level is higher than or equal to the level of its logger. Otherwise, the log record is ignored.
The all and off levels can be used only in configuration and are just handy shortcuts that allow developer to log every log record or disable logging entirely for the specific context.
Every appender should know exactly how to format log messages before they are written to the console or file on the disk.
This behaviour is controlled by the layouts and configured through appender.layout
configuration property for every
custom appender (see examples in Configuration). Currently we don't define any default layout for the
custom appenders, so one should always make the choice explicitly.
There are two types of layout supported at the moment: pattern
and json
.
With pattern
layout it's possible to define a string pattern with special placeholders %conversion_pattern
(see the table below) that
will be replaced with data from the actual log message. By default the following pattern is used:
[%date][%level][%logger]%meta %message
. Also highlight
option can be enabled for pattern
layout so that
some parts of the log message are highlighted with different colors that may be quite handy if log messages are forwarded
to the terminal with color support.
pattern
layout uses a sub-set of log4j2 pattern syntax
and doesn't implement all log4j2
capabilities. The conversions that are provided out of the box are:
Outputs the level of the logging event.
Example of %level
output:
TRACE
DEBUG
INFO
Outputs the name of the logger that published the logging event.
Example of %logger
output:
server
server.http
server.http.Kibana
Outputs the application supplied message associated with the logging event.
Outputs the entries of meta
object data in json format, if one is present in the event.
Example of %meta
output:
// Meta{from: 'v7', to: 'v8'}
'{"from":"v7","to":"v8"}'
// Meta empty object
'{}'
// no Meta provided
''
Outputs the date of the logging event. The date conversion specifier may be followed by a set of braces containing a name of predefined date format and canonical timezone name.
Timezone name is expected to be one from TZ database name
Example of %date
output:
Conversion pattern | Example |
---|---|
%date |
2012-02-01T14:30:22.011Z uses ISO8601 format by default |
%date{ISO8601} |
2012-02-01T14:30:22.011Z |
%date{ISO8601_TZ} |
2012-02-01T09:30:22.011-05:00 ISO8601 with timezone |
%date{ISO8601_TZ}{America/Los_Angeles} |
2012-02-01T06:30:22.011-08:00 |
%date{ABSOLUTE} |
09:30:22.011 |
%date{ABSOLUTE}{America/Los_Angeles} |
06:30:22.011 |
%date{UNIX} |
1328106622 |
%date{UNIX_MILLIS} |
1328106622011 |
Outputs the process ID.
With json
layout log messages will be formatted as JSON strings that include timestamp, log level, context, message
text and any other metadata that may be associated with the log message itself.
As any configuration in the platform, logging configuration is validated against the predefined schema and if there are any issues with it, Kibana will fail to start with the detailed error message.
Once the code acquired a logger instance it should not care about any runtime changes in the configuration that may happen: all changes will be applied to existing logger instances under the hood.
Here is the configuration example that can be used to configure loggers, appenders and layouts:
logging:
appenders:
console:
kind: console
layout:
kind: pattern
highlight: true
file:
kind: file
path: /var/log/kibana.log
layout:
kind: pattern
custom:
kind: console
layout:
kind: pattern
pattern: "[%date][%level] %message"
json-file-appender:
kind: file
path: /var/log/kibana-json.log
root:
appenders: [console, file]
level: error
loggers:
- context: plugins
appenders: [custom]
level: warn
- context: plugins.pid
level: info
- context: server
level: fatal
- context: optimize
appenders: [console]
- context: telemetry
level: all
appenders: [json-file-appender]
Here is what we get with the config above:
Context | Appenders | Level |
---|---|---|
root | console, file | error |
plugins | custom | warn |
plugins.pid | custom | info |
server | console, file | fatal |
optimize | console | error |
telemetry | json-file-appender | all |
The root
logger has a dedicated configuration node since this context is special and should always exist. By
default root
is configured with info
level and default
appender that is also always available. This is the
configuration that all custom loggers will use unless they're re-configured explicitly.
For example to see all log messages that fall back on the root
logger configuration, just add one line to the configuration:
logging.root.level: all
Or disable logging entirely with off
:
logging.root.level: off
Usage is very straightforward, one should just get a logger for a specific context and use it to log messages with different log level.
const logger = kibana.logger.get('server');
logger.trace('Message with `trace` log level.');
logger.debug('Message with `debug` log level.');
logger.info('Message with `info` log level.');
logger.warn('Message with `warn` log level.');
logger.error('Message with `error` log level.');
logger.fatal('Message with `fatal` log level.');
const loggerWithNestedContext = kibana.logger.get('server', 'http');
loggerWithNestedContext.trace('Message with `trace` log level.');
loggerWithNestedContext.debug('Message with `debug` log level.');
And assuming logger for server
context with console
appender and trace
level was used, console output will look like this:
[2017-07-25T18:54:41.639Z][TRACE][server] Message with `trace` log level.
[2017-07-25T18:54:41.639Z][DEBUG][server] Message with `debug` log level.
[2017-07-25T18:54:41.639Z][INFO ][server] Message with `info` log level.
[2017-07-25T18:54:41.639Z][WARN ][server] Message with `warn` log level.
[2017-07-25T18:54:41.639Z][ERROR][server] Message with `error` log level.
[2017-07-25T18:54:41.639Z][FATAL][server] Message with `fatal` log level.
[2017-07-25T18:54:41.639Z][TRACE][server.http] Message with `trace` log level.
[2017-07-25T18:54:41.639Z][DEBUG][server.http] Message with `debug` log level.
The log will be less verbose with warn
level for the server
context:
[2017-07-25T18:54:41.639Z][WARN ][server] Message with `warn` log level.
[2017-07-25T18:54:41.639Z][ERROR][server] Message with `error` log level.
[2017-07-25T18:54:41.639Z][FATAL][server] Message with `fatal` log level.
Compatibility with the legacy logging system is assured until the end of the v7
version.
All log messages handled by root
context are forwarded to the legacy logging service. If you re-write
root appenders, make sure that it contains default
appender to provide backward compatibility.
Note: If you define an appender for a context, the log messages aren't handled by the
root
context anymore and not forwarded to the legacy logging service.
By default logs in stdout. With new Kibana logging you can use pre-existing console
appender or
define a custom one.
logging:
loggers:
- context: your-plugin
appenders: [console]
Logs in a file if given file path. You should define a custom appender with kind: file
logging:
appenders:
file:
kind: file
path: /var/log/kibana.log
layout:
kind: pattern
loggers:
- context: your-plugin
appenders: [file]
Defines the format of log output. Logs in JSON if true
. With new logging config you can adjust
the output format with layouts.
Suppresses all logging output other than error messages. With new logging, config can be achieved with adjusting minimum required logging level
loggers:
- context: my-plugin
appenders: [console]
level: error
# or for all output
logging.root.level: error
Suppresses all logging output.
logging.root.level: off
Logs all events
logging.root.level: all
Set to the canonical timezone id to log events using that timezone. New logging config allows
to specify timezone for layout: pattern
.
logging:
appenders:
custom-console:
kind: console
layout:
kind: pattern
highlight: true
pattern: "[%level] [%date{ISO8601_TZ}{America/Los_Angeles}][%logger] %message"
Define a custom logger for a specific context.
TBD
Parameter | Platform log record in pattern format | Legacy Platform log record text format |
---|---|---|
@timestamp | ISO8601 2012-01-31T23:33:22.011Z |
Absolute 23:33:22.011 |
context | parent.child |
['parent', 'child'] |
level | DEBUG |
['debug'] |
meta | stringified JSON object {"to": "v8"} |
N/A |
pid | can be configured as %pid |
N/A |
Parameter | Platform log record in json format | Legacy Platform log record json format |
---|---|---|
@timestamp | ISO8601_TZ 2012-01-31T23:33:22.011-05:00 |
ISO8601 2012-01-31T23:33:22.011Z |
context | context: parent.child |
tags: ['parent', 'child'] |
level | level: DEBUG |
tags: ['debug'] |
meta | separate property "meta": {"to": "v8"} |
merged in log record {... "to": "v8"} |
pid | pid: 12345 |
pid: 12345 |
type | N/A | type: log |
error | { message, name, stack } |
{ message, name, stack, code, signal } |