rebar3/src/rebar_log.erl

167 lines
5.6 KiB
Erlang
Raw Permalink Normal View History

2021-12-27 19:09:21 +00:00
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ts=4 sw=4 et
%% -------------------------------------------------------------------
%%
%% rebar: Erlang Build Tools
%%
%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
%%
%% Permission is hereby granted, free of charge, to any person obtaining a copy
%% of this software and associated documentation files (the "Software"), to deal
%% in the Software without restriction, including without limitation the rights
%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the Software is
%% furnished to do so, subject to the following conditions:
%%
%% The above copyright notice and this permission notice shall be included in
%% all copies or substantial portions of the Software.
%%
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%% THE SOFTWARE.
%% -------------------------------------------------------------------
-module(rebar_log).
-export([init/2,
crashdump/2,
set_level/1,
get_level/0,
error_level/0,
default_level/0,
debug_level/0,
diagnostic_level/0,
intensity/0,
log/3,
is_verbose/1,
valid_level/1,
truncate/1]).
-define(ERROR_LEVEL, 0).
-define(WARN_LEVEL, 1).
-define(INFO_LEVEL, 2).
-define(DEBUG_LEVEL, 3).
-define(DIAGNOSTIC_LEVEL, 4).
-define(DFLT_INTENSITY, high).
%% ===================================================================
%% Public API
%% ===================================================================
%% @doc Returns the color intensity, we first check the application envorinment
%% if that is not set we check the environment variable REBAR_COLOR.
intensity() ->
case application:get_env(rebar, color_intensity) of
undefined ->
R = case os:getenv("REBAR_COLOR") of
"high" ->
high;
"low" ->
low;
"none" ->
none;
_ ->
?DFLT_INTENSITY
end,
application:set_env(rebar, color_intensity, R),
R;
{ok, Mode} ->
Mode
end.
init(Caller, Verbosity) ->
Level = case valid_level(Verbosity) of
?ERROR_LEVEL -> error;
?WARN_LEVEL -> warn;
?INFO_LEVEL -> info;
?DEBUG_LEVEL -> debug;
?DIAGNOSTIC_LEVEL -> debug
end,
Intensity = intensity(),
application:set_env(rebar, log_caller, Caller),
Log = ec_cmd_log:new(Level, Caller, Intensity),
set_level(valid_level(Verbosity)),
application:set_env(rebar, log, Log).
set_level(Level) ->
ok = application:set_env(rebar, log_level, Level).
get_level() ->
case application:get_env(rebar, log_level) of
undefined ->
default_level();
{ok, Level} ->
Level
end.
log(diagnostic, Str, Args) ->
%% The diagnostic level is intended for debug info
%% that is useful for rebar3 developers and implementers who
%% understand the internal structure; the debug level
%% itself should aim to be useful for users themselves.
%% The underlying library only supports debug at its lowest
%% level, so we filter on our end of the lib.
case get_level() of
?DIAGNOSTIC_LEVEL -> log(debug, Str, Args);
_ -> ok
end;
log(Level = error, Str, Args) ->
case application:get_env(rebar, log) of
{ok, LogState} ->
NewStr = lists:flatten(cf:format("~!^~ts~n", [Str])),
ec_cmd_log:Level( LogState, NewStr, Args);
undefined -> % fallback
io:format(standard_error, Str++"~n", Args)
end;
log(Level, Str, Args) ->
case application:get_env(rebar, log) of
{ok, LogState} -> ec_cmd_log:Level(LogState, Str++"~n", Args);
undefined -> io:format(Str++"~n", Args)
end.
crashdump(Str, Args) ->
crashdump("rebar3.crashdump", Str, Args).
crashdump(File, Str, Args) ->
case application:get_env(rebar, log_caller) of
{ok, api} ->
ok;
_ ->
file:write_file(File, io_lib:fwrite(Str, Args))
end.
error_level() -> ?ERROR_LEVEL.
default_level() -> ?INFO_LEVEL.
debug_level() -> ?DEBUG_LEVEL.
diagnostic_level() -> ?DIAGNOSTIC_LEVEL.
is_verbose(State) ->
rebar_state:get(State, is_verbose, false).
valid_level(Level) ->
erlang:max(?ERROR_LEVEL, erlang:min(Level, ?DIAGNOSTIC_LEVEL)).
%% ===================================================================
%% Internal functions
%% ===================================================================
truncate(IoData) ->
Size = iolist_size(IoData),
if Size > 4096 -> [take_bytes(4096, IoData), "[...]"];
Size =< 4096 -> IoData
end.
take_bytes(0, _) -> [];
take_bytes(N, Bin) when is_binary(Bin), byte_size(Bin) > N ->
<<B:N/binary, _>> = Bin,
binary:copy(B); % avoid holding on to large refs
take_bytes(_, Bin) when is_binary(Bin) ->
Bin;
take_bytes(_, []) -> [];
take_bytes(N, [H|T]) when is_integer(H) ->
[H | take_bytes(N-1, T)];
take_bytes(N, [H|T]) when is_binary(H); is_list(H) ->
Res = take_bytes(N, H),
[Res | take_bytes(N-byte_size(Res), T)].