-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Switch from Lager to the new Erlang Logger API for logging #2861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
3500345
to
ad0891c
Compare
3417d2a
to
b0457df
Compare
Why was |
There is a subtle change to severity formatting in the logs. Note how it uses
|
24920d4
to
13b8421
Compare
Erlang Logger does not offer a way to force log rotation. However it will detect correctly when a file was rotated by an external tool. We can restore |
That's me who wanted aligned messages. It made the logs much more readable during development. I plan to make this configurable (it is already in the code), but I don't know yet how to expose the new settings. I would like to have more feedback from the Platform team because they will need the JSON structure to be configurable as well probably. Once I have more input, I can figure out a good way to expose the configuration. |
Thank you for the patch for Erlang 24. I squashed it in the first commit. |
@dumbbell I suspect there is a lot of systems that depend on |
Speaking of Windows, a bit of research yields this comment which suggests that external log rotation is indeed something that Windows users cannot use and/or frown upon. |
deps/rabbit/apps/rabbitmq_prelaunch/src/rabbit_logger_std_h.erl
Outdated
Show resolved
Hide resolved
8f11399
to
ff5a42a
Compare
We have lost support for log.console = false
log.default.level = warning
log.connection.level = error doesn't have the desired effect (the node logs at |
a188968
to
e22ed70
Compare
We discussed this outside of GitHub: the reason is that when the node is started using |
816ba9c
to
e6f6c18
Compare
The latest changes (squashed into the main commit and force-pushed) include:
|
1ca1125
to
752f1a6
Compare
9ecd493
to
59103bf
Compare
The configuration remains the same for the end-user. The only exception is the log root directory: it is now set through the `log_root` application env. variable in `rabbit`. People using the Cuttlefish-based configuration file are not affected by this exception. The main change is how the logging facility is configured. It now happens in `rabbit_prelaunch_logging`. The `rabbit_lager` module is removed. The supported outputs remain the same: the console, text files, the `amq.rabbitmq.log` exchange and syslog. The message text format slightly changed: the timestamp is more precise (now to the microsecond) and the level can be abbreviated to always be 4-character long to align all messages and improve readability. Here is an example: 2021-03-03 10:22:30.377392+01:00 [dbug] <0.229.0> == Prelaunch DONE == 2021-03-03 10:22:30.377860+01:00 [info] <0.229.0> 2021-03-03 10:22:30.377860+01:00 [info] <0.229.0> Starting RabbitMQ 3.8.10+115.g071f3fb on Erlang 23.2.5 2021-03-03 10:22:30.377860+01:00 [info] <0.229.0> Licensed under the MPL 2.0. Website: https://rabbitmq.com The example above also shows that multiline messages are supported and each line is prepended with the same prefix (the timestamp, the level and the Erlang process PID). JSON is also supported as a message format and now for any outputs. Indeed, it is possible to use it with e.g. syslog or the exchange. Here is an example of a JSON-formatted message sent to syslog: Mar 3 11:23:06 localhost rabbitmq-server[27908] <0.229.0> - {"time":"2021-03-03T11:23:06.998466+01:00","level":"notice","msg":"Logging: configured log handlers are now ACTIVE","meta":{"domain":"rabbitmq.prelaunch","file":"src/rabbit_prelaunch_logging.erl","gl":"<0.228.0>","line":311,"mfa":["rabbit_prelaunch_logging","configure_logger",1],"pid":"<0.229.0>"}} For quick testing, the values accepted by the `$RABBITMQ_LOGS` environment variables were extended: * `-` still means stdout * `-stderr` means stderr * `syslog:` means syslog on localhost * `exchange:` means logging to `amq.rabbitmq.log` `$RABBITMQ_LOG` was also extended. It now accepts a `+json` modifier (in addition to the existing `+color` one). With that modifier, messages are formatted as JSON intead of plain text. The `rabbitmqctl rotate_logs` command is deprecated. The reason is Logger does not expose a function to force log rotation. However, it will detect when a file was rotated by an external tool. From a developer point of view, the old `rabbit_log*` API remains supported, though it is now deprecated. It is implemented as regular modules: there is no `parse_transform` involved anymore. In the code, it is recommended to use the new Logger macros. For instance, `?LOG_INFO(Format, Args)`. If possible, messages should be augmented with some metadata. For instance (note the map after the message): ?LOG_NOTICE("Logging: switching to configured handler(s); following " "messages may not be visible in this log output", #{domain => ?RMQLOG_DOMAIN_PRELAUNCH}), Domains in Erlang Logger parlance are the way to categorize messages. Some predefined domains, matching previous categories, are currently defined in `rabbit_common/include/logging.hrl` or headers in the relevant plugins for plugin-specific categories. At this point, very few messages have been converted from the old `rabbit_log*` API to the new macros. It can be done gradually when working on a particular module or logging. The Erlang builtin console/file handler, `logger_std_h`, has been forked because it lacks date-based file rotation. The configuration of date-based rotation is identical to Lager. Once the dust has settled for this feature, the goal is to submit it upstream for inclusion in Erlang. The forked module is calld `rabbit_logger_std_h` and is based `logger_std_h` in Erlang 23.0.
... from `rabbit_log:*` calls. Many rabbitmq_peer_discovery_consul testcases are executed outside of a RabbitMQ server node. When we had Lager `parse_transform` enabled, calls to `rabbit_log` were converted to something which happened to not break when executed outside of RabbitMQ. Now that `rabbit_log` calls are kept (there is no `parse_transform`), the missing dependency to rabbit_common in the common_test node surfaces nad hilights the breakage which has always been there. Calls to `rabbit_log` are now replaced with Logger macros and this works again, even in the context of the common_test node.
it no longer depends on Lager
Lager strips trailing newline characters but OTP logger with the default formatter adds a newline at the end. To avoid unintentional multi-line log messages we have to revisit most messages logged. Some log entries are intentionally multiline, others are printed to stdout directly: newlines are required there for sensible formatting.
777ad85
to
97ff62d
Compare
... if it is set in the configuration file. Here is an example of that use case: * The official Docker image sets $RABBITMQ_LOGS=- * A user of that image adds a configuration file with: log.console.level = debug The initial implementation, introduced in #2861, considered that if the output is overriden in the environment (through $RABBITMQ_LOGS), any output configuration in the configuration file is ignored. The problem is that the output-specific configuration could also set the log level which is not changed by $RABBITMQ_LOGS. This patch fixes that by keeping the log level from the configuration (if it is set obviously) even if the output is overridden in the environment.
... if it is set in the configuration file. Here is an example of that use case: * The official Docker image sets RABBITMQ_LOGS=- in the environment * A user of that image adds a configuration file with: log.console.level = debug The initial implementation, introduced in #2861, considered that if the output is overriden in the environment (through $RABBITMQ_LOGS), any output configuration in the configuration file is ignored. The problem is that the output-specific configuration could also set the log level which is not changed by $RABBITMQ_LOGS. This patch fixes that by keeping the log level from the configuration (if it is set obviously) even if the output is overridden in the environment.
... if it is set in the configuration file. Here is an example of that use case: * The official Docker image sets RABBITMQ_LOGS=- in the environment * A user of that image adds a configuration file with: log.console.level = debug The initial implementation, introduced in #2861, considered that if the output is overriden in the environment (through $RABBITMQ_LOGS), any output configuration in the configuration file is ignored. The problem is that the output-specific configuration could also set the log level which is not changed by $RABBITMQ_LOGS. This patch fixes that by keeping the log level from the configuration (if it is set obviously) even if the output is overridden in the environment.
Switch from Lager to the new Erlang Logger API for logging
The configuration remains the same for the end-user. The only exception is the log root directory: it is now set through the
log_root
application env. variable inrabbit
. People using the Cuttlefish-based configuration file are not affected by this exception.The main change is how the logging facility is configured. It now happens in
rabbit_prelaunch_logging
. Therabbit_lager
module is removed.The supported outputs remain the same: the console, text files, the
amq.rabbitmq.log
exchange and syslog.The message text format slightly changed: the timestamp is more precise (now to the microsecond) and the level can be abbreviated to always be 4-character long to align all messages and improve readability. Here is an example:
The example above also shows that multiline messages are supported and each line is prepended with the same prefix (the timestamp, the level and the Erlang process PID).
JSON is also supported as a message format and now for any outputs. Indeed, it is possible to use it with e.g. syslog or the exchange. Here is an example of a JSON-formatted message sent to syslog:
For quick testing, the values accepted by the
$RABBITMQ_LOGS
environment variables were extended:-
still means stdout-stderr
means stderrsyslog:
means syslog on localhostexchange:
means logging toamq.rabbitmq.log
$RABBITMQ_LOG
was also extended. It now accepts a+json
modifier (in addition to the existing+color
one). With that modifier, messages are formatted as JSON intead of plain text.The
rabbitmqctl rotate_logs
command is deprecated. The reason is Logger does not expose a function to force log rotation. However, it will detect when a file was rotated by an external tool.From a developer point of view, the old
rabbit_log*
API remains supported, though it is now deprecated. It is implemented as regular modules: there is noparse_transform
involved anymore.In the code, it is recommended to use the new Logger macros. For instance,
?LOG_INFO(Format, Args)
. If possible, messages should be augmented with some metadata. For instance (note the map after the message):Domains in Erlang Logger parlance are the way to categorize messages. Some predefined domains, matching previous categories, are currently defined in
rabbit_common/include/logging.hrl
or headers in the relevant plugins for plugin-specific categories.At this point, very few messages have been converted from the old
rabbit_log*
API to the new macros. It can be done gradually when working on a particular module or logging.The Erlang builtin console/file handler,
logger_std_h
, has been forked because it lacks date-based file rotation. The configuration of date-based rotation is identical to Lager. Once the dust has settled for this feature, the goal is to submit it upstream for inclusion in Erlang. The forked module is calldrabbit_logger_std_h
and is basedlogger_std_h
in Erlang 23.0.