Projects
Kolab:Winterfell
erlang-lager
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 4
View file
erlang-lager.spec
Changed
@@ -7,7 +7,7 @@ %global debug_package %{nil} Name: erlang-%{realname} -Version: 3.1.0 +Version: 3.2.4 Release: 1%{?dist} Summary: A logging framework for Erlang/OTP Group: Development/Languages @@ -52,7 +52,6 @@ install -p -m 0644 ebin/%{realname}.app %{buildroot}%{_libdir}/erlang/lib/%{realname}-%{version}/ebin/ install -p -m 0644 ebin/*.beam %{buildroot}%{_libdir}/erlang/lib/%{realname}-%{version}/ebin install -p -m 0644 include/*.hrl %{buildroot}%{_libdir}/erlang/lib/%{realname}-%{version}/include/ -install -p -m 0644 rebar.config %{buildroot}%{_libdir}/erlang/lib/%{realname}-%{version}/ %check rebar skip_deps=true eunit -v || : @@ -67,9 +66,11 @@ %{_libdir}/erlang/lib/%{realname}-%{version}/ebin/%{realname}.app %{_libdir}/erlang/lib/%{realname}-%{version}/ebin/*.beam %{_libdir}/erlang/lib/%{realname}-%{version}/include/*.hrl -%{_libdir}/erlang/lib/%{realname}-%{version}/rebar.config %changelog +* Tue Nov 22 2016 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 3.2.4-1 +- Update to 3.2.4 + * Fri May 15 2015 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 2.1.0-1 - Check in 2.1.0
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +erlang-lager (3.2.4-0~kolab1) unstable; urgency=medium + + * Bump version to 3.2.4. + + -- Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Tue, 22 Nov 2016 21:39:31 +0100 + erlang-lager (3.1.0-0~kolab1) unstable; urgency=medium * Bump version to 3.1.0.
View file
debian.control
Changed
@@ -2,7 +2,7 @@ Priority: optional Maintainer: Philipp Huebner <debalance@debian.org> Uploaders: Christoph Erhardt <kolab@sicherha.de> -Build-Depends: debhelper (>= 9), dh-rebar, erlang-goldrush +Build-Depends: debhelper (>= 9), dh-rebar, erlang-crypto, erlang-goldrush Standards-Version: 3.9.5 Section: libs Homepage: https://github.com/basho/lager
View file
erlang-lager.dsc
Changed
@@ -2,14 +2,14 @@ Source: erlang-lager Binary: erlang-lager Architecture: any -Version: 3.1.0-0~kolab1 +Version: 3.2.4-0~kolab1 Maintainer: Philipp Huebner <debalance@debian.org> Uploaders: Christoph Erhardt <kolab@sicherha.de> Homepage: https://github.com/basho/lager Standards-Version: 3.9.5 -Build-Depends: debhelper (>= 9), dh-rebar, erlang-goldrush -Package-List: +Build-Depends: debhelper (>= 9), dh-rebar, erlang-crypto, erlang-goldrush +Package-List: erlang-lager deb libs optional -Files: - 00000000000000000000000000000000 0 lager-3.1.0.tar.gz +Files: + 00000000000000000000000000000000 0 lager-3.2.4.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
View file
lager-3.1.0.tar.gz/.travis.yml -> lager-3.2.4.tar.gz/.travis.yml
Changed
@@ -1,11 +1,9 @@ +sudo: false language: erlang notifications: - webhooks: http://basho-engbot.herokuapp.com/travis?key=8c2550739c2f776d4b05d993aa032f0724fe5450 email: eng@basho.com otp_release: - - R16B + - 18.2.1 + - 17.5 + - R16B03-1 - R15B03 - - R15B01 - - R15B - - R14B04 - - R14B03
View file
lager-3.1.0.tar.gz/README.md -> lager-3.2.4.tar.gz/README.md
Changed
@@ -25,6 +25,8 @@ * Syslog style log level comparison flags * Colored terminal output (requires R16+) * Map support (requires 17+) +* Optional load shedding by setting a high water mark to kill (and reinstall) + a sink after a configurable cool down timer Usage ----- @@ -189,14 +191,19 @@ ]}. ``` -Included is `lager_default_formatter`. This provides a generic, default formatting for log messages using a structure similar to Erlang's [iolist](http://learnyousomeerlang.com/buckets-of-sockets#io-lists) which we call "semi-iolist": +Included is `lager_default_formatter`. This provides a generic, default +formatting for log messages using a structure similar to Erlang's +[iolist](http://learnyousomeerlang.com/buckets-of-sockets#io-lists) which we +call "semi-iolist": * Any traditional iolist elements in the configuration are printed verbatim. -* Atoms in the configuration are treated as placeholders for lager metadata and extracted from the log message. +* Atoms in the configuration are treated as placeholders for lager metadata and + extracted from the log message. * The placeholders `date`, `time`, `message`, `sev` and `severity` will always exist. - * `sev` is an abbreviated severity which is interpreted as a capitalized single letter encoding of the severity level - (e.g. `'debug'` -> `$D`) - * The placeholders `pid`, `file`, `line`, `module`, `function`, and `node` will always exist if the parse transform is used. + * `sev` is an abbreviated severity which is interpreted as a capitalized + single letter encoding of the severity level (e.g. `'debug'` -> `$D`) + * The placeholders `pid`, `file`, `line`, `module`, `function`, and `node` + will always exist if the parse transform is used. * Applications can define their own metadata placeholder. * A tuple of `{atom(), semi-iolist()}` allows for a fallback for the atom placeholder. If the value represented by the atom @@ -228,13 +235,14 @@ The `error_logger` handler will also log more complete error messages (protected with use of `trunc_io`) to a "crash log" which can be referred to for further information. The location of the crash log can be specified by the crash_log -application variable. If set to `undefined` it is not written at all. +application variable. If set to `false` it is not written at all. Messages in the crash log are subject to a maximum message size which can be specified via the `crash_log_msg_size` application variable. Messages from `error_logger` will be redirected to `error_logger_lager_event` sink if it is defined so it can be redirected to another log file. + For example: ``` @@ -249,15 +257,18 @@ }] }]. ``` -Will send all `error_logger` messages to `error_logger.log` file. +will send all `error_logger` messages to `error_logger.log` file. + Overload Protection ------------------- +### Asynchronous mode + Prior to lager 2.0, the `gen_event` at the core of lager operated purely in synchronous mode. Asynchronous mode is faster, but has no protection against -message queue overload. In lager 2.0, the `gen_event` takes a hybrid approach. it -polls its own mailbox size and toggles the messaging between synchronous and -asynchronous depending on mailbox size. +message queue overload. As of lager 2.0, the `gen_event` takes a hybrid +approach. it polls its own mailbox size and toggles the messaging between +synchronous and asynchronous depending on mailbox size. ```erlang {async_threshold, 20}, @@ -283,6 +294,31 @@ It is probably best to keep this number small. +### Sink Killer + +In some high volume situations, it may be preferable to drop all pending log +messages instead of letting them drain over time. + +If you prefer, you may choose to use the sink killer to shed load. In this +operational mode, if the `gen_event` mailbox exceeds a configurable +high water mark, the sink will be killed and reinstalled after a +configurable cool down time. + +You can configure this behavior by using these configuration directives: + +```erlang +{killer_hwm, 1000}, +{killer_reinstall_after, 5000} +``` + +This means if the sink's mailbox size exceeds 1000 messages, kill the +entire sink and reload it after 5000 milliseconds. This behavior can +also be installed into alternative sinks if desired. + +By default, the manager killer *is not installed* into any sink. If +the `killer_reinstall_after` cool down time is not specified it defaults +to 5000. + "Unsafe" -------- The unsafe code pathway bypasses the normal lager formatting code and uses the @@ -553,7 +589,7 @@ filters: ```erlang -lager:trace_file("log/security.log", [{sink, audit}, {function, myfunction}], warning) +lager:trace_file("log/security.log", [{sink, audit_event}, {function, myfunction}], warning) ``` If no sink is thus specified, the default lager sink will be used. @@ -568,6 +604,38 @@ can be fixed by rearchitecting lager's file backend, but this has not been tackled. +### Traces from configuration + +Lager supports starting traces from its configuration file. The keyword +to define them is `traces`, followed by a proplist of tuples that define +a backend handler and zero or more filters in a required list, +followed by an optional message severity level. + +An example looks like this: + +```erlang +{lager, [ + {handlers, [...]}, + {traces, [ + %% handler, filter, message level (defaults to debug if not given) + {lager_console_backend, [{module, foo}], info }, + {{lager_file_backend, "trace.log"}, [{request, '>', 120}], error}, + {{lager_file_backend, "event.log"}, [{module, bar}] } %% implied debug level here + ]} +]}. +``` + +In this example, we have three traces. One using the console backend, and two +using the file backend. If the message severity level is left out, it defaults +to `debug` as in the last file backend example. + +The `traces` keyword works on alternative sinks too but the same limitations +and caveats noted above apply. + +**IMPORTANT**: You **must** define a severity level in all lager releases +up to and including 3.1.0 or previous. The 2-tuple form wasn't added until +3.2.0. + Setting the truncation limit at compile-time -------------------------------------------- Lager defaults to truncating messages at 4096 bytes, you can alter this by @@ -586,6 +654,40 @@ 3.x Changelog ------------- +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
View file
lager-3.1.0.tar.gz/rebar.config -> lager-3.2.4.tar.gz/rebar.config
Changed
@@ -40,11 +40,14 @@ {eunit_opts, [verbose]}. {eunit_compile_opts, [ + export_all, + nowarn_untyped_record, nowarn_export_all ]}. + {deps, [ - {goldrush, ".*", {git, "git://github.com/DeadZen/goldrush.git", {tag, "0.1.8"}}} + {goldrush, ".*", {git, "https://github.com/basho/goldrush.git", {tag, "0.1.9"}}} ]}. {xref_checks, []}. @@ -52,3 +55,4 @@ {cover_enabled, true}. {edoc_opts, [{stylesheet_file, "./priv/edoc.css"}]}. +
View file
lager-3.1.0.tar.gz/src/error_logger_lager_h.erl -> lager-3.2.4.tar.gz/src/error_logger_lager_h.erl
Changed
@@ -73,7 +73,7 @@ -spec init(any()) -> {ok, #state{}}. init([HighWaterMark, GlStrategy]) -> Shaper = #lager_shaper{hwm=HighWaterMark}, - Raw = application:get_env(lager, error_logger_format_raw, false), + Raw = lager_app:get_env(lager, error_logger_format_raw, false), Sink = configured_sink(), {ok, #state{sink=Sink, shaper=Shaper, groupleader_strategy=GlStrategy, raw=Raw}}. @@ -104,7 +104,7 @@ code_change(_OldVsn, {state, Shaper, GLStrategy}, _Extra) -> - Raw = application:get_env(lager, error_logger_format_raw, false), + Raw = lager_app:get_env(lager, error_logger_format_raw, false), {ok, #state{ sink=configured_sink(), shaper=Shaper, @@ -112,7 +112,7 @@ raw=Raw }}; code_change(_OldVsn, {state, Sink, Shaper, GLS}, _Extra) -> - Raw = application:get_env(lager, error_logger_format_raw, false), + Raw = lager_app:get_env(lager, error_logger_format_raw, false), {ok, #state{sink=Sink, shaper=Shaper, groupleader_strategy=GLS, raw=Raw}}; code_change(_OldVsn, State, _Extra) -> {ok, State}. @@ -120,7 +120,7 @@ %% internal functions configured_sink() -> - case proplists:get_value(?ERROR_LOGGER_SINK, application:get_env(lager, extra_sinks, [])) of + case proplists:get_value(?ERROR_LOGGER_SINK, lager_app:get_env(lager, extra_sinks, [])) of undefined -> ?DEFAULT_SINK; _ -> ?ERROR_LOGGER_SINK end. @@ -295,7 +295,15 @@ MFArgs -> %% regular supervisor MFA = format_mfa(MFArgs), - Name = get_value(name, Off), + + %% In 2014 the error report changed from `name' to + %% `id', so try that first. + Name = case get_value(id, Off) of + undefined -> + get_value(name, Off); + Id -> + Id + end, io_lib:format("~p started with ~s at ~w", [Name, MFA, get_value(pid, Off)]) end.
View file
lager-3.1.0.tar.gz/src/lager.app.src -> lager-3.2.4.tar.gz/src/lager.app.src
Changed
@@ -3,7 +3,7 @@ {application, lager, [ {description, "Erlang logging framework"}, - {vsn, "3.1.0"}, + {vsn, "3.2.2"}, {modules, []}, {applications, [ kernel, @@ -30,7 +30,7 @@ ]}, - %% Whether to write a crash log, and where. Undefined means no crash logger. + %% Whether to write a crash log, and where. False means no 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},
View file
lager-3.1.0.tar.gz/src/lager.erl -> lager-3.2.4.tar.gz/src/lager.erl
Changed
@@ -37,7 +37,7 @@ safe_format/3, safe_format_chop/3, unsafe_format/2, dispatch_log/5, dispatch_log/7, dispatch_log/9, do_log/9, do_log/10, do_log_unsafe/10, pr/2, pr/3, pr_stacktrace/1, pr_stacktrace/2]). --type log_level() :: debug | info | notice | warning | error | critical | alert | emergency. +-type log_level() :: none | debug | info | notice | warning | error | critical | alert | emergency. -type log_level_number() :: 0..7. -export_type([log_level/0, log_level_number/0]). @@ -609,9 +609,19 @@ lists:flatten( pr_stacktrace(Stacktrace) ++ "\n" ++ io_lib:format("~s:~p", [Class, Reason])). + +%% R15 compatibility only +filtermap(Fun, List1) -> + lists:foldr(fun(Elem, Acc) -> + case Fun(Elem) of + false -> Acc; + {true,Value} -> [Value|Acc] + end + end, [], List1). + rotate_sink(Sink) -> Handlers = lager_config:global_get(handlers), - RotateHandlers = lists:filtermap( + RotateHandlers = filtermap( fun({Handler,_,S}) when S == Sink -> {true, {Handler, Sink}}; (_) -> false end,
View file
lager-3.1.0.tar.gz/src/lager_app.erl -> lager-3.2.4.tar.gz/src/lager_app.erl
Changed
@@ -23,12 +23,19 @@ -behaviour(application). -include("lager.hrl"). -ifdef(TEST). +-compile([export_all]). -include_lib("eunit/include/eunit.hrl"). -endif. -export([start/0, start/2, start_handler/3, - stop/1]). + configure_sink/2, + stop/1, + boot/1]). + +%% The `application:get_env/3` compatibility wrapper is useful +%% for other modules +-export([get_env/3]). -define(FILENAMES, '__lager_file_backend_filenames'). -define(THROTTLE, lager_backend_throttle). @@ -52,21 +59,19 @@ [Sink, ?THROTTLE, [Threshold, Window]]), ok. -determine_async_behavior(_Sink, {ok, undefined}, _Window) -> - ok; determine_async_behavior(_Sink, undefined, _Window) -> ok; -determine_async_behavior(_Sink, {ok, Threshold}, _Window) when not is_integer(Threshold) orelse Threshold < 0 -> +determine_async_behavior(_Sink, Threshold, _Window) when not is_integer(Threshold) orelse Threshold < 0 -> error_logger:error_msg("Invalid value for 'async_threshold': ~p~n", [Threshold]), throw({error, bad_config}); -determine_async_behavior(Sink, {ok, Threshold}, undefined) -> +determine_async_behavior(Sink, Threshold, undefined) -> start_throttle(Sink, Threshold, erlang:trunc(Threshold * 0.2)); -determine_async_behavior(_Sink, {ok, Threshold}, {ok, Window}) when not is_integer(Window) orelse Window > Threshold orelse Window < 0 -> +determine_async_behavior(_Sink, Threshold, Window) when not is_integer(Window) orelse Window > Threshold orelse Window < 0 -> error_logger:error_msg( "Invalid value for 'async_threshold_window': ~p~n", [Window]), throw({error, bad_config}); -determine_async_behavior(Sink, {ok, Threshold}, {ok, Window}) -> +determine_async_behavior(Sink, Threshold, Window) -> start_throttle(Sink, Threshold, Window). start_handlers(_Sink, undefined) -> @@ -93,7 +98,7 @@ [Sink, Module, Config]), {Module, Watcher, Sink}. -check_handler_config({lager_file_backend, F}, Config) when is_list(Config) -> +check_handler_config({lager_file_backend, F}, Config) when is_list(Config); is_tuple(Config) -> Fs = case get(?FILENAMES) of undefined -> ordsets:new(); X -> X @@ -118,23 +123,30 @@ interpret_hwm(undefined) -> undefined; -interpret_hwm({ok, undefined}) -> - undefined; -interpret_hwm({ok, HWM}) when not is_integer(HWM) orelse HWM < 0 -> +interpret_hwm(HWM) when not is_integer(HWM) orelse HWM < 0 -> _ = lager:log(warning, self(), "Invalid error_logger high water mark: ~p, disabling", [HWM]), undefined; -interpret_hwm({ok, HWM}) -> +interpret_hwm(HWM) -> HWM. -start_error_logger_handler({ok, false}, _HWM, _Whitelist) -> +maybe_install_sink_killer(_Sink, undefined, _ReinstallTimer) -> ok; +maybe_install_sink_killer(Sink, HWM, undefined) -> maybe_install_sink_killer(Sink, HWM, 5000); +maybe_install_sink_killer(Sink, HWM, ReinstallTimer) when is_integer(HWM) andalso is_integer(ReinstallTimer) + andalso HWM >= 0 andalso ReinstallTimer >= 0 -> + _ = supervisor:start_child(lager_handler_watcher_sup, [Sink, lager_manager_killer, + [HWM, ReinstallTimer]]); +maybe_install_sink_killer(_Sink, HWM, ReinstallTimer) -> + error_logger:error_msg("Invalid value for 'killer_hwm': ~p or 'killer_reinstall_after': ~p", [HWM, ReinstallTimer]), + throw({error, bad_config}). + +-spec start_error_logger_handler(boolean(), pos_integer(), list()) -> list(). +start_error_logger_handler(false, _HWM, _Whitelist) -> []; -start_error_logger_handler(_, HWM, undefined) -> - start_error_logger_handler(ignore_me, HWM, {ok, []}); -start_error_logger_handler(_, HWM, {ok, WhiteList}) -> +start_error_logger_handler(true, HWM, WhiteList) -> GlStrategy = case application:get_env(lager, error_logger_groupleader_strategy) of undefined -> handle; - {ok, GlStrategy0} when + {ok, GlStrategy0} when GlStrategy0 =:= handle; GlStrategy0 =:= ignore; GlStrategy0 =:= mirror -> @@ -146,23 +158,24 @@ throw({error, bad_config}) end, - case supervisor:start_child(lager_handler_watcher_sup, [error_logger, error_logger_lager_h, [HWM, GlStrategy]]) of + + _ = case supervisor:start_child(lager_handler_watcher_sup, [error_logger, error_logger_lager_h, [HWM, GlStrategy]]) of {ok, _} -> [begin error_logger:delete_report_handler(X), X end || X <- gen_event:which_handlers(error_logger) -- [error_logger_lager_h | WhiteList]]; {error, _} -> [] - end. + end, -%% `determine_async_behavior/3' is called with the results from either -%% `application:get_env/2' and `proplists:get_value/2'. Since -%% `application:get_env/2' wraps a successful retrieval in an `{ok, -%% Value}' tuple, do the same for the result from -%% `proplists:get_value/2'. -wrap_proplist_value(undefined) -> - undefined; -wrap_proplist_value(Value) -> - {ok, Value}. + Handlers = case application:get_env(lager, handlers) of + undefined -> + [{lager_console_backend, info}, + {lager_file_backend, [{file, "log/error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]}, + {lager_file_backend, [{file, "log/console.log"}, {level, info}, {size, 10485760}, {date, "$D0"}, {count, 5}]}]; + {ok, Val} -> + Val + end, + Handlers. configure_sink(Sink, SinkDef) -> lager_config:new_sink(Sink), @@ -172,12 +185,11 @@ {gen_event, start_link, [{local, Sink}]}, permanent, 5000, worker, dynamic}), - determine_async_behavior(Sink, - wrap_proplist_value( - proplists:get_value(async_threshold, SinkDef)), - wrap_proplist_value( - proplists:get_value(async_threshold_window, SinkDef)) + determine_async_behavior(Sink, proplists:get_value(async_threshold, SinkDef), + proplists:get_value(async_threshold_window, SinkDef) ), + _ = maybe_install_sink_killer(Sink, proplists:get_value(killer_hwm, SinkDef), + proplists:get_value(killer_reinstall_after, SinkDef)), start_handlers(Sink, proplists:get_value(handlers, SinkDef, [])), @@ -188,11 +200,16 @@ lists:foreach(fun({Sink, Proplist}) -> configure_sink(Sink, Proplist) end, Sinks). +-spec get_env(atom(), atom()) -> term(). +get_env(Application, Key) -> + get_env(Application, Key, undefined). + %% R15 doesn't know about application:get_env/3 +-spec get_env(atom(), atom(), term()) -> term(). get_env(Application, Key, Default) -> - get_env_default(application:get_env(Application, Key), - Default). + get_env_default(application:get_env(Application, Key), Default). +-spec get_env_default('undefined' | {'ok', term()}, term()) -> term(). get_env_default(undefined, Default) -> Default; get_env_default({ok, Value}, _Default) -> @@ -200,34 +217,50 @@ start(_StartType, _StartArgs) -> {ok, Pid} = lager_sup:start_link(), + SavedHandlers = boot(), + _ = boot('__all_extra'), + _ = boot('__traces'), + clean_up_config_checks(), + {ok, Pid, SavedHandlers}. +boot() -> %% Handle the default sink. determine_async_behavior(?DEFAULT_SINK, - application:get_env(lager, async_threshold), - application:get_env(lager, async_threshold_window)), + get_env(lager, async_threshold), + get_env(lager, async_threshold_window)), + + _ = maybe_install_sink_killer(?DEFAULT_SINK, get_env(lager, killer_hwm), + get_env(lager, killer_reinstall_after)), + start_handlers(?DEFAULT_SINK, get_env(lager, handlers, ?DEFAULT_HANDLER_CONF)), - lager:update_loglevel_config(?DEFAULT_SINK), SavedHandlers = start_error_logger_handler( - application:get_env(lager, error_logger_redirect), - interpret_hwm(application:get_env(lager, error_logger_hwm)), - application:get_env(lager, error_logger_whitelist) + get_env(lager, error_logger_redirect, true), + interpret_hwm(get_env(lager, error_logger_hwm, 0)), + get_env(lager, error_logger_whitelist, []) ), + SavedHandlers. + +boot('__traces') -> _ = lager_util:trace_filter(none), + ok = add_configured_traces(); - %% Now handle extra sinks - configure_extra_sinks(get_env(lager, extra_sinks, [])), +boot('__all_extra') -> + configure_extra_sinks(get_env(lager, extra_sinks, [])); - ok = add_configured_traces(), - - clean_up_config_checks(), - - {ok, Pid, SavedHandlers}. +boot(?DEFAULT_SINK) -> boot(); +boot(Sink) -> + AllSinksDef = get_env(lager, extra_sinks, []), + boot_sink(Sink, lists:keyfind(Sink, 1, AllSinksDef)). +boot_sink(Sink, {Sink, Def}) -> + configure_sink(Sink, Def); +boot_sink(Sink, false) -> + configure_sink(Sink, []). stop(Handlers) -> lists:foreach(fun(Handler) -> @@ -256,12 +289,14 @@ TraceVal end, - lists:foreach(fun({Handler, Filter, Level}) -> - {ok, _} = lager:trace(Handler, Filter, Level) - end, - Traces), + lists:foreach(fun start_configured_trace/1, Traces), ok. +start_configured_trace({Handler, Filter}) -> + {ok, _} = lager:trace(Handler, Filter); +start_configured_trace({Handler, Filter, Level}) when is_atom(Level) -> + {ok, _} = lager:trace(Handler, Filter, Level). + maybe_make_handler_id(Mod, Config) -> %% Allow the backend to generate a gen_event handler id, if it wants to. %% We don't use erlang:function_exported here because that requires the module @@ -352,6 +387,13 @@ {format, json}, {json_encoder, jiffy}}], BadToo = [{fail, {fail}}], + OldSchoolLagerGood = expand_handlers([{lager_console_backend,info}, + {lager_file_backend, [ + {"./log/error.log",error,10485760,"$D0",5}, + {"./log/console.log",info,10485760,"$D0",5}, + {"./log/debug.log",debug,10485760,"$D0",5} + ]}]), + NewConfigMissingList = expand_handlers([{foo_backend, {file, "same_file.log"}}]), [ {"lager_file_backend_good", ?_assertEqual([ok, ok, ok], [ check_handler_config(M,C) || {M,C} <- Good ]) @@ -364,6 +406,12 @@ }, {"Invalid config dies", ?_assertThrow({error, {bad_config, _}}, start_handlers(foo, BadToo)) + }, + {"Old Lager config works", + ?_assertEqual([ok, ok, ok, ok], [ check_handler_config(M, C) || {M, C} <- OldSchoolLagerGood]) + }, + {"New Config missing its list should fail", + ?_assertThrow({error, {bad_config, foo_backend}}, [ check_handler_config(M, C) || {M, C} <- NewConfigMissingList]) } ]. -endif.
View file
lager-3.1.0.tar.gz/src/lager_crash_log.erl -> lager-3.2.4.tar.gz/src/lager_crash_log.erl
Changed
@@ -46,8 +46,8 @@ -record(state, { name :: string(), - fd :: pid(), - inode :: integer(), + fd :: pid() | undefined, + inode :: integer() | undefined, fmtmaxbytes :: integer(), size :: integer(), date :: undefined | string(), @@ -119,7 +119,7 @@ %% ===== Begin code lifted from riak_err ===== -spec limited_fmt(string(), list(), integer()) -> iolist(). -%% @doc Format Fmt and Args similar to what io_lib:format/2 does but with +%% @doc Format Fmt and Args similar to what io_lib:format/2 does but with %% limits on how large the formatted string may be. %% %% If the Args list's size is larger than TermMaxSize, then the
View file
lager-3.1.0.tar.gz/src/lager_file_backend.erl -> lager-3.2.4.tar.gz/src/lager_file_backend.erl
Changed
@@ -57,8 +57,8 @@ -record(state, { name :: string(), level :: {'mask', integer()}, - fd :: file:io_device(), - inode :: integer(), + fd :: file:io_device() | undefined, + inode :: integer() | undefined, flap=false :: boolean(), size = 0 :: integer(), date :: undefined | string(), @@ -81,7 +81,7 @@ {check_interval, non_neg_integer()} | {formatter, atom()} | {formatter_config, term()}. --spec init([option(),...]) -> {ok, #state{}} | {error, bad_config}. +-spec init([option(),...]) -> {ok, #state{}} | {error, {fatal,bad_config}}. init({FileName, LogLevel}) when is_list(FileName), is_atom(LogLevel) -> %% backwards compatibility hack init([{file, FileName}, {level, LogLevel}]); @@ -158,7 +158,7 @@ NewState = case Drop > 0 of true -> Report = io_lib:format( - "lager_file_backend dropped ~p messages in the last second that exceeded the limit of ~p messages/sec", + "lager_file_backend dropped ~p messages in the last second that exceeded the limit of ~p messages/sec", [Drop, Hwm]), ReportMsg = lager_msg:new(Report, warning, [], []), write(State, lager_msg:timestamp(ReportMsg), @@ -520,7 +520,12 @@ application:set_env(lager, handlers, [{lager_test_backend, info}]), application:set_env(lager, error_logger_redirect, false), application:set_env(lager, async_threshold, undefined), - lager:start() + lager:start(), + %% race condition where lager logs its own start up + %% makes several tests fail. See test/lager_test_backend + %% around line 800 for more information. + timer:sleep(5), + lager_test_backend:flush() end, fun(_) -> file:delete("test.log"), @@ -647,7 +652,7 @@ lager:log(error, self(), "Test message1"), gen_event:call(lager_event, {lager_file_backend, "test.log"}, rotate, infinity), lager:log(error, self(), "Test message1"), - ?assert(filelib:is_regular("test.log.0")) + ?assert(filelib:is_regular("test.log.0")) end }, {"sync_on option should work", @@ -799,6 +804,64 @@ ] }. +trace_files_test_() -> + {foreach, + fun() -> + file:delete("events.log"), + file:delete("test.log"), + file:delete("debug.log"), + error_logger:tty(false), + application:load(lager), + application:set_env(lager, handlers, [{lager_file_backend, [{file, "test.log"}, + {level, error}, + {formatter, lager_default_formatter}, + {formatter_config, [message, "\n"]}]}]), + application:set_env(lager, traces, [ + { % get default level of debug + {lager_file_backend, "debug.log"}, [{module, ?MODULE}] + }, + { % Handler Filters Level + {lager_file_backend, "events.log"}, [{module, ?MODULE}], notice + } + ] + ), + application:set_env(lager, async_threshold, undefined), + lager:start() + end, + fun(_) -> + catch ets:delete(lager_config), + application:unset_env(lager, traces), + application:stop(lager), + + file:delete("events.log"), + file:delete("test.log"), + file:delete("debug.log"), + error_logger:tty(true) + end, + [ + {"a trace using file backend set up in configuration should work", + fun() -> + lager:error("trace test error message"), + lager:info("info message"), + %% not eligible for trace + lager:log(error, self(), "Not trace test message"), + {ok, BinInfo} = file:read_file("events.log"), + ?assertMatch([_, _, "[error]", _, "trace test error message\n"], + re:split(BinInfo, " ", [{return, list}, {parts, 5}])), + ?assert(filelib:is_regular("test.log")), + {ok, BinInfo2} = file:read_file("test.log"), + ?assertMatch(["trace test error message", "Not trace test message\n"], + re:split(BinInfo2, "\n", [{return, list}, {parts, 2}])), + ?assert(filelib:is_regular("debug.log")), + %% XXX Aughhhh, wish I could force this to flush somehow... + timer:sleep(1000), + {ok, BinInfo3} = file:read_file("debug.log"), + ?assertEqual(2, length(re:split(BinInfo3, "\n", [{return, list}, trim]))) + end + } + ] + }. + formatting_test_() -> {foreach, fun() -> @@ -808,7 +871,9 @@ application:load(lager), application:set_env(lager, handlers, [{lager_test_backend, info}]), application:set_env(lager, error_logger_redirect, false), - lager:start() + lager:start(), + %% same race condition issue + timer:sleep(5) end, fun(_) -> file:delete("test.log"),
View file
lager-3.1.0.tar.gz/src/lager_format.erl -> lager-3.2.4.tar.gz/src/lager_format.erl
Changed
@@ -245,18 +245,34 @@ Term = lager_trunc_io:fprint(A, L, [{depth, Depth}, {lists_as_strings, true}]), {Term, lists:flatlength(Term)}; control2($s, [L0], F, Adj, P, Pad, latin1, L) -> - List = lager_trunc_io:fprint(maybe_flatten(L0), L, [{force_strings, true}]), + List = lager_trunc_io:fprint(iolist_to_chars(L0), L, [{force_strings, true}]), Res = string(List, F, Adj, P, Pad), {Res, lists:flatlength(Res)}; control2($s, [L0], F, Adj, P, Pad, unicode, L) -> - List = lager_trunc_io:fprint(unicode:characters_to_list(L0), L, [{force_strings, true}]), + List = lager_trunc_io:fprint(cdata_to_chars(L0), L, [{force_strings, true}]), Res = uniconv(string(List, F, Adj, P, Pad)), {Res, lists:flatlength(Res)}. -maybe_flatten(X) when is_list(X) -> - lists:flatten(X); -maybe_flatten(X) -> - X. +iolist_to_chars([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 -> + [C | iolist_to_chars(Cs)]; +iolist_to_chars([I|Cs]) -> + [iolist_to_chars(I) | iolist_to_chars(Cs)]; +iolist_to_chars([]) -> + []; +iolist_to_chars(B) when is_binary(B) -> + binary_to_list(B). + +cdata_to_chars([C|Cs]) when is_integer(C), C >= $\000 -> + [C | cdata_to_chars(Cs)]; +cdata_to_chars([I|Cs]) -> + [cdata_to_chars(I) | cdata_to_chars(Cs)]; +cdata_to_chars([]) -> + []; +cdata_to_chars(B) when is_binary(B) -> + case catch unicode:characters_to_list(B) of + L when is_list(L) -> L; + _ -> binary_to_list(B) + end. make_options([], Options) -> Options;
View file
lager-3.1.0.tar.gz/src/lager_handler_watcher.erl -> lager-3.2.4.tar.gz/src/lager_handler_watcher.erl
Changed
@@ -61,6 +61,18 @@ {stop, normal, State}; handle_info({gen_event_EXIT, Module, shutdown}, #state{module=Module} = State) -> {stop, normal, State}; +handle_info({gen_event_EXIT, Module, {'EXIT', {kill_me, [_KillerHWM, KillerReinstallAfter]}}}, + #state{module=Module, sink=Sink} = State) -> + %% Brutally kill the manager but stay alive to restore settings. + %% + %% SinkPid here means the gen_event process. Handlers *all* live inside the + %% same gen_event process space, so when the Pid is killed, *all* of the + %% pending log messages in its mailbox will die too. + SinkPid = whereis(Sink), + unlink(SinkPid), + exit(SinkPid, kill), + erlang:send_after(KillerReinstallAfter, self(), {reboot, Sink}), + {noreply, State}; handle_info({gen_event_EXIT, Module, Reason}, #state{module=Module, config=Config, sink=Sink} = State) -> case lager:log(error, self(), "Lager event handler ~p exited with reason ~s", @@ -75,6 +87,9 @@ handle_info(reinstall_handler, #state{module=Module, config=Config, sink=Sink} = State) -> install_handler(Sink, Module, Config), {noreply, State}; +handle_info({reboot, Sink}, State) -> + _ = lager_app:boot(Sink), + {noreply, State}; handle_info(stop, State) -> {stop, normal, State}; handle_info(_Info, State) -> @@ -135,11 +150,10 @@ application:unset_env(lager, crash_log), lager:start(), try - ?assertEqual(1, lager_test_backend:count()), {_Level, _Time, Message, _Metadata} = lager_test_backend:pop(), ?assertMatch("Lager failed to install handler lager_crash_backend into lager_event, retrying later :"++_, lists:flatten(Message)), - ?assertEqual(0, lager_test_backend:count()), timer:sleep(6000), + lager_test_backend:flush(), ?assertEqual(0, lager_test_backend:count()), ?assert(lists:member(lager_crash_backend, gen_event:which_handlers(lager_event))) after @@ -162,14 +176,12 @@ application:unset_env(lager, crash_log), lager:start(), try - ?assertEqual(0, lager_test_backend:count()), ?assert(lists:member(lager_crash_backend, gen_event:which_handlers(lager_event))), timer:sleep(6000), - ?assertEqual(2, lager_test_backend:count()), - {_Severity, _Date, Msg, _Metadata} = lager_test_backend:pop(), - ?assertEqual("Lager event handler lager_crash_backend exited with reason crash", lists:flatten(Msg)), - {_Severity2, _Date2, Msg2, _Metadata2} = lager_test_backend:pop(), - ?assertMatch("Lager failed to install handler lager_crash_backend into lager_event, retrying later :"++_, lists:flatten(Msg2)), + + pop_until("Lager event handler lager_crash_backend exited with reason crash", fun lists:flatten/1), + pop_until("Lager failed to install handler lager_crash_backend into lager_event, retrying later", + fun(Msg) -> string:substr(lists:flatten(Msg), 1, 84) end), ?assertEqual(false, lists:member(lager_crash_backend, gen_event:which_handlers(lager_event))) after application:stop(lager), @@ -180,5 +192,17 @@ ] }. +pop_until(String, Fun) -> + try_backend_pop(lager_test_backend:pop(), String, Fun). + +try_backend_pop(undefined, String, _Fun) -> + throw("Not found: " ++ String); +try_backend_pop({_Severity, _Date, Msg, _Metadata}, String, Fun) -> + case Fun(Msg) of + String -> + ok; + _ -> + try_backend_pop(lager_test_backend:pop(), String, Fun) + end. -endif.
View file
lager-3.2.4.tar.gz/src/lager_manager_killer.erl
Added
@@ -0,0 +1,53 @@ +-module(lager_manager_killer). +-author("Sungjin Park <jinni.park@gmail.com>"). +-behavior(gen_event). + +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). + +-export([kill_me/0]). + +-include("lager.hrl"). + +-record(state, { + killer_hwm :: non_neg_integer(), + killer_reinstall_after :: non_neg_integer() + }). + +kill_me() -> + gen_event:call(lager_event, ?MODULE, kill_self). + +init([KillerHWM, KillerReinstallAfter]) -> + {ok, #state{killer_hwm=KillerHWM, killer_reinstall_after=KillerReinstallAfter}}. + +handle_call(get_loglevel, State) -> + {ok, {mask, ?LOG_NONE}, State}; +handle_call({set_loglevel, _Level}, State) -> + {ok, ok, State}; +handle_call(get_settings, State = #state{killer_hwm=KillerHWM, killer_reinstall_after=KillerReinstallAfter}) -> + {ok, [KillerHWM, KillerReinstallAfter], State}; +handle_call(kill_self, #state{killer_hwm=KillerHWM, killer_reinstall_after=KillerReinstallAfter}) -> + exit({kill_me, [KillerHWM, KillerReinstallAfter]}); +handle_call(_Request, State) -> + {ok, ok, State}. +%% It's not the best idea in the world to check the queue length for every +%% log message. We can make this operation work on a poll timer in the +%% future. +handle_event({log, _Message}, State = #state{killer_hwm=KillerHWM, killer_reinstall_after=KillerReinstallAfter}) -> + {message_queue_len, Len} = process_info(self(), message_queue_len), + case Len > KillerHWM of + true -> + exit({kill_me, [KillerHWM, KillerReinstallAfter]}); + _ -> + {ok, State} + end; +handle_event(_Event, State) -> + {ok, State}. + +handle_info(_Info, State) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}.
View file
lager-3.1.0.tar.gz/src/lager_stdlib.erl -> lager-3.2.4.tar.gz/src/lager_stdlib.erl
Changed
@@ -83,12 +83,7 @@ Val; undefined -> %% Backwards compatible: - case application:get_env(stdlib, utc_log) of - {ok, Val} -> - Val; - undefined -> - false - end + lager_app:get_env(stdlib, utc_log, false) end, if UTC =:= true ->
View file
lager-3.1.0.tar.gz/src/lager_sup.erl -> lager-3.2.4.tar.gz/src/lager_sup.erl
Changed
@@ -35,8 +35,8 @@ %% set up the config, is safe even during relups lager_config:new(), %% TODO: - %% Always start lager_event as the default and make sure that - %% other gen_event stuff can start up as needed + %% Always start lager_event as the default and make sure that + %% other gen_event stuff can start up as needed %% %% Maybe a new API to handle the sink and its policy? Children = [ @@ -45,45 +45,42 @@ {lager_handler_watcher_sup, {lager_handler_watcher_sup, start_link, []}, permanent, 5000, supervisor, [lager_handler_watcher_sup]}], - %% check if the crash log is enabled - Crash = case application:get_env(lager, crash_log) of - {ok, undefined} -> - []; - {ok, false} -> - []; - {ok, File} -> - MaxBytes = case application:get_env(lager, crash_log_msg_size) of - {ok, Val} when is_integer(Val) andalso Val > 0 -> Val; - _ -> 65536 - end, - RotationSize = case application:get_env(lager, crash_log_size) of - {ok, Val1} when is_integer(Val1) andalso Val1 >= 0 -> Val1; - _ -> 0 - end, - RotationCount = case application:get_env(lager, crash_log_count) of - {ok, Val2} when is_integer(Val2) andalso Val2 >=0 -> Val2; - _ -> 0 - end, - RotationDate = case application:get_env(lager, crash_log_date) of - {ok, Val3} -> - case lager_util:parse_rotation_date_spec(Val3) of - {ok, Spec} -> Spec; - {error, _} when Val3 == "" -> undefined; %% blank is ok - {error, _} -> - error_logger:error_msg("Invalid date spec for " - "crash log ~p~n", [Val3]), - undefined - end; - _ -> undefined - end, - - [{lager_crash_log, {lager_crash_log, start_link, [File, MaxBytes, - RotationSize, RotationDate, RotationCount]}, - permanent, 5000, worker, [lager_crash_log]}]; - _ -> - [] - end, + CrashLog = decide_crash_log(lager_app:get_env(lager, crash_log, false)), {ok, {{one_for_one, 10, 60}, - Children ++ Crash - }}. + Children ++ CrashLog + }}. + +validate_positive({ok, Val}, _Default) when is_integer(Val) andalso Val >= 0 -> + Val; +validate_positive(_Val, Default) -> + Default. + +determine_rotation_date({ok, ""}) -> + undefined; +determine_rotation_date({ok, Val3}) -> + case lager_util:parse_rotation_date_spec(Val3) of + {ok, Spec} -> Spec; + {error, _} -> + error_logger:error_msg("Invalid date spec for " + "crash log ~p~n", [Val3]), + undefined + end; +determine_rotation_date(_) -> + undefined. + +decide_crash_log(undefined) -> + []; +decide_crash_log(false) -> + []; +decide_crash_log(File) -> + MaxBytes = validate_positive(application:get_env(lager, crash_log_msg_size), 65536), + RotationSize = validate_positive(application:get_env(lager, crash_log_size), 0), + RotationCount = validate_positive(application:get_env(lager, crash_log_count), 0), + + RotationDate = determine_rotation_date(application:get_env(lager, crash_log_date)), + + + [{lager_crash_log, {lager_crash_log, start_link, [File, MaxBytes, + RotationSize, RotationDate, RotationCount]}, + permanent, 5000, worker, [lager_crash_log]}].
View file
lager-3.1.0.tar.gz/src/lager_transform.erl -> lager-3.2.4.tar.gz/src/lager_transform.erl
Changed
@@ -59,16 +59,19 @@ walk_ast([{function, Line, Name, Arity, walk_clauses([], Clauses)}|Acc], T); walk_ast(Acc, [{attribute, _, record, {Name, Fields}}=H|T]) -> - FieldNames = lists:map(fun({record_field, _, {atom, _, FieldName}}) -> - FieldName; - ({record_field, _, {atom, _, FieldName}, _Default}) -> - FieldName - end, Fields), + FieldNames = lists:map(fun record_field_name/1, Fields), stash_record({Name, FieldNames}), walk_ast([H|Acc], T); walk_ast(Acc, [H|T]) -> walk_ast([H|Acc], T). +record_field_name({record_field, _, {atom, _, FieldName}}) -> + FieldName; +record_field_name({record_field, _, {atom, _, FieldName}, _Default}) -> + FieldName; +record_field_name({typed_record_field, Field, _Type}) -> + record_field_name(Field). + walk_clauses(Acc, []) -> lists:reverse(Acc); walk_clauses(Acc, [{clause, Line, Arguments, Guards, Body}|T]) ->
View file
lager-3.1.0.tar.gz/src/lager_trunc_io.erl -> lager-3.2.4.tar.gz/src/lager_trunc_io.erl
Changed
@@ -882,4 +882,10 @@ ?assertError(badarg, format(65535, [], 50)), ok. +improper_io_list_test() -> + ?assertEqual(">hello", lists:flatten(format('~s', [[$>|<<"hello">>]], 50))), + ?assertEqual(">hello", lists:flatten(format('~ts', [[$>|<<"hello">>]], 50))), + ?assertEqual("helloworld", lists:flatten(format('~ts', [[<<"hello">>|<<"world">>]], 50))), + ok. + -endif.
View file
lager-3.2.4.tar.gz/test/lager_app_tests.erl
Added
@@ -0,0 +1,22 @@ +-module(lager_app_tests). + +-compile([{parse_transform, lager_transform}]). + +-include_lib("eunit/include/eunit.hrl"). + + +get_env_default_test() -> + ?assertEqual(<<"Some">>, lager_app:get_env_default(undefined, <<"Some">>)), + ?assertEqual(<<"Value">>, lager_app:get_env_default({ok, <<"Value">>}, <<"Some">>)), + ok. + +get_env_test() -> + application:set_env(myapp, mykey1, <<"Value">>), + + ?assertEqual(<<"Some">>, lager_app:get_env(myapp, mykey0, <<"Some">>)), + ?assertEqual(<<"Value">>, lager_app:get_env(myapp, mykey1, <<"Some">>)), + + ?assertEqual(undefined, lager_app:get_env(myapp, mykey0)), + ?assertEqual(<<"Value">>, lager_app:get_env(myapp, mykey1)), + ok. +
View file
lager-3.2.4.tar.gz/test/lager_manager_killer_test.erl
Added
@@ -0,0 +1,125 @@ +-module(lager_manager_killer_test). +-author("Sungjin Park <jinni.park@gmail.com>"). + +-compile([{parse_transform, lager_transform}]). + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +-define(TEST_SINK_NAME, '__lager_test_sink'). %% <-- used by parse transform +-define(TEST_SINK_EVENT, '__lager_test_sink_lager_event'). %% <-- used by lager API calls and internals for gen_event + +overload_test_() -> + {timeout, 60, + fun() -> + application:stop(lager), + application:load(lager), + Delay = 1000, % sleep 1 sec on every log + KillerHWM = 10, % kill the manager if there are more than 10 pending logs + KillerReinstallAfter = 1000, % reinstall killer after 1 sec + application:set_env(lager, handlers, [{lager_slow_backend, [{delay, Delay}]}]), + application:set_env(lager, async_threshold, undefined), + application:set_env(lager, error_logger_redirect, true), + application:set_env(lager, killer_hwm, KillerHWM), + application:set_env(lager, killer_reinstall_after, KillerReinstallAfter), + ensure_started(lager), + lager_config:set(async, true), + Manager = whereis(lager_event), + erlang:trace(all, true, [procs]), + [lager:info("~p'th message", [N]) || N <- lists:seq(1,KillerHWM+2)], + Margin = 100, + ok = confirm_manager_exit(Manager, Delay+Margin), + ok = confirm_sink_reregister(lager_event, Margin), + erlang:trace(all, false, [procs]), + wait_until(fun() -> + case proplists:get_value(lager_manager_killer, gen_event:which_handlers(lager_event)) of + [] -> false; + _ -> true + end + end, Margin, 15), + wait_until(fun() -> + case gen_event:call(lager_event, lager_manager_killer, get_settings) of + [KillerHWM, KillerReinstallAfter] -> true; + _Other -> false + end + end, Margin, 15), + application:stop(lager) + end}. + +overload_alternate_sink_test_() -> + {timeout, 60, + fun() -> + application:stop(lager), + application:load(lager), + Delay = 1000, % sleep 1 sec on every log + KillerHWM = 10, % kill the manager if there are more than 10 pending logs + KillerReinstallAfter = 1000, % reinstall killer after 1 sec + application:set_env(lager, handlers, []), + application:set_env(lager, extra_sinks, [{?TEST_SINK_EVENT, [ + {handlers, [{lager_slow_backend, [{delay, Delay}]}]}, + {killer_hwm, KillerHWM}, + {killer_reinstall_after, KillerReinstallAfter}, + {async_threshold, undefined} + ]}]), + application:set_env(lager, error_logger_redirect, true), + ensure_started(lager), + lager_config:set({?TEST_SINK_EVENT, async}, true), + Manager = whereis(?TEST_SINK_EVENT), + erlang:trace(all, true, [procs]), + [?TEST_SINK_NAME:info("~p'th message", [N]) || N <- lists:seq(1,KillerHWM+2)], + Margin = 100, + ok = confirm_manager_exit(Manager, Delay+Margin), + ok = confirm_sink_reregister(?TEST_SINK_EVENT, Margin), + erlang:trace(all, false, [procs]), + wait_until(fun() -> + case proplists:get_value(lager_manager_killer, gen_event:which_handlers(?TEST_SINK_EVENT)) of + [] -> false; + _ -> true + end + end, Margin, 15), + wait_until(fun() -> + case gen_event:call(?TEST_SINK_EVENT, lager_manager_killer, get_settings) of + [KillerHWM, KillerReinstallAfter] -> true; + _Other -> false + end + end, Margin, 15), + application:stop(lager) + end}. + +ensure_started(App) -> + case application:start(App) of + ok -> + ok; + {error, {not_started, Dep}} -> + ensure_started(Dep), + ensure_started(App) + end. + +confirm_manager_exit(Manager, Delay) -> + receive + {trace, Manager, exit, killed} -> + ?debugFmt("Manager ~p killed", [Manager]); + Other -> + ?debugFmt("OTHER MSG: ~p", [Other]), + confirm_manager_exit(Manager, Delay) + after Delay -> + ?assert(false) + end. + +confirm_sink_reregister(Sink, Delay) -> + receive + {trace, _Pid, register, Sink} -> + ?assertNot(lists:member(lager_manager_killer, gen_event:which_handlers(Sink))) + after Delay -> + ?assert(false) + end. + +wait_until(_Fun, _Delay, 0) -> + {error, too_many_retries}; +wait_until(Fun, Delay, Retries) -> + case Fun() of + true -> ok; + false -> timer:sleep(Delay), wait_until(Fun, Delay, Retries-1) + end. + +-endif.
View file
lager-3.1.0.tar.gz/test/lager_rotate.erl -> lager-3.2.4.tar.gz/test/lager_rotate.erl
Changed
@@ -46,8 +46,7 @@ lager:log(error, self(), "Test message 1"), lager:log(sink_event, error, self(), "Sink test message 1", []), lager:rotate_handler({lager_file_backend, "test1.log"}), - timer:sleep(1000), - true = filelib:is_regular("test1.log.0"), + ok = wait_until(fun() -> filelib:is_regular("test1.log.0") end, 10), lager:log(error, self(), "Test message 2"), lager:log(sink_event, error, self(), "Sink test message 2", []), @@ -73,8 +72,7 @@ lager:log(error, self(), "Test message 1"), lager:log(sink_event, error, self(), "Sink test message 1", []), lager:rotate_sink(sink_event), - timer:sleep(1000), - true = filelib:is_regular("test3.log.0"), + ok = wait_until(fun() -> filelib:is_regular("test3.log.0") end, 10), lager:log(error, self(), "Test message 2"), lager:log(sink_event, error, self(), "Sink test message 2", []), {ok, File1} = file:read_file("test1.log"), @@ -99,8 +97,7 @@ lager:log(error, self(), "Test message 1"), lager:log(sink_event, error, self(), "Sink test message 1", []), lager:rotate_all(), - timer:sleep(1000), - true = filelib:is_regular("test3.log.0"), + ok = wait_until(fun() -> filelib:is_regular("test3.log.0") end, 10), lager:log(error, self(), "Test message 2"), lager:log(sink_event, error, self(), "Sink test message 2", []), {ok, File1} = file:read_file("test1.log"), @@ -136,3 +133,11 @@ have_no_log(Data, Log) -> nomatch = binary:match(Data, Log). +wait_until(_Fun, 0) -> {error, too_many_retries}; +wait_until(Fun, Retry) -> + case Fun() of + true -> ok; + false -> + timer:sleep(500), + wait_until(Fun, Retry-1) + end.
View file
lager-3.2.4.tar.gz/test/lager_slow_backend.erl
Added
@@ -0,0 +1,34 @@ +-module(lager_slow_backend). +-author("Sungjin Park <jinni.park@gmail.com>"). +-behavior(gen_event). + +-export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). + +-include("lager.hrl"). + +-record(state, { + delay :: non_neg_integer() +}). + +init([{delay, Delay}]) -> + {ok, #state{delay=Delay}}. + +handle_call(get_loglevel, State) -> + {ok, lager_util:config_to_mask(debug), State}; +handle_call(_Request, State) -> + {ok, ok, State}. + +handle_event({log, _Message}, State) -> + timer:sleep(State#state.delay), + {ok, State}; +handle_event(_Event, State) -> + {ok, State}. + +handle_info(_Info, State) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}.
View file
lager-3.1.0.tar.gz/test/lager_test_backend.erl -> lager-3.2.4.tar.gz/test/lager_test_backend.erl
Changed
@@ -515,6 +515,8 @@ application:stop(lager), application:set_env(lager, traces, [{lager_test_backend, [{foo, bar}], debug}]), lager:start(), + timer:sleep(5), + flush(), lager:debug([{foo, bar}], "hello world"), ?assertEqual(1, count()), application:unset_env(lager, traces), @@ -537,6 +539,7 @@ end }, {"stopped trace stops and removes its event handler - default sink (gh#267)", + {timeout, 10, fun() -> Sink = ?DEFAULT_SINK, StartHandlers = gen_event:which_handlers(Sink), @@ -560,14 +563,14 @@ ?assertEqual(length(StartGlobal)+1, length(lager_config:global_get(handlers))), ok = lager:stop_trace(TestTrace2), - EndHandlers = gen_event:which_handlers(?DEFAULT_SINK), + EndHandlers = gen_event:which_handlers(Sink), EndGlobal = lager_config:global_get(handlers), {_, T3} = lager_config:get({Sink, loglevel}), ?assertEqual([], T3), ?assertEqual(StartHandlers, EndHandlers), ?assertEqual(StartGlobal, EndGlobal), ok - end + end} }, {"record printing works", fun() -> @@ -794,10 +797,24 @@ application:load(lager), application:set_env(lager, handlers, [{?MODULE, info}]), application:set_env(lager, error_logger_redirect, false), + application:unset_env(lager, traces), lager:start(), + %% There is a race condition between the application start up, lager logging its own + %% start up condition and several tests that count messages or parse the output of + %% tests. When the lager start up message wins the race, it causes these tests + %% which parse output or count message arrivals to fail. + %% + %% We introduce a sleep here to allow `flush' to arrive *after* the start up + %% message has been received and processed. + %% + %% This race condition was first exposed during the work on + %% 4b5260c4524688b545cc12da6baa2dfa4f2afec9 which introduced the lager + %% manager killer PR. + timer:sleep(5), gen_event:call(lager_event, ?MODULE, flush). cleanup(_) -> + catch ets:delete(lager_config), %% kill the ets config table with fire application:stop(lager), application:stop(goldrush), error_logger:tty(true). @@ -1127,46 +1144,66 @@ end }, {"warning messages with unicode characters in Args are printed", + %% The next 4 tests need to store the current value of + %% `error_logger:warning_map/0' into a process dictionary + %% key `warning_map' so that the error message level used + %% to process the log messages will match what lager + %% expects. + %% + %% The atom returned by `error_logger:warning_map/0' + %% changed between OTP 17 and 18 (and later releases) + %% + %% `warning_map' is consumed in the `test/sync_error_logger.erl' + %% module. The default message level used in sync_error_logger + %% was fine for OTP releases through 17 and then broke + %% when 18 was released. By storing the expected value + %% in the process dictionary, sync_error_logger will + %% use the correct message level to process the + %% messages and these tests will no longer + %% break. fun(Sink) -> + Lvl = error_logger:warning_map(), + put(warning_map, Lvl), sync_error_logger:warning_msg("~ts", ["Привет!"]), - Map = error_logger:warning_map(), _ = gen_event:which_handlers(error_logger), {Level, _, Msg,Metadata} = pop(Sink), - ?assertEqual(lager_util:level_to_num(Map),Level), + ?assertEqual(lager_util:level_to_num(Lvl),Level), ?assertEqual(self(),proplists:get_value(pid,Metadata)), ?assertEqual("Привет!", lists:flatten(Msg)) end }, - {"warning messages are printed at the correct level", fun(Sink) -> + Lvl = error_logger:warning_map(), + put(warning_map, Lvl), sync_error_logger:warning_msg("doom, doom has come upon you all"), - Map = error_logger:warning_map(), _ = gen_event:which_handlers(error_logger), {Level, _, Msg,Metadata} = pop(Sink), - ?assertEqual(lager_util:level_to_num(Map),Level), + ?assertEqual(lager_util:level_to_num(Lvl),Level), ?assertEqual(self(),proplists:get_value(pid,Metadata)), ?assertEqual("doom, doom has come upon you all", lists:flatten(Msg)) end }, {"warning reports are printed at the correct level", fun(Sink) -> + Lvl = error_logger:warning_map(), + put(warning_map, Lvl), sync_error_logger:warning_report([{i, like}, pie]), - Map = error_logger:warning_map(), _ = gen_event:which_handlers(error_logger), {Level, _, Msg,Metadata} = pop(Sink), - ?assertEqual(lager_util:level_to_num(Map),Level), + ?assertEqual(lager_util:level_to_num(Lvl),Level), ?assertEqual(self(),proplists:get_value(pid,Metadata)), ?assertEqual("i: like, pie", lists:flatten(Msg)) end }, {"single term warning reports are printed at the correct level", fun(Sink) -> + Lvl = error_logger:warning_map(), + put(warning_map, Lvl), sync_error_logger:warning_report({foolish, bees}), - Map = error_logger:warning_map(), _ = gen_event:which_handlers(error_logger), {Level, _, Msg,Metadata} = pop(Sink), - ?assertEqual(lager_util:level_to_num(Map),Level), + ?assertEqual(lager_util:level_to_num(Lvl),Level), ?assertEqual(self(),proplists:get_value(pid,Metadata)), ?assertEqual("{foolish,bees}", lists:flatten(Msg)) end @@ -1533,7 +1570,8 @@ ?assertEqual(true, lager_config:get(async)), %% put a ton of things in the queue - Workers = [spawn_monitor(fun() -> [lager:info("hello world") || _ <- lists:seq(1, 1000)] end) || _ <- lists:seq(1, 15)], + Workers = [spawn_monitor(fun() -> [lager:info("hello world") || _ <- lists:seq(1, 100)] end) + || _ <- lists:seq(1, 10)], %% serialize on mailbox _ = gen_event:which_handlers(lager_event), @@ -1551,7 +1589,9 @@ %% point in the past ?assertMatch([{sync_toggled, N}] when N > 0, ets:lookup(async_threshold_test, sync_toggled)), - %% wait for all the workers to return, meaning that all the messages have been logged (since we're definitely in sync mode at the end of the run) + %% wait for all the workers to return, meaning that all + %% the messages have been logged (since we're + %% definitely in sync mode at the end of the run) collect_workers(Workers), %% serialize on the mailbox again _ = gen_event:which_handlers(lager_event),
View file
lager-3.1.0.tar.gz/test/zzzz_gh280_crash.erl -> lager-3.2.4.tar.gz/test/zzzz_gh280_crash.erl
Changed
@@ -10,6 +10,9 @@ -include_lib("eunit/include/eunit.hrl"). gh280_crash_test() -> + {timeout, 30, fun() -> gh280_impl() end}. + +gh280_impl() -> application:stop(lager), application:stop(goldrush), @@ -25,7 +28,7 @@ {Handler,Reason}; X -> X - after 1000 -> + after 10000 -> timeout end, ?assert(Result),
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.