Quellcode durchsuchen

ft: 格式化

master
SisMaker vor 4 Jahren
Ursprung
Commit
e31ef4326f
8 geänderte Dateien mit 546 neuen und 915 gelöschten Zeilen
  1. +44
    -413
      README.md
  2. +50
    -50
      eRum.sample.config
  3. +28
    -28
      src/eRum.erl
  4. +2
    -2
      src/formatter/rumFormatter.erl
  5. +151
    -151
      src/misc/rumErrLoggerH.erl
  6. +16
    -16
      src/misc/rumTruncIo.erl
  7. +4
    -4
      test/crash_statem.erl
  8. +251
    -251
      test/lager_test_backend.erl

+ 44
- 413
README.md Datei anzeigen

@ -1,13 +1,6 @@
# 基于lager 3.9.0 rewrite
Overview
--------
Lager (as in the beer) is a logging framework for Erlang. Its purpose is to provide a more traditional way to perform
logging in an erlang application that plays nicely with traditional UNIX logging tools like logrotate and syslog.
[Travis-CI](http://travis-ci.org/erlang-lager/lager) :: [![Build Status](https://travis-ci.org/erlang-lager/lager.svg?branch=master)]
[![Hex pm](https://img.shields.io/hexpm/v/lager)](https://hex.pm/packages/lager)
eRum is a Erlang logger. 基于lager3.9.0 rewrite
Features
--------
@ -23,95 +16,60 @@ Features
* Optional feature to bypass log size truncation ("unsafe")
* Supports internal time and date based rotation, as well as external rotation tools
* Syslog style log level comparison flags
* Colored terminal output (requires R16+)
* Map support (requires 17+)
* Colored terminal output
* Optional load shedding by setting a high water mark to kill (and reinstall)
a sink after a configurable cool down timer
Contributing
------------
We welcome contributions from the community. We are always excited to get ideas for improving lager.
If you are looking for an idea to help out, please take a look at our open issues - a number of them are tagged
with [Help Wanted](https://github.com/erlang-lager/lager/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22)
and [Easy](https://github.com/erlang-lager/lager/issues?q=is%3Aopen+is%3Aissue+label%3AEasy) - some of them are tagged
as both! We are happy to mentor people get started with any of these issues, and they don't need prior discussion.
That being said, before you send large changes please open an issue first to discuss the change you'd like to make along
with an idea of your proposal to implement that change.
### PR guidelines ###
* Large changes without prior discussion are likely to be rejected.
* Changes without test cases are likely to be rejected.
* Please use the style of the existing codebase when submitting PRs.
We review PRs and issues at least once a month as described below.
OTP Support Policy
------------------
The lager maintainers intend to support the past three OTP releases from current on the main 3.x branch of the project.
As of August 2019 that includes 22, 21 20
Lager may or may not run on older OTP releases but it will only be guaranteed tested on the previous three OTP releases.
If you need a version of lager which runs on older OTP releases, we recommend you use either the 3.4.0 release or the
2.x branch.
Monthly triage cadence
----------------------
We have (at least) monthly issue and PR triage for lager in the #lager room on the
[freenode](https://freenode.net) IRC network every third Thursday at 2 pm US/Pacific, 10 pm UTC. You are welcome to join
us there to ask questions about lager or participate in the triage.
* rewrite term format fun, it's more efficient
Usage
-----
To use lager in your application, you need to define it as a rebar dep or have some other way of including it in
Erlang's path. You can then add the following option to the erlang compiler flags:
To use eRum in your application, you need to define it as a rebar dep or have some other way of including it in Erlang's
path. You can then add the following option to the erlang compiler flags:
```erlang
{parse_transform, lager_transform}
{parse_transform, rumTransform}
```
Alternately, you can add it to the module you wish to compile with logging enabled:
```erlang
-compile([{parse_transform, lager_transform}]).
-compile([{parse_transform, rumTransform}]).
```
Before logging any messages, you'll need to start the lager application. The lager module's `start` function takes care
of loading and starting any dependencies lager requires.
Before logging any messages, you'll need to start the eRum application. The eRum module's `start` function takes care of
loading and starting any dependencies eRum requires.
```erlang
lager:start().
eRum:start().
```
You can also start lager on startup with a switch to `erl`:
You can also start eRum on startup with a switch to `erl`:
```erlang
erl -pa path/to/lager/ebin -s lager
erl -pa path/to/eRum/ebin -s eRum
```
Once you have built your code with lager and started the lager application, you can then generate log messages by doing
Once you have built your code with eRum and started the eRum application, you can then generate log messages by doing
the following:
```erlang
lager:error("Some message")
eRum:error("Some message")
```
Or:
```erlang
lager:warning("Some message with a term: ~p", [Term])
eRum:warning("Some message with a term: ~p", [Term])
```
The general form is `lager:Severity()` where `Severity` is one of the log levels mentioned above.
The general form is `eRum:Severity()` where `Severity` is one of the log levels mentioned above.
Configuration
-------------
To configure lager's backends, you use an application variable (probably in your app.config):
To configure eRum's backends, you use an application variable (probably in your app.config):
```erlang
{lager, [
{eRum, [
{log_root, "/var/log/hello"},
{handlers, [
{lager_console_backend, [{level, info}]},
@ -241,7 +199,7 @@ similar to Erlang's
* A tuple of `{pterm, atom(), semi-iolist()}` will attempt to lookup the value of the specified atom from the
persistent_term feature added in OTP 21.2. The default value is the specified semi-iolist(). The default value
will be used if the key cannot be found or the if this formatting term is specified on an OTP release before OTP
21.
21.
Examples:
@ -525,21 +483,21 @@ The module should provide the following callbacks as `lager_rotator_behaviour`
```erlang
%% @doc Create a log file
-callback(create_logfile(Name::list(), Buffer::{integer(), integer()} | any()) ->
{ok, {FD::file:io_device(), Inode::integer(), Size::integer()}} | {error, any()}).
-callback(create_logfile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
{ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}).
%% @doc Open a log file
-callback(open_logfile(Name::list(), Buffer::{integer(), integer()} | any()) ->
{ok, {FD::file:io_device(), Inode::integer(), Size::integer()}} | {error, any()}).
-callback(open_logfile(Name :: list(), Buffer :: {integer(), integer()} | any()) ->
{ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}).
%% @doc Ensure reference to current target, could be rotated
-callback(ensure_logfile(Name::list(), FD::file:io_device(), Inode::integer(),
Buffer::{integer(), integer()} | any()) ->
{ok, {FD::file:io_device(), Inode::integer(), Size::integer()}} | {error, any()}).
-callback(ensure_logfile(Name :: list(), FD :: file:io_device(), Inode :: integer(),
Buffer :: {integer(), integer()} | any()) ->
{ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}).
%% @doc Rotate the log file
-callback(rotate_logfile(Name::list(), Count::integer()) ->
ok).
-callback(rotate_logfile(Name :: list(), Count :: integer()) ->
ok).
```
Syslog Support
@ -837,7 +795,7 @@ This example would work with `on_emit` but could be unsafe to use with
-export([my_callback/0]).
my_callback() ->
my_app_serv:call('some options').
my_app_serv:call('some options').
```
This example would be to safe to work with both `on_emit` and `on_log`
@ -846,14 +804,14 @@ This example would be to safe to work with both `on_emit` and `on_log`
-export([my_callback/0]).
my_callback() ->
try my_app_serv:call('some options') of
Result ->
Result
catch
_ ->
%% You could define any traditional iolist elements you wanted here
undefined
end.
try my_app_serv:call('some options') of
Result ->
Result
catch
_ ->
%% You could define any traditional iolist elements you wanted here
undefined
end.
```
Note that the callback can be any Module:Function/0. It does not have be part of your application. For example you could
@ -866,19 +824,19 @@ Examples:
-export([reductions/0]).
reductions() ->
proplists:get_value(reductions, erlang:process_info(self())).
proplists:get_value(reductions, erlang:process_info(self())).
```
```erlang
-export([seq_trace/0]).
seq_trace() ->
case seq_trace:get_token(label) of
{label, TraceLabel} ->
TraceLabel;
_ ->
undefined
end.
case seq_trace:get_token(label) of
{label, TraceLabel} ->
TraceLabel;
_ ->
undefined
end.
```
**IMPORTANT**: Since `on_emit` relies on function calls injected at the point where a log message is emitted, your
@ -974,330 +932,3 @@ appname_maint_12345@127.0.0.1).
If you intend to use tracing with this feature, make sure the second parameter to start_handler and the `id` parameter
match. Thus when the custom group_leader process exits, lager will remove any associated traces for that handler.
Elixir Support
--------------
There are 2 ways in which Lager can be leveraged in an Elixir project:
1. Lager Backend for Elixir Logger
2. Directly
### Lager Backend for Elixir Logger
[Elixir's Logger](https://hexdocs.pm/logger/Logger.html) is the idiomatic way to add logging into elixir code. Logger
has a plug-in model, allowing for different logging [Backends](https://hexdocs.pm/logger/Logger.html#module-backends)
to be used without the need to change the logging code within your project.
This approach will benefit from the fact that most elixir libs and frameworks are likely to use the elixir Logger and as
such logging will all flow via the same logging mechanism.
In [elixir 1.5 support for parse transforms was deprecated](https://github.com/elixir-lang/elixir/issues/5762). Taking
the "Lager as a Logger Backend" approach is likely bypass any related regression issues that would be introduced into a
project which is using lager directly when updating to elixir 1.5.
There are open source elixir Logger backends for Lager available:
- [LagerLogger](https://github.com/PSPDFKit-labs/lager_logger)
- [LoggerLagerBackend](https://github.com/jonathanperret/logger_lager_backend)
### Directly
It is fully possible prior to elixir 1.5 to use lager and all its features directly.
After elixir 1.5 there is no support for parse transforms, and it is recommended to use an elixir wrapper for the lager
api that provides compile time log level exclusion via elixir macros when opting for direct use of lager.
Including Lager as a dependency:
``` elixir
# mix.exs
def application do
[
applications: [:lager],
erl_opts: [parse_transform: "lager_transform"]
]
end
defp deps do
[{:lager, "~> 3.2"}]
end
```
Example Configuration:
``` elixir
# config.exs
use Mix.Config
# Stop lager writing a crash log
config :lager, :crash_log, false
config :lager,
log_root: '/var/log/hello',
handlers: [
lager_console_backend: :info,
lager_file_backend: [file: "error.log", level: :error],
lager_file_backend: [file: "console.log", level: :info]
]
```
There is a known issue where Elixir's Logger and Lager both contest for the Erlang `error_logger` handle if used side by
side.
If using both add the following to your `config.exs`:
```elixir
# config.exs
use Mix.Config
# Stop lager redirecting :error_logger messages
config :lager, :error_logger_redirect, false
# Stop lager removing Logger's :error_logger handler
config :lager, :error_logger_whitelist, [Logger.ErrorHandler]
```
Example Usage:
``` elixir
:lager.error('Some message')
:lager.warning('Some message with a term: ~p', [term])
```
3.x Changelog
-------------
3.9.0 - 24 February 2021
* Bugfix: Try to make a log root of "log" more sensible (#540)
* Feature: Further adapt to OTP 24 (also remove pre OTP 21 code),
adopt Github Actions for tests
3.8.2 - 4 February 2021
* Bugfix: Make directory expansion return an absolute path (#535)
* Feature: Write crash.log under the log_root location (#536)
* Bugfix: Handle line numbering correctly in forthcoming OTP 24 release (#537)
3.8.1 - 28 August 2020
* Feature: Allow metadata fields to be whitelisted in log formatting (#514)
* Feature: Enable a persistent_term log formatter (#530) (#531)
* Bugfix: Handle gen_statem crashes in newer OTP releases correctly (#523)
* Cleanup: Add a hex badge (#525)
* Cleanup: Fix Travis CI badge link
* Policy: Officially ending support for OTP 20 (Support OTP 21, 22, 23)
3.8.0 - 9 August 2019
* Breaking API change: Modify the `lager_rotator_behaviour` to pass in a
file's creation time to `ensure_logfile/5` to be used to determine if
file has changed on systems where inodes are not available (i.e.
`win32`). The return value from `create_logfile/2`, `open_logfile/2` and
`ensure_logfile/5` now requires ctime to be returned (#509)
* Bugfix: ensure log file rotation works on `win32` (#509)
* Bugfix: ensure test suite passes on `win32` (#509)
* Bugfix: ensure file paths with Unicode are formatted properly (#510)
3.7.0 - 24 May 2019
* Policy: Officially ending support for OTP 19 (Support OTP 20, 21, 22)
* Cleanup: Fix all dialyzer errors
* Bugfix: Minor changes to FSM/statem exits in OTP 22.
3.6.10 - 30 April 2019
* Documentation: Fix pr_stacktrace invocation example (#494)
* Bugfix: Do not count suppressed messages for message drop counts (#499)
3.6.9 - 13 March 2019
* Bugfix: Fix file rotation on windows (#493)
3.6.8 - 21 December 2018
* Documentation: Document the error_logger_whitelist environment variable. (#489)
* Bugfix: Remove the built in handler inside of OTP 21 `logger` system. (#488)
* Bugfix: Cleanup unneeded check for is_map (#486)
* Bugfix: Cleanup ranch errors treated as cowboy errors (#485)
* Testing: Remove OTP 18 from TravisCI testing matrix
3.6.7 - 14 October 2018
* Bugfix: fix tracing to work with OTP21 #480
3.6.6 - 24 September 2018
* Bugfix: When printing records, handle an improper list correctly. #478
* Bugfix: Fix various tests and make some rotation code more explicit. #476
* Bugfix: Make sure not to miscount messages during high-water mark check. #475
3.6.5 - 3 September 2018
* Feature: Allow the console backend to redirect output to a remote node #469
* Feature: is_loggble - support for severity as atom #472
* Bugfix: Prevent silent dropping of messages when hwm is exceeded #467
* Bugfix: rotation - default log file not deleted #474
* Bugfix: Handle strange crash report from gen_statem #473
* Documentation: Various markup fixes: #468 #470
3.6.4 - 11 July 2018
* Bugfix: Reinstall handlers after a sink is killed #459
* Bugfix: Fix platform_define matching not to break on OSX Mojave #461
* Feature: Add support for installing a sys trace function #462
3.6.3 - 6 June 2018
* OTP 21 support
3.6.2 - 26 April 2018
* Bugfix: flush_threshold not working (#449)
* Feature: Add `node` as a formatting option (#447)
* Documentation: Update Elixir section with information about parse_transform (#446)
* Bugfix: Correct default console configuation to use "[{level,info}]" instead (#445)
* Feature: Pretty print lists of records at top level and field values with lager:pr (#442)
* Bugfix: Ignore return value of lager:dispatch_log in lager.hrl (#441)
3.6.1 - 1 February 2018
* Bugfix: Make a few corrections to the recent mailbox flushing changes (#436)
* Bugfix: add flush options to proplist validation (#439)
* Bugfix: Don't log when we dropped 0 messages (#440)
3.6.0 - 16 January 2018
* Feature: Support logging with macros per level (#419)
* Feature: Support custom file rotation handler; support hourly file
rotation (#420)
* Feature: Optionally reverse pretty stacktraces (so errors are
at the top and the failed function call is at the bottom.)
(#424)
* Bugfix: Handle OTP 20 gen_server failure where client pid
is dead. (#426)
* Feature: Optionally don't flush notify messages at
high water mark. (#427)
* Bugfix: Handle another stacktrace format (#429)
* Bugfix: Fix test failure using macros on OTP 18 (#430)
* Policy: Remove all code which supports R15 (#432)
3.5.2 - 19 October 2017
* Bugfix: Properly check for unicode characters in potentially deep
character list. (#417)
3.5.1 - 15 June 2017
* Doc fix: Missed a curly brace in an example. (#412)
* Feature: Dynamic metadata functions (#392) - It is now possible to
dynamically add metadata to lager messages. See the "dynamic
metadata" section above for more information.
* Doc fix: Add information about the "application" placeholder. (#414)
3.5.0 - 28 May 2017
* Bugfix: Support OTP 20 gen_event messages (#410)
* Feature: Enable console output to standard_error.
Convert to proplist configuration style (like file handler)
Deprecate previous configuration directives (#409)
* Bugfix: Enable the event shaper to filter messages before they're
counted; do not count application/supervisor start/stops
toward high water mark. (#411)
* Docs: Add PR guidelines; add info about the #lager chat room on freenode.
3.4.2 - 26 April 2017
* Docs: Document how to make lager use UTC timestamps (#405)
* Docs: Add a note about our triage cadence.
* Docs: Update lager_syslog URL
* Docs: Document placeholders for error_logger integration (#404)
* Feature: Add hex.pm metadata and full rebar3 support.
3.4.1 - 28 March 2017
* Docs: Added documentation around using lager in the context of elixir applications (#398)
* Bugfix: Properly expand paths when log_root is set. (#386)
* Policy: Removed R15 from Travis configuration
3.4.0 - 16 March 2017
* Policy: Adopt official OTP support policy. (This is the **last** lager 3.x release
that will support R15.)
* Test: Fix timeouts, R15 missing functions on possibly long-running tests in Travis. (#394, #395)
* Feature: capture and log metadata from error_logger messages (#397)
* Feature: Expose new trace filters and enable filter composition (#389)
* Feature: Log crashes from gen_fsm and gen_statem correctly (#391)
* Docs: Typo in badge URL (#390)
3.3.0 - 16 February 2017
* Docs: Fix documentation to make 'it' unambiguous when discussing asychronous
operation. (#387)
* Test: Fix test flappiness due to insufficient sanitation between test runs (#384, #385)
* Feature: Allow metadata only logging. (#380)
* Feature: Add an upper case severity formatter (#372)
* Feature: Add support for suppressing start/stop messages from supervisors (#368)
* Bugfix: Fix ranch crash messages (#366)
* Test: Update Travis config for 18.3 and 19.0 (#365)
3.2.4 - 11 October 2016
* Test: Fix dialyzer warnings.
3.2.3 - 29 September 2016
* Dependency: Update to goldrush 0.19
3.2.2 - 22 September 2016
* Bugfix: Backwards-compatibility fix for `{crash_log, undefined}` (#371)
* Fix documentation/README to reflect the preference for using `false`
as the `crash_log` setting value rather than `undefined` to indicate
that the crash log should not be written (#364)
* Bugfix: Backwards-compatibility fix for `lager_file_backend` "legacy"
configuration format (#374)
3.2.1 - 10 June 2016
* Bugfix: Recent `get_env` changes resulted in launch failure (#355)
* OTP: Support typed records for Erlang 19.0 (#361)
3.2.0 - 08 April 2016
* Feature: Optional sink killer to shed load when mailbox size exceeds a
configurable high water mark (#346)
* Feature: Export `configure_sink/2` so users may dynamically configure
previously setup and parse transformed sinks from their own code. (#342)
* Feature: Re-enable Travis CI and update .travis.yml (#340)
* Bugfix: Fix test race conditions for Travis CI (#344)
* Bugfix: Add the atom 'none' to the log_level() type so downstream
users won't get dialyzer failures if they use the 'none' log level. (#343)
* Bugfix: Fix typo in documentation. (#341)
* Bugfix: Fix OTP 18 test failures due to `warning_map/0` response
change. (#337)
* Bugfix: Make sure traces that use the file backend work correctly
when specified in lager configuration. (#336)
* Bugfix: Use `lager_app:get_env/3` for R15 compatibility. (#335)
* Bugfix: Make sure lager uses `id` instead of `name` when reporting
supervisor children failures. (The atom changed in OTP in 2014.) (#334)
* Bugfix: Make lager handle improper iolists (#327)
3.1.0 - 27 January 2016
* Feature: API calls to a rotate handler, sink or all. This change
introduces a new `rotate` message for 3rd party lager backends; that's
why this is released as a new minor version number. (#311)
3.0.3 - 27 January 2016
* Feature: Pretty printer for human readable stack traces (#298)
* Feature: Make error reformatting optional (#305)
* Feature: Optional and explicit sink for error_logger messages (#303)
* Bugfix: Always explicitly close a file after its been rotated (#316)
* Bugfix: If a relative path already contains the log root, do not add it again (#317)
* Bugfix: Configure and start extra sinks before traces are evaluated (#307)
* Bugfix: Stop and remove traces correctly (#306)
* Bugfix: A byte value of 255 is valid for Unicode (#300)
* Dependency: Bump to goldrush 0.1.8 (#313)

+ 50
- 50
eRum.sample.config Datei anzeigen

@ -1,56 +1,56 @@
[
{eRum, [
%% 是否开启颜色
{colored, false},
%% 颜色码配置
{colors, [
{debug, "\e[0;38m"},
{info, "\e[1;37m"},
{notice, "\e[1;36m"},
{warning, "\e[1;33m"},
{error, "\e[1;31m"},
{critical, "\e[1;35m"},
{alert, "\e[1;44m"},
{emergency, "\e[1;41m"}
]},
%% crash log cfg
%% 有效值 string | false
%% 为 false 的时候 没有 crash logger.
{crash_log, "log/crash.log"},
%% Maximum size in bytes of events in the crash log - defaults to 65536
{crash_log_msg_size, 65536},
%% Maximum size of the crash log in bytes, before its rotated, set to 0 to disable rotation - default is 0
{crash_log_size, 10485760},
%% What time to rotate the crash log - default is no time rotation. See the README for a description of this format.
{crash_log_date, "$D0"},
%% Number of rotated crash logs to keep, 0 means keep only the current one - default is 0
{crash_log_count, 5},
%% Crash Log Rotator Module - default is lager_rotator_default
{crash_log_rotator, lager_rotator_default},
%% Whether to redirect error_logger messages into the default lager_event sink - defaults to true
{error_logger_redirect, true},
%% How many messages per second to allow from error_logger before we start dropping them
{error_logger_hwm, 50},
%% How big the gen_event mailbox can get before it is
%% switched into sync mode. This value only applies to
%% the default sink; extra sinks can supply their own.
{async_threshold, 20},
%% Switch back to async mode, when gen_event mailbox size
%% decrease from `async_threshold' to async_threshold -
%% async_threshold_window. This value only applies to the
%% default sink; extra sinks can supply their own.
{async_threshold_window, 5}
%% 是否开启颜色
{colored, false},
%% 颜色码配置
{colors, [
{debug, "\e[0;38m"},
{info, "\e[1;37m"},
{notice, "\e[1;36m"},
{warning, "\e[1;33m"},
{error, "\e[1;31m"},
{critical, "\e[1;35m"},
{alert, "\e[1;44m"},
{emergency, "\e[1;41m"}
]},
%% crash log cfg
%% 有效值 string | false
%% 为 false 的时候 没有 crash logger.
{crash_log, "log/crash.log"},
%% Maximum size in bytes of events in the crash log - defaults to 65536
{crash_log_msg_size, 65536},
%% Maximum size of the crash log in bytes, before its rotated, set to 0 to disable rotation - default is 0
{crash_log_size, 10485760},
%% What time to rotate the crash log - default is no time rotation. See the README for a description of this format.
{crash_log_date, "$D0"},
%% Number of rotated crash logs to keep, 0 means keep only the current one - default is 0
{crash_log_count, 5},
%% Crash Log Rotator Module - default is lager_rotator_default
{crash_log_rotator, lager_rotator_default},
%% Whether to redirect error_logger messages into the default lager_event sink - defaults to true
{error_logger_redirect, true},
%% How many messages per second to allow from error_logger before we start dropping them
{error_logger_hwm, 50},
%% How big the gen_event mailbox can get before it is
%% switched into sync mode. This value only applies to
%% the default sink; extra sinks can supply their own.
{async_threshold, 20},
%% Switch back to async mode, when gen_event mailbox size
%% decrease from `async_threshold' to async_threshold -
%% async_threshold_window. This value only applies to the
%% default sink; extra sinks can supply their own.
{async_threshold_window, 5}
]}
].

+ 28
- 28
src/eRum.erl Datei anzeigen

@ -175,20 +175,20 @@ do_log(Severity, Metadata, Format, Args, Size, SeverityAsInt, LevelThreshold, Tr
do_log_impl(Severity, Metadata, Format, Args, SeverityAsInt, LevelThreshold, TraceFilters, Sink, SinkPid, FormatFun) ->
{Destinations, TraceSinkPid} =
case TraceFilters of
[] ->
{[], undefined};
_ ->
{rumUtil:check_traces(Metadata, SeverityAsInt, TraceFilters, []), whereis(?TRACE_SINK)}
end,
[] ->
{[], undefined};
_ ->
{rumUtil:check_traces(Metadata, SeverityAsInt, TraceFilters, []), whereis(?TRACE_SINK)}
end,
case (LevelThreshold band SeverityAsInt) /= 0 orelse Destinations /= [] of
true ->
Msg =
case Args of
A when is_list(A) ->
FormatFun();
_ ->
Format
end,
A when is_list(A) ->
FormatFun();
_ ->
Format
end,
LagerMsg = rumMsg:new(Msg,
Severity, Metadata, Destinations),
case rumConfig:get({Sink, async}, false) of
@ -284,24 +284,24 @@ trace_file(File, Filter, Level, Options) ->
%% check if this file backend is already installed
Res =
case rumUtil:find_file(FileName, Handlers) of
false ->
%% install the handler
LogFileConfig =
lists:keystore(level, 1,
lists:keystore(file, 1,
Options,
{file, FileName}),
{level, none}),
HandlerInfo =
lager_app:start_handler(Sink, {lager_file_backend, FileName},
LogFileConfig),
rumConfig:global_set(handlers, [HandlerInfo | Handlers]),
{ok, installed};
{_Watcher, _Handler, Sink} ->
{ok, exists};
{_Watcher, _Handler, _OtherSink} ->
{error, file_in_use}
end,
false ->
%% install the handler
LogFileConfig =
lists:keystore(level, 1,
lists:keystore(file, 1,
Options,
{file, FileName}),
{level, none}),
HandlerInfo =
lager_app:start_handler(Sink, {lager_file_backend, FileName},
LogFileConfig),
rumConfig:global_set(handlers, [HandlerInfo | Handlers]),
{ok, installed};
{_Watcher, _Handler, Sink} ->
{ok, exists};
{_Watcher, _Handler, _OtherSink} ->
{error, file_in_use}
end,
case Res of
{ok, _} ->
add_trace_to_loglevel_config(Trace, Sink),

+ 2
- 2
src/formatter/rumFormatter.erl Datei anzeigen

@ -251,8 +251,8 @@ uppercase_severity(emergency) -> "EMERGENCY".
basic_test_() ->
Date = {1, 1,1},
Time = {1, 1,1},
Date = {1, 1, 1},
Time = {1, 1, 1},
Now = 11,
[{"Default formatting test",
?_assertEqual(iolist_to_binary([Date, " ", Time, " [error] ", pid_to_list(self()), " Message\n"]),

+ 151
- 151
src/misc/rumErrLoggerH.erl Datei anzeigen

@ -184,168 +184,168 @@ log_event(Event, #state{sink = Sink} = State) ->
{Md, Formatted} = format_reason_md(Reason),
?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_server ~w terminated with reason: ~s",
[Name, Formatted]);
{false, "** State machine " ++ _} ->
%% Check if the terminated process is gen_fsm or gen_statem
%% since they generate the same exit message
{Type, Name, StateName, Reason} =
case Args of
[TName, _Msg, TStateName, _StateData, TReason] ->
{gen_fsm, TName, TStateName, TReason};
%% Handle changed logging in gen_fsm stdlib-3.9 (TPid, ClientArgs)
[TName, _Msg, TPid, TStateName, _StateData, TReason | _ClientArgs] when is_pid(TPid), is_atom(TStateName) ->
{gen_fsm, TName, TStateName, TReason};
%% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs)
[TName, _Msg, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] ->
{gen_statem, TName, TStateName, {TReason, Stacktrace}};
%% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs)
[TName, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] ->
{gen_statem, TName, TStateName, {TReason, Stacktrace}};
[TName, _Msg, [{TStateName, _StateData}], _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] ->
%% sometimes gen_statem wraps its statename/data in a list for some reason???
{gen_statem, TName, TStateName, {TReason, Stacktrace}}
end,
{Md, Formatted} = format_reason_md(Reason),
?CRASH_LOG(Event),
?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "~s ~w in state ~w terminated with reason: ~s",
[Type, Name, StateName, Formatted]);
{false, "** gen_event handler" ++ _} ->
%% gen_event handler terminate
[ID, Name, _Msg, _State, Reason] = Args,
{false, "** State machine " ++ _} ->
%% Check if the terminated process is gen_fsm or gen_statem
%% since they generate the same exit message
{Type, Name, StateName, Reason} =
case Args of
[TName, _Msg, TStateName, _StateData, TReason] ->
{gen_fsm, TName, TStateName, TReason};
%% Handle changed logging in gen_fsm stdlib-3.9 (TPid, ClientArgs)
[TName, _Msg, TPid, TStateName, _StateData, TReason | _ClientArgs] when is_pid(TPid), is_atom(TStateName) ->
{gen_fsm, TName, TStateName, TReason};
%% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs)
[TName, _Msg, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] ->
{gen_statem, TName, TStateName, {TReason, Stacktrace}};
%% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs)
[TName, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] ->
{gen_statem, TName, TStateName, {TReason, Stacktrace}};
[TName, _Msg, [{TStateName, _StateData}], _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] ->
%% sometimes gen_statem wraps its statename/data in a list for some reason???
{gen_statem, TName, TStateName, {TReason, Stacktrace}}
end,
{Md, Formatted} = format_reason_md(Reason),
?CRASH_LOG(Event),
?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "~s ~w in state ~w terminated with reason: ~s",
[Type, Name, StateName, Formatted]);
{false, "** gen_event handler" ++ _} ->
%% gen_event handler terminate
[ID, Name, _Msg, _State, Reason] = Args,
{Md, Formatted} = format_reason_md(Reason),
?CRASH_LOG(Event),
?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_event ~w installed in ~w terminated with reason: ~s",
[ID, Name, Formatted]);
{false, "** Cowboy handler" ++ _} ->
%% Cowboy HTTP server error
?CRASH_LOG(Event),
case Args of
[Module, Function, Arity, _Request, _State] ->
%% we only get the 5-element list when its a non-exported function
?LOGFMT(Sink, error, Pid,
"Cowboy handler ~p terminated with reason: call to undefined function ~p:~p/~p",
[Module, Module, Function, Arity]);
[Module, Function, Arity, _Class, Reason | Tail] ->
%% any other cowboy error_format list *always* ends with the stacktrace
StackTrace = lists:last(Tail),
{Md, Formatted} = format_reason_md({Reason, StackTrace}),
?LOGFMT(Sink, error, [{pid, Pid} | Md],
"Cowboy handler ~p terminated in ~p:~p/~p with reason: ~s",
[Module, Module, Function, Arity, Formatted])
end;
{false, "Ranch listener " ++ _} ->
%% Ranch errors
?CRASH_LOG(Event),
case Args of
%% Error logged by cowboy, which starts as ranch error
[Ref, ConnectionPid, StreamID, RequestPid, Reason, StackTrace] ->
{Md, Formatted} = format_reason_md({Reason, StackTrace}),
?LOGFMT(Sink, error, [{pid, RequestPid} | Md],
"Cowboy stream ~p with ranch listener ~p and connection process ~p "
"had its request process exit with reason: ~s",
[StreamID, Ref, ConnectionPid, Formatted]);
[Ref, _Protocol, Worker, {[{reason, Reason}, {mfa, {Module, Function, Arity}}, {stacktrace, StackTrace} | _], _}] ->
{Md, Formatted} = format_reason_md({Reason, StackTrace}),
?LOGFMT(Sink, error, [{pid, Worker} | Md],
"Ranch listener ~p terminated in ~p:~p/~p with reason: ~s",
[Ref, Module, Function, Arity, Formatted]);
[Ref, _Protocol, Worker, Reason] ->
{Md, Formatted} = format_reason_md(Reason),
?CRASH_LOG(Event),
?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_event ~w installed in ~w terminated with reason: ~s",
[ID, Name, Formatted]);
{false, "** Cowboy handler" ++ _} ->
%% Cowboy HTTP server error
?CRASH_LOG(Event),
case Args of
[Module, Function, Arity, _Request, _State] ->
%% we only get the 5-element list when its a non-exported function
?LOGFMT(Sink, error, Pid,
"Cowboy handler ~p terminated with reason: call to undefined function ~p:~p/~p",
[Module, Module, Function, Arity]);
[Module, Function, Arity, _Class, Reason | Tail] ->
%% any other cowboy error_format list *always* ends with the stacktrace
StackTrace = lists:last(Tail),
{Md, Formatted} = format_reason_md({Reason, StackTrace}),
?LOGFMT(Sink, error, [{pid, Pid} | Md],
"Cowboy handler ~p terminated in ~p:~p/~p with reason: ~s",
[Module, Module, Function, Arity, Formatted])
end;
{false, "Ranch listener " ++ _} ->
%% Ranch errors
?CRASH_LOG(Event),
case Args of
%% Error logged by cowboy, which starts as ranch error
[Ref, ConnectionPid, StreamID, RequestPid, Reason, StackTrace] ->
{Md, Formatted} = format_reason_md({Reason, StackTrace}),
?LOGFMT(Sink, error, [{pid, RequestPid} | Md],
"Cowboy stream ~p with ranch listener ~p and connection process ~p "
"had its request process exit with reason: ~s",
[StreamID, Ref, ConnectionPid, Formatted]);
[Ref, _Protocol, Worker, {[{reason, Reason}, {mfa, {Module, Function, Arity}}, {stacktrace, StackTrace} | _], _}] ->
{Md, Formatted} = format_reason_md({Reason, StackTrace}),
?LOGFMT(Sink, error, [{pid, Worker} | Md],
"Ranch listener ~p terminated in ~p:~p/~p with reason: ~s",
[Ref, Module, Function, Arity, Formatted]);
[Ref, _Protocol, Worker, Reason] ->
{Md, Formatted} = format_reason_md(Reason),
?LOGFMT(Sink, error, [{pid, Worker} | Md],
"Ranch listener ~p terminated with reason: ~s",
[Ref, Formatted]);
[Ref, Protocol, Ret] ->
%% ranch_conns_sup.erl module line 119-123 has three parameters error msg, log it.
{Md, Formatted} = format_reason_md(Ret),
?LOGFMT(Sink, error, [{pid, Protocol} | Md],
"Ranch listener ~p terminated with result:~s",
[Ref, Formatted])
end;
{false, "webmachine error" ++ _} ->
%% Webmachine HTTP server error
?CRASH_LOG(Event),
[Path, Error] = Args,
%% webmachine likes to mangle the stack, for some reason
StackTrace = case Error of
{error, {error, Reason, Stack}} ->
{Reason, Stack};
_ ->
Error
end,
{Md, Formatted} = format_reason_md(StackTrace),
?LOGFMT(Sink, error, [{pid, Pid} | Md], "Webmachine error at path ~p : ~s", [Path, Formatted]);
_ ->
?CRASH_LOG(Event),
?LOGFMT(Sink, error, Pid, Fmt, Args)
?LOGFMT(Sink, error, [{pid, Worker} | Md],
"Ranch listener ~p terminated with reason: ~s",
[Ref, Formatted]);
[Ref, Protocol, Ret] ->
%% ranch_conns_sup.erl module line 119-123 has three parameters error msg, log it.
{Md, Formatted} = format_reason_md(Ret),
?LOGFMT(Sink, error, [{pid, Protocol} | Md],
"Ranch listener ~p terminated with result:~s",
[Ref, Formatted])
end;
{error_report, _GL, {Pid, std_error, D}} ->
{false, "webmachine error" ++ _} ->
%% Webmachine HTTP server error
?CRASH_LOG(Event),
?LOGMSG(Sink, error, Pid, print_silly_list(D));
{error_report, _GL, {Pid, supervisor_report, D}} ->
[Path, Error] = Args,
%% webmachine likes to mangle the stack, for some reason
StackTrace = case Error of
{error, {error, Reason, Stack}} ->
{Reason, Stack};
_ ->
Error
end,
{Md, Formatted} = format_reason_md(StackTrace),
?LOGFMT(Sink, error, [{pid, Pid} | Md], "Webmachine error at path ~p : ~s", [Path, Formatted]);
_ ->
?CRASH_LOG(Event),
case lists:sort(D) of
[{errorContext, Ctx}, {offender, Off}, {reason, Reason}, {supervisor, Name}] ->
Offender = format_offender(Off),
{Md, Formatted} = format_reason_md(Reason),
?LOGFMT(Sink, error, [{pid, Pid} | Md],
"Supervisor ~w had child ~s exit with reason ~s in context ~w",
[supervisor_name(Name), Offender, Formatted, Ctx]);
?LOGFMT(Sink, error, Pid, Fmt, Args)
end;
{error_report, _GL, {Pid, std_error, D}} ->
?CRASH_LOG(Event),
?LOGMSG(Sink, error, Pid, print_silly_list(D));
{error_report, _GL, {Pid, supervisor_report, D}} ->
?CRASH_LOG(Event),
case lists:sort(D) of
[{errorContext, Ctx}, {offender, Off}, {reason, Reason}, {supervisor, Name}] ->
Offender = format_offender(Off),
{Md, Formatted} = format_reason_md(Reason),
?LOGFMT(Sink, error, [{pid, Pid} | Md],
"Supervisor ~w had child ~s exit with reason ~s in context ~w",
[supervisor_name(Name), Offender, Formatted, Ctx]);
_ ->
?LOGMSG(Sink, error, Pid, "SUPERVISOR REPORT " ++ print_silly_list(D))
end;
{error_report, _GL, {Pid, crash_report, [Self, Neighbours]}} ->
?CRASH_LOG(Event),
{Md, Formatted} = format_crash_report(Self, Neighbours),
?LOGMSG(Sink, error, [{pid, Pid} | Md], "CRASH REPORT " ++ Formatted);
{warning_msg, _GL, {Pid, Fmt, Args}} ->
?LOGFMT(Sink, warning, Pid, Fmt, Args);
{warning_report, _GL, {Pid, std_warning, Report}} ->
?LOGMSG(Sink, warning, Pid, print_silly_list(Report));
{info_msg, _GL, {Pid, Fmt, Args}} ->
?LOGFMT(Sink, info, Pid, Fmt, Args);
{info_report, _GL, {Pid, std_info, D}} when is_list(D) ->
Details = lists:sort(D),
case Details of
[{application, App}, {exited, Reason}, {type, _Type}] ->
case application:get_env(lager, suppress_application_start_stop, false) of
true when Reason == stopped ->
no_log;
_ ->
?LOGMSG(Sink, error, Pid, "SUPERVISOR REPORT " ++ print_silly_list(D))
{Md, Formatted} = format_reason_md(Reason),
?LOGFMT(Sink, info, [{pid, Pid} | Md], "Application ~w exited with reason: ~s",
[App, Formatted])
end;
{error_report, _GL, {Pid, crash_report, [Self, Neighbours]}} ->
?CRASH_LOG(Event),
{Md, Formatted} = format_crash_report(Self, Neighbours),
?LOGMSG(Sink, error, [{pid, Pid} | Md], "CRASH REPORT " ++ Formatted);
{warning_msg, _GL, {Pid, Fmt, Args}} ->
?LOGFMT(Sink, warning, Pid, Fmt, Args);
{warning_report, _GL, {Pid, std_warning, Report}} ->
?LOGMSG(Sink, warning, Pid, print_silly_list(Report));
{info_msg, _GL, {Pid, Fmt, Args}} ->
?LOGFMT(Sink, info, Pid, Fmt, Args);
{info_report, _GL, {Pid, std_info, D}} when is_list(D) ->
Details = lists:sort(D),
case Details of
[{application, App}, {exited, Reason}, {type, _Type}] ->
case application:get_env(lager, suppress_application_start_stop, false) of
true when Reason == stopped ->
no_log;
_ ->
{Md, Formatted} = format_reason_md(Reason),
?LOGFMT(Sink, info, [{pid, Pid} | Md], "Application ~w exited with reason: ~s",
[App, Formatted])
end;
_ ->
?LOGMSG(Sink, info, Pid, print_silly_list(D))
end;
{info_report, _GL, {Pid, std_info, D}} ->
?LOGFMT(Sink, info, Pid, "~w", [D]);
{info_report, _GL, {P, progress, D}} ->
Details = lists:sort(D),
case Details of
[{application, App}, {started_at, Node}] ->
case application:get_env(lager, suppress_application_start_stop, false) of
true ->
no_log;
_ ->
?LOGMSG(Sink, info, Pid, print_silly_list(D))
?LOGFMT(Sink, info, P, "Application ~w started on node ~w",
[App, Node])
end;
{info_report, _GL, {Pid, std_info, D}} ->
?LOGFMT(Sink, info, Pid, "~w", [D]);
{info_report, _GL, {P, progress, D}} ->
Details = lists:sort(D),
case Details of
[{application, App}, {started_at, Node}] ->
case application:get_env(lager, suppress_application_start_stop, false) of
true ->
no_log;
_ ->
?LOGFMT(Sink, info, P, "Application ~w started on node ~w",
[App, Node])
end;
[{started, Started}, {supervisor, Name}] ->
case application:get_env(lager, suppress_supervisor_start_stop, false) of
true ->
no_log;
_ ->
MFA = format_mfa(get_value(mfargs, Started)),
Pid = get_value(pid, Started),
?LOGFMT(Sink, debug, P, "Supervisor ~w started ~s at pid ~w",
[supervisor_name(Name), MFA, Pid])
end;
[{started, Started}, {supervisor, Name}] ->
case application:get_env(lager, suppress_supervisor_start_stop, false) of
true ->
no_log;
_ ->
?LOGMSG(Sink, info, P, "PROGRESS REPORT " ++ print_silly_list(D))
MFA = format_mfa(get_value(mfargs, Started)),
Pid = get_value(pid, Started),
?LOGFMT(Sink, debug, P, "Supervisor ~w started ~s at pid ~w",
[supervisor_name(Name), MFA, Pid])
end;
_ ->
?LOGFMT(Sink, warning, self(), "Unexpected error_logger event ~w", [Event])
end,
?LOGMSG(Sink, info, P, "PROGRESS REPORT " ++ print_silly_list(D))
end;
_ ->
?LOGFMT(Sink, warning, self(), "Unexpected error_logger event ~w", [Event])
end,
case DidLog of
logged ->
{ok, State};

+ 16
- 16
src/misc/rumTruncIo.erl Datei anzeigen

@ -167,22 +167,22 @@ print(Binary, Max, Options) when is_binary(Binary) ->
{L0, Len0}
end
catch
throw:{unprintable, C} ->
Index = string:chr(In, C),
case Index > 1 andalso Options#print_options.depth =< Index andalso
Options#print_options.depth > -1 andalso
not Options#print_options.force_strings of
true ->
%% print first Index-1 characters followed by ...
{L0, Len0} = alist_start(string:substr(In, 1, Index - 1), Max - 1, Options),
{L0 ++ "...", Len0 + 3};
false ->
list_body(In, Max - 4, dec_depth(Options), true)
end
end;
_ ->
list_body(B, Max - 4, dec_depth(Options), true)
end,
throw:{unprintable, C} ->
Index = string:chr(In, C),
case Index > 1 andalso Options#print_options.depth =< Index andalso
Options#print_options.depth > -1 andalso
not Options#print_options.force_strings of
true ->
%% print first Index-1 characters followed by ...
{L0, Len0} = alist_start(string:substr(In, 1, Index - 1), Max - 1, Options),
{L0 ++ "...", Len0 + 3};
false ->
list_body(In, Max - 4, dec_depth(Options), true)
end
end;
_ ->
list_body(B, Max - 4, dec_depth(Options), true)
end,
case Options#print_options.force_strings of
true ->
{Res, Length};

+ 4
- 4
test/crash_statem.erl Datei anzeigen

@ -10,10 +10,10 @@
handle_event/4
]).
-export([terminate/3,code_change/4,init/1,callback_mode/0]).
-export([terminate/3, code_change/4, init/1, callback_mode/0]).
start() ->
gen_statem:start({local,?MODULE}, ?MODULE, [], []).
gen_statem:start({local, ?MODULE}, ?MODULE, [], []).
crash() ->
gen_statem:call(?MODULE, boom).
@ -26,11 +26,11 @@ timeout() ->
%% Mandatory callback functions
terminate(_Reason, _State, _Data) -> ok.
code_change(_Vsn, State, Data, _Extra) -> {ok,State,Data}.
code_change(_Vsn, State, Data, _Extra) -> {ok, State, Data}.
init([]) ->
%% insert rant here about breaking changes in minor versions...
case erlang:system_info(version) of
"8.0" -> {callback_mode(),state1,undefined};
"8.0" -> {callback_mode(), state1, undefined};
_ -> {ok, state1, undefined}
end.

+ 251
- 251
test/lager_test_backend.erl
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


Laden…
Abbrechen
Speichern