Packages

Fault-tolerant dataflow DSL

Current section

Files

Jump to
kflow src framework kflow_lib.erl
Raw

src/framework/kflow_lib.erl

%%%===================================================================
%%% @copyright 2019 Klarna Bank AB (publ)
%%% @private
%%%===================================================================
-module(kflow_lib).
-include("kflow_int.hrl").
-export([ optional_callback/4
, optional_callback/3
, ensure_log/1
, root_node_id/1
, cfg/1
, pretty_print_node_id/1
, redirect_logs/1
]).
-spec optional_callback(module(), atom(), list()) -> ok.
optional_callback(Module, Function, Args) ->
optional_callback(Module, Function, Args, ok).
-spec optional_callback(module(), atom(), list(), Default) -> Default.
optional_callback(Module, Function, Args, Default) ->
Arity = length(Args),
erlang:module_loaded(Module) orelse code:ensure_loaded(Module),
case erlang:function_exported(Module, Function, Arity) of
true ->
apply(Module, Function, Args);
false ->
Default
end.
-spec ensure_log(atom()) -> ok.
ensure_log(Id) ->
Formatter = ?cfg(pipe_log_formatter),
DefaultLogLevel = ?cfg(pipe_log_level),
LogLevels = ?cfg(pipe_log_levels),
LogDir = ?cfg(log_dir),
MyLogLevel = maps:get(Id, LogLevels, DefaultLogLevel),
File = filename:join(LogDir, atom_to_list(Id)),
Domain = root_node_id(Id),
Filter = {fun logger_filters:domain/2, {log, sub, Domain}},
logger:add_handler( Id
, logger_disk_log_h
, #{ level => MyLogLevel
, config => #{file => File}
, formatter => Formatter
, filter_default => stop
, filters => [{domain, Filter}]
}
),
ok.
-spec root_node_id(atom()) -> kflow:node_id().
root_node_id(Root) ->
[kflow_pipe, Root].
-spec cfg(atom()) -> term().
cfg(Key) ->
{ok, Val} = application:get_env(kflow, Key),
Val.
-spec pretty_print_node_id(kflow:node_id()) -> file:filename_all().
pretty_print_node_id(NodeId) ->
filename:join(['/' | NodeId]).
%% @private Small hack to make log messages of a process end up in our
%% dedicated log. `Pid' should be a `gen_server' or such.
-spec redirect_logs(pid() | atom()) -> ok.
redirect_logs(Pid) ->
case logger:get_process_metadata() of
#{domain := Domain} ->
sys:replace_state(Pid,
fun(S) ->
logger:set_process_metadata(#{domain => Domain}),
S
end),
ok;
_ ->
ok
end.