Current section
Files
Jump to
Current section
Files
src/lager_logentries_utils.erl
-module(lager_logentries_utils).
-export([parse_config/1,
validate_loglevel/1,
safe_json/1
]).
-type config() :: #{host := lager_logentries:host(),
port := lager_logentries:port_number(),
address_family := lager_logentries:address_family(),
level := lager_logentries:mask(),
token := iolist() | binary(),
context := [{atom(), jsx:json_term()}]
}.
%% API
-spec parse_config([{atom(), any()}]) -> {ok, config()} | {error, term()}.
parse_config(Config) when is_list(Config) ->
Level = proplists:get_value(level, Config, info),
Host = proplists:get_value(host, Config, <<"data.logentries.com">>),
Port = proplists:get_value(port, Config, 80),
AddressFamily = proplists:get_value(address_family, Config),
Token = proplists:get_value(token, Config),
Context = proplists:get_value(context, Config, []),
DefaultConfig = [{level, Level},
{host, Host},
{port, Port},
{address_family, AddressFamily},
{token, Token},
{context, Context}],
validate_settings(DefaultConfig, #{}).
%% Private
-spec validate_settings([{atom(), term()}], map()) ->
{ok, config()} | {error, term()}.
validate_settings([{Key, Value} | Rest], Acc) ->
case validate_setting(Key, Value) of
ok ->
validate_settings(Rest, Acc#{Key => Value});
{ok, NewValue} ->
validate_settings(Rest, Acc#{Key => NewValue});
{error, Error} ->
{error, Error}
end;
validate_settings([], Acc) ->
{ok, Acc}.
-spec validate_loglevel(any()) -> {ok, lager_logentries:mask()} | error.
validate_loglevel(Level) ->
try lager_util:config_to_mask(Level) of
Mask ->
{ok, Mask}
catch _:_ ->
error
end.
-spec is_uuid4(iolist() | binary()) -> boolean().
is_uuid4(Uuid) when is_list(Uuid) ->
is_uuid4(iolist_to_binary(Uuid));
is_uuid4(<<_:36/binary>> = Uuid) when is_binary(Uuid)->
true;
is_uuid4(_) ->
false.
-spec validate_setting(atom(), term()) -> ok | {ok, term()} | {error, term()}.
validate_setting(level, Level) when is_atom(Level) ->
case validate_loglevel(Level) of
{ok, Mask} -> {ok, Mask};
error -> {error, {invalid_loglevel, Level}}
end;
validate_setting(host, undefined) ->
{error, undefined_host};
validate_setting(port, undefined) ->
{error, undefined_port};
validate_setting(port, P) when not is_integer(P) ->
{error, {invalid_port, P}};
validate_setting(port, Port) when Port < 1 orelse Port > 65536 ->
{error, {invalid_port, Port}};
validate_setting(address_family, Family) when Family =/= undefined,
Family =/= inet,
Family =/= inet6 ->
{error, {invalid_address_family, Family}};
validate_setting(token, undefined) ->
{error, undefined_token};
validate_setting(token, Token) ->
case is_uuid4(Token) of
true ->
{ok, Token};
false ->
{error, {invalid_token, Token}}
end;
validate_setting(context, Context) when not is_list(Context) ->
{error, {invalid_context, Context}};
validate_setting(context, Context) ->
{ok, safe_json(Context)};
validate_setting(_, _) ->
ok.
-spec safe_json([{term(), term()}]) -> [lager_logentries:json_object()].
safe_json(Fields) ->
lists:map(fun to_json/1, Fields).
-spec to_json({term(), term()}) -> lager_logentries:json_object().
to_json({Key, Value}) when is_atom(Key);
is_binary(Key)->
{Key, json_value(Value)};
to_json({Key, Value}) when is_list(Key) ->
to_json({list_to_binary(Key), Value}).
-spec json_value(term()) -> jsx:json_term().
json_value(Pid) when is_pid(Pid) ->
list_to_binary(pid_to_list(Pid));
json_value(List) when is_list(List) ->
case io_lib:char_list(List) of
true ->
list_to_binary(List);
false ->
lists:map(fun json_value/1, List)
end;
json_value(Val) ->
Val.