From cf38dbdd51e3f690d5d6d5e7319003248b5109f4 Mon Sep 17 00:00:00 2001 From: Ethan Gunderson Date: Tue, 17 Jan 2023 14:38:40 -0600 Subject: [PATCH 1/2] small qol update to :telemetry.attach/4 docs --- src/telemetry.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/telemetry.erl b/src/telemetry.erl index 6e7f75c..afa0aff 100644 --- a/src/telemetry.erl +++ b/src/telemetry.erl @@ -56,11 +56,11 @@ %% %% See {@link execute/3} to learn how the handlers are invoked. %% -%% Note: due to how anonymous functions are implemented in the Erlang VM, it is best to use -%% function captures (i.e. `fun mod:fun/4' in Erlang or `&Mod.fun/4' in Elixir) as event handlers -%% to achieve maximum performance. In other words, avoid using literal anonymous functions -%% (`fun(...) -> ... end' or `fn ... -> ... end') or local function captures (`fun handle_event/4' -%% or `&handle_event/4' ) as event handlers. +%% `function` must be a 4 arity function. Due to how anonymous functions are implemented +%% in the Erlang VM, it is best to use function captures (i.e. `fun mod:fun/4' in Erlang or +%% `&Mod.fun/4' in Elixir) as event handlers to achieve maximum performance. In other words, +%% avoid using literal anonymous functions (`fun(...) -> ... end' or `fn ... -> ... end') or +%% local function captures (`fun handle_event/4' or `&handle_event/4' ) as event handlers. %% %% All the handlers are executed by the process dispatching event. If the function fails (raises, %% exits or throws) then the handler is removed and a failure event is emitted. From 830f38b778b36fb6321c07bd2b8dad42c2ff9167 Mon Sep 17 00:00:00 2001 From: Ethan Gunderson Date: Wed, 18 Jan 2023 09:54:23 -0600 Subject: [PATCH 2/2] raise badarg instead of function clause when a wrong arity function is supplied --- src/telemetry.erl | 9 ++++++++- test/telemetry_SUITE.erl | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/telemetry.erl b/src/telemetry.erl index afa0aff..884d24e 100644 --- a/src/telemetry.erl +++ b/src/telemetry.erl @@ -103,8 +103,9 @@ attach(HandlerId, EventName, Function, Config) -> EventName :: event_name(), Function :: handler_function(), Config :: handler_config(). -attach_many(HandlerId, EventNames, Function, Config) when is_function(Function, 4) -> +attach_many(HandlerId, EventNames, Function, Config) -> assert_event_names(EventNames), + assert_function(Function), case erlang:fun_info(Function, type) of {type, external} -> ok; @@ -369,6 +370,12 @@ assert_event_names(List) when is_list(List) -> assert_event_names(Term) -> erlang:error(badarg, Term). +-spec assert_function(term()) -> ok. +assert_function(Function) when is_function(Function, 4) -> + ok; +assert_function(Function) -> + erlang:error(badarg, Function). + -spec assert_event_prefix(term()) -> ok. assert_event_prefix(List) when is_list(List) -> case lists:all(fun erlang:is_atom/1, List) of diff --git a/test/telemetry_SUITE.erl b/test/telemetry_SUITE.erl index 79d4f72..950cb7c 100644 --- a/test/telemetry_SUITE.erl +++ b/test/telemetry_SUITE.erl @@ -14,7 +14,7 @@ all() -> handler_on_multiple_events, remove_all_handler_on_failure, list_handler_on_many, detach_from_all, old_execute, default_metadata, off_execute, invoke_successful_span_handlers, invoke_exception_span_handlers, - spans_generate_unique_default_contexts, logs_on_local_function]. + spans_generate_unique_default_contexts, logs_on_local_function, badarg_on_wrong_arity_function]. init_per_suite(Config) -> application:ensure_all_started(telemetry), @@ -426,6 +426,13 @@ spans_generate_unique_default_contexts(Config) -> 1000 -> ct:fail(timeout_receive_echo) end. +badarg_on_wrong_arity_function(Config) -> + HandlerId = ?config(id, Config), + Event = [a, first, event], + HandlerFun = fun ?MODULE:wrong_arity_function/3, + + ?assertError(badarg, telemetry:attach(HandlerId, Event, HandlerFun, nil)). + logs_on_local_function(Config) -> HandlerId = ?config(id, Config), Event = [some, action],