-module(glimt). -compile(no_auto_import). -export([new/1, level/2, with_context/2, get_context/1, with_time_provider/2, new_stdout/1, append_instance/2, stdout_instance/2, stdout_anonymous_instance/1, start_instance/3, debug/2, info/2, warning/2, trace/2, error/3, fatal/3, log/3, log_with_data/4, log_error_with_data/5]). -export_type([logger/2, logger_instance/2]). -opaque logger(HNL, HNM) :: {logger, binary(), integer(), fun(() -> binary()), gleam@option:option(HNM), list(logger_instance(HNL, HNM))}. -type logger_instance(HNT, HNU) :: {direct, gleam@option:option(binary()), integer(), fun((glimt@log_message:log_message(HNT, HNU, gleam@dynamic:dynamic())) -> nil)} | {actor, gleam@option:option(binary()), integer(), gleam@erlang@process:subject(glimt@log_message:log_message(HNT, HNU, gleam@dynamic:dynamic()))}. -spec new(binary()) -> logger(any(), any()). new(Name) -> {logger, Name, glimt@log_message:level_value(all), fun now_iso/0, none, []}. -spec level(logger(HOR, HOS), glimt@log_message:log_level()) -> logger(HOR, HOS). level(Logger, Level) -> erlang:setelement(3, Logger, glimt@log_message:level_value(Level)). -spec with_context(logger(HOX, HOY), HOY) -> logger(HOX, HOY). with_context(Logger, Context) -> erlang:setelement(5, Logger, {some, Context}). -spec get_context(logger(any(), HPD)) -> gleam@option:option(HPD). get_context(Logger) -> erlang:element(5, Logger). -spec with_time_provider(logger(HPH, HPI), fun(() -> binary())) -> logger(HPH, HPI). with_time_provider(Logger, Time_provider) -> erlang:setelement(4, Logger, Time_provider). -spec new_stdout(binary()) -> logger(nil, {binary(), binary()}). new_stdout(Name) -> _pipe = new(Name), append_instance(_pipe, stdout_anonymous_instance(all)). -spec append_instance(logger(HPO, HPP), logger_instance(HPO, HPP)) -> logger(HPO, HPP). append_instance(Logger, Instance) -> erlang:setelement(6, Logger, [Instance | erlang:element(6, Logger)]). -spec stdout_instance(binary(), glimt@log_message:log_level()) -> logger_instance(any(), any()). stdout_instance(Name, Level) -> {direct, {some, Name}, glimt@log_message:level_value(Level), glimt@dispatcher@stdout:dispatcher( fun glimt@serializer@basic:basic_serializer/1 )}. -spec stdout_anonymous_instance(glimt@log_message:log_level()) -> logger_instance(any(), any()). stdout_anonymous_instance(Level) -> {direct, none, glimt@log_message:level_value(Level), glimt@dispatcher@stdout:dispatcher( fun glimt@serializer@basic:basic_serializer/1 )}. -spec start_instance( binary(), glimt@log_message:log_level(), fun((glimt@log_message:log_message(HQE, HQF, any())) -> nil) ) -> {ok, logger_instance(HQE, HQF)} | {error, gleam@otp@actor:start_error()}. start_instance(Name, Level, Dispatch) -> _pipe = start_logger_actor(Dispatch), gleam@result:map( _pipe, fun(Subject) -> {actor, {some, Name}, glimt@log_message:level_value(Level), Subject} end ). -spec start_logger_actor( fun((glimt@log_message:log_message(any(), any(), any())) -> nil) ) -> {ok, gleam@erlang@process:subject(glimt@log_message:log_message(any(), any(), gleam@dynamic:dynamic()))} | {error, gleam@otp@actor:start_error()}. start_logger_actor(Dispatch) -> gleam@otp@actor:start( Dispatch, fun(Message, Dispatch@1) -> case Message of {log_message, _, _, _, _, _, _, _, _, _, _, _} -> Dispatch@1( erlang:setelement(6, Message, {some, erlang:self()}) ); _ -> nil end, {continue, Dispatch@1} end ). -spec debug(logger(HQX, HQY), binary()) -> logger(HQX, HQY). debug(Logger, Message) -> Log_message = mk_message(Logger, debug, Message), dispatch_log(Logger, Log_message), Logger. -spec info(logger(HRD, HRE), binary()) -> logger(HRD, HRE). info(Logger, Message) -> Log_message = mk_message(Logger, info, Message), dispatch_log(Logger, Log_message), Logger. -spec warning(logger(HRJ, HRK), binary()) -> logger(HRJ, HRK). warning(Logger, Message) -> Log_message = mk_message(Logger, warning, Message), dispatch_log(Logger, Log_message), Logger. -spec trace(logger(HRP, HRQ), binary()) -> logger(HRP, HRQ). trace(Logger, Message) -> Log_message = mk_message(Logger, trace, Message), dispatch_log(Logger, Log_message), Logger. -spec error(logger(HRV, HRW), binary(), {ok, any()} | {error, any()}) -> logger(HRV, HRW). error(Logger, Message, Error) -> Log_message = mk_error_message(Logger, error, Message, Error), dispatch_log(Logger, Log_message), Logger. -spec fatal(logger(HSF, HSG), binary(), {ok, any()} | {error, any()}) -> logger(HSF, HSG). fatal(Logger, Message, Error) -> Log_message = mk_error_message(Logger, fatal, Message, Error), dispatch_log(Logger, Log_message), Logger. -spec log(logger(HSP, HSQ), glimt@log_message:log_level(), binary()) -> logger(HSP, HSQ). log(Logger, Level, Message) -> Log_message = mk_message(Logger, Level, Message), dispatch_log(Logger, Log_message), Logger. -spec log_with_data( logger(HSV, HSW), glimt@log_message:log_level(), binary(), HSV ) -> logger(HSV, HSW). log_with_data(Logger, Level, Message, Data) -> dispatch_log( Logger, {log_message, (erlang:element(4, Logger))(), erlang:element(2, Logger), erlang:self(), none, none, Level, glimt@log_message:level_value(Level), Message, none, {some, Data}, erlang:element(5, Logger)} ), Logger. -spec log_error_with_data( logger(HTB, HTC), glimt@log_message:log_level(), binary(), {ok, any()} | {error, any()}, HTB ) -> logger(HTB, HTC). log_error_with_data(Logger, Level, Message, Error, Data) -> Dynamic_result = case Error of {ok, A} -> {some, {ok, gleam@dynamic:from(A)}}; {error, A@1} -> {some, {error, gleam@dynamic:from(A@1)}} end, dispatch_log( Logger, {log_message, (erlang:element(4, Logger))(), erlang:element(2, Logger), erlang:self(), none, none, Level, glimt@log_message:level_value(Level), Message, Dynamic_result, {some, Data}, erlang:element(5, Logger)} ), Logger. -spec mk_message(logger(HTL, HTM), glimt@log_message:log_level(), binary()) -> glimt@log_message:log_message(HTL, HTM, gleam@dynamic:dynamic()). mk_message(Logger, Level, Message) -> {log_message, (erlang:element(4, Logger))(), erlang:element(2, Logger), erlang:self(), none, none, Level, glimt@log_message:level_value(Level), Message, none, none, erlang:element(5, Logger)}. -spec mk_error_message( logger(HTS, HTT), glimt@log_message:log_level(), binary(), {ok, any()} | {error, any()} ) -> glimt@log_message:log_message(HTS, HTT, gleam@dynamic:dynamic()). mk_error_message(Logger, Level, Message, Error) -> Dynamic_result = case Error of {ok, A} -> {some, {ok, gleam@dynamic:from(A)}}; {error, A@1} -> {some, {error, gleam@dynamic:from(A@1)}} end, {log_message, (erlang:element(4, Logger))(), erlang:element(2, Logger), erlang:self(), none, none, Level, glimt@log_message:level_value(Level), Message, Dynamic_result, none, erlang:element(5, Logger)}. -spec dispatch_log( logger(HUD, HUE), glimt@log_message:log_message(HUD, HUE, gleam@dynamic:dynamic()) ) -> nil. dispatch_log(Logger, Log_message) -> {log_message, _, _, _, _, _, _, Level_value, _, _, _, _} = Log_message, _pipe = erlang:element(6, Logger), gleam@list:each( _pipe, fun(Impl) -> case erlang:element(8, Log_message) >= erlang:element(3, Logger) of true -> case Impl of {direct, Instance_name, Level_min_value, Dispatch} when Level_value >= Level_min_value -> Dispatch( erlang:setelement(5, Log_message, Instance_name) ); {actor, Instance_name@1, Level_min_value@1, Subject} when Level_value >= Level_min_value@1 -> _pipe@1 = Subject, gleam@erlang@process:send( _pipe@1, erlang:setelement( 5, Log_message, Instance_name@1 ) ); _ -> nil end; _ -> nil end end ). -spec now_iso() -> binary(). now_iso() -> _pipe = birl@time:now(), birl@time:to_iso(_pipe).