Current section

Files

Jump to
partisan src partisan_telemetry.erl_draft
Raw

src/partisan_telemetry.erl_draft

-module(partisan_telemetry).
-export([span/3]).
%% =============================================================================
%% API
%% =============================================================================
%% -----------------------------------------------------------------------------
%% @doc This is a re-write of {@link telemetry:span/3} that provides an async
%% implementation of {@link telemetry:execute/3}.
%%
%% The telemetry library's implementation calls the handlers sequentially
%% with the start event before calling `SpanFunction' and then again with the
%% end or exception event after calling it.
%%
%% This is bad as users might inadvertedly attach too many handlers and or slow
%% handlers, affecting the observed execution time of the Partisan function
%% that wants to use this function.
%% @end
%% -----------------------------------------------------------------------------
-spec span(
telemetry:event_prefix(),
telemetry:event_metadata(),
telemetry:span_function()) -> telemetry:span_result().
span(EventPrefix, StartMeta, SpanFunction) ->
StartTime = erlang:monotonic_time(),
SysTime = erlang:system_time(),
try {_, #{}} = SpanFunction() of
{Result, StopMeta} ->
StopTime = erlang:monotonic_time(),
ok = execute(
EventPrefix, StartMeta, StopMeta, SysTime, StartTime, StopMeta
),
Result
catch
?WITH_STACKTRACE(Class, Reason, Stacktrace)
StopTime = erlang:monotonic_time(),
ok = execute(
EventPrefix, StartMeta, StopMeta, SysTime, StartTime, StopMeta
),
erlang:raise(Class, Reason, Stacktrace)
end.
%% =============================================================================
%% PRIVATE
%% =============================================================================
%% @private
execute(EventPrefix, StartMeta, StopMeta, SysTime, StartTime, StopTime) ->
spawn(fun() ->
DefaultCtx = erlang:make_ref(),
ok = execute(
EventPrefix ++ [start],
#{monotonic_time => StartTime, system_time => SysTime},
merge_ctx(StartMeta, DefaultCtx)
),
ok = execute(
EventPrefix ++ [stop],
#{duration => StopTime - StartTime, monotonic_time => StopTime},
merge_ctx(StopMeta, DefaultCtx)
)
end.
%% -----------------------------------------------------------------------------
%% @private
%% @doc
%% @end
%% -----------------------------------------------------------------------------
-spec merge_ctx(event_metadata(), any()) -> event_metadata().
merge_ctx(#{telemetry_span_context := _} = Metadata, _Ctx) ->
Metadata;
merge_ctx(Metadata, Ctx) ->
Metadata#{telemetry_span_context => Ctx}.