%% Count payload decodes on the preparation caller without production metrics. -module(albedo_lcm_preparation_test_support). -export([count_decodes/2]). count_decodes(Owner, Run) -> Processes = lists:usort([self(), Owner]), Patterns = [{albedo_conversation, unpack, 2}, {albedo_conversation, unpack_fit, 2}], Tracer = spawn(fun() -> collect(0, none) end), lists:foreach(fun(Pattern) -> erlang:trace_pattern(Pattern, true, [local]) end, Patterns), lists:foreach(fun(Pid) -> erlang:trace(Pid, true, [call, {tracer, Tracer}]) end, Processes), try Value = Run(), Tracer ! {count, self(), Processes}, receive {decode_count, Count} -> {Value, Count} end after lists:foreach(fun(Pid) -> erlang:trace(Pid, false, [call]) end, Processes), lists:foreach(fun(Pattern) -> erlang:trace_pattern(Pattern, false, [local]) end, Patterns), exit(Tracer, kill) end. %% The tracer drains its own delivery markers before answering. Keep call %% tracing enabled until the markers arrive, so queued events are retained. collect(Count, Finish) -> receive {trace, _, call, {albedo_conversation, Function, [_, _]}} when Function =:= unpack; Function =:= unpack_fit -> collect(Count + 1, Finish); {count, Reply, Processes} -> Refs = [erlang:trace_delivered(Pid) || Pid <- Processes], collect(Count, {Reply, Refs}); {trace_delivered, _, Ref} -> {Reply, Refs} = Finish, case lists:delete(Ref, Refs) of [] -> Reply ! {decode_count, Count}, collect(Count, none); Pending -> collect(Count, {Reply, Pending}) end; _ -> collect(Count, Finish) end.