File telemetry-1.2.1-git.patch of Package telemetry
diff --git a/src/telemetry.erl b/src/telemetry.erl
index 6e7f75c..20339fd 100644
--- a/src/telemetry.erl
+++ b/src/telemetry.erl
@@ -29,7 +29,7 @@
-type handler_config() :: term().
-type handler_function() :: fun((event_name(), event_measurements(), event_metadata(), handler_config()) -> any()).
-type span_result() :: term().
--type span_function() :: fun(() -> {span_result(), event_metadata()}).
+-type span_function() :: fun(() -> {span_result(), event_metadata()}) | {span_result(), event_measurements(), event_metadata()}.
-type handler() :: #{id := handler_id(),
event_name := event_name(),
function := handler_function(),
@@ -178,7 +178,7 @@ execute([_ | _] = EventName, Measurements, Metadata) when is_map(Measurements) a
%% @doc Runs the provided `SpanFunction', emitting start and stop/exception events, invoking the handlers attached to each.
%%
-%% The `SpanFunction' must return a `{result, stop_metadata}' tuple.
+%% The `SpanFunction' must return a `{result, stop_metadata}' or a `{result, extra_measurements, stop_metadata}` tuple.
%%
%% When this function is called, 2 events will be emitted via {@link execute/3}. Those events will be one of the following
%% pairs:
@@ -203,6 +203,10 @@ execute([_ | _] = EventName, Measurements, Metadata) when is_map(Measurements) a
%% should be available to both `start' and `stop' events need to supplied separately for `StartMetadata' and
%% `StopMetadata'.
%%
+%% If `SpanFunction` returns `{result, extra_measurements, stop_metadata}`, then a map of extra measurements
+%% will be merged with the measurements automatically provided. This is useful if you want to return, for example,
+%% bytes from an HTTP request. The standard measurements `duration` and `monotonic_time` cannot be overridden.
+%%
%% For `telemetry' events denoting the <strong>start</strong> of a larger event, the following data is provided:
%%
%% <p>
@@ -253,7 +257,8 @@ execute([_ | _] = EventName, Measurements, Metadata) when is_map(Measurements) a
%% % The current monotonic time minus the start monotonic time in native units
%% % by calling: erlang:monotonic_time() - start_monotonic_time
%% duration => integer(),
-%% monotonic_time => integer()
+%% monotonic_time => integer(),
+%% % User defined measurements when returning `SpanFunction` as a 3 element tuple
%% }
%% '''
%% </li>
@@ -318,7 +323,7 @@ span(EventPrefix, StartMetadata, SpanFunction) ->
merge_ctx(StartMetadata, DefaultCtx)
),
- try {_, #{}} = SpanFunction() of
+ try SpanFunction() of
{Result, StopMetadata} ->
StopTime = erlang:monotonic_time(),
execute(
@@ -326,7 +331,17 @@ span(EventPrefix, StartMetadata, SpanFunction) ->
#{duration => StopTime - StartTime, monotonic_time => StopTime},
merge_ctx(StopMetadata, DefaultCtx)
),
+ Result;
+ {Result, ExtraMeasurements, StopMetadata} ->
+ StopTime = erlang:monotonic_time(),
+ Measurements = maps:merge(ExtraMeasurements, #{duration => StopTime - StartTime, monotonic_time => StopTime}),
+ execute(
+ EventPrefix ++ [stop],
+ Measurements,
+ merge_ctx(StopMetadata, DefaultCtx)
+ ),
Result
+
catch
?WITH_STACKTRACE(Class, Reason, Stacktrace)
StopTime = erlang:monotonic_time(),
diff --git a/src/telemetry_test.erl b/src/telemetry_test.erl
index 5d0629d..61a4317 100644
--- a/src/telemetry_test.erl
+++ b/src/telemetry_test.erl
@@ -55,5 +55,6 @@ attach_event_handlers(DestPID, Events) when is_pid(DestPID) and is_list(Events)
telemetry:attach_many(Ref, Events, fun telemetry_test:handle_event/4, Config),
Ref.
+%% @hidden
handle_event(Event, Measurements, Metadata, #{dest_pid := DestPID, ref := Ref}) ->
DestPID ! {Event, Ref, Measurements, Metadata}.
diff --git a/test/telemetry_SUITE.erl b/test/telemetry_SUITE.erl
index 79d4f72..87c0927 100644
--- a/test/telemetry_SUITE.erl
+++ b/test/telemetry_SUITE.erl
@@ -336,14 +336,43 @@ invoke_successful_span_handlers(Config) ->
receive
{event, StartEvent, StartMeasurements, StartMetadata, HandlerConfig} ->
- ?assertEqual([monotonic_time, system_time], maps:keys(StartMeasurements))
+ ?assertEqual([monotonic_time, system_time], lists:sort(maps:keys(StartMeasurements)))
after
1000 -> ct:fail(timeout_receive_echo)
end,
receive
{event, StopEvent, StopMeasurements, StopMetadata, HandlerConfig} ->
- ?assertEqual([duration, monotonic_time], maps:keys(StopMeasurements))
+ ?assertEqual([duration, monotonic_time], lists:sort(maps:keys(StopMeasurements)))
+ after
+ 1000 -> ct:fail(timeout_receive_echo)
+ end.
+
+% Ensure that stop event includes custom measurements if provided
+invoke_successful_span_handlers_with_measurements(Config) ->
+ HandlerId = ?config(id, Config),
+ EventPrefix = [some, action],
+ StartEvent = EventPrefix ++ [start],
+ StopEvent = EventPrefix ++ [stop],
+ HandlerConfig = #{send_to => self()},
+ StartMetadata = #{some => start_metadata, telemetry_span_context => ctx},
+ StopMetadata = #{other => stop_metadata, telemetry_span_context => ctx},
+ ExtraMeasurements = #{other_thing => 100},
+ ErrorSpanFunction = fun() -> {ok, ExtraMeasurements, StopMetadata} end,
+
+ telemetry:attach_many(HandlerId, [StartEvent, StopEvent], fun ?MODULE:echo_event/4, HandlerConfig),
+ telemetry:span(EventPrefix, StartMetadata, ErrorSpanFunction),
+
+ receive
+ {event, StartEvent, StartMeasurements, StartMetadata, HandlerConfig} ->
+ ?assertEqual([monotonic_time, system_time], lists:sort(maps:keys(StartMeasurements)))
+ after
+ 1000 -> ct:fail(timeout_receive_echo)
+ end,
+
+ receive
+ {event, StopEvent, StopMeasurements, StopMetadata, HandlerConfig} ->
+ ?assertEqual([duration, monotonic_time, other_thing], lists:sort(maps:keys(StopMeasurements)))
after
1000 -> ct:fail(timeout_receive_echo)
end.
@@ -372,14 +401,14 @@ invoke_exception_span_handlers(Config) ->
receive
{event, StartEvent, StartMeasurements, StartMetadata, HandlerConfig} ->
- ?assertEqual([monotonic_time, system_time], maps:keys(StartMeasurements))
+ ?assertEqual([monotonic_time, system_time], lists:sort(maps:keys(StartMeasurements)))
after
1000 -> ct:fail(timeout_receive_echo)
end,
receive
{event, ExceptionEvent, StopMeasurements, ExceptionMetadata, HandlerConfig} ->
- ?assertEqual([duration, monotonic_time], maps:keys(StopMeasurements)),
+ ?assertEqual([duration, monotonic_time], lists:sort(maps:keys(StopMeasurements))),
?assertEqual([kind, reason, some, stacktrace, telemetry_span_context], lists:sort(maps:keys(ExceptionMetadata)))
after
1000 -> ct:fail(timeout_receive_echo)