aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cowboy_tracer_h.erl14
-rw-r--r--test/tracer_SUITE.erl61
2 files changed, 67 insertions, 8 deletions
diff --git a/src/cowboy_tracer_h.erl b/src/cowboy_tracer_h.erl
index 1f054e3..b69faf4 100644
--- a/src/cowboy_tracer_h.erl
+++ b/src/cowboy_tracer_h.erl
@@ -80,7 +80,7 @@ init_tracer(StreamID, Req, Opts=#{tracer_match_specs := List, tracer_callback :=
start_tracer(StreamID, Req, Opts)
end;
%% When the options tracer_match_specs or tracer_callback
-%% arenot provided we do not enable tracing.
+%% are not provided we do not enable tracing.
init_tracer(_, _, _) ->
no_tracing.
@@ -138,6 +138,8 @@ start_tracer(StreamID, Req, Opts) ->
-spec tracer_process(_, _, _) -> no_return().
tracer_process(StreamID, Req=#{pid := Parent}, Opts=#{tracer_callback := Fun}) ->
+ %% This is necessary because otherwise the tracer could stop
+ %% before it has finished processing the events in its queue.
process_flag(trap_exit, true),
State = Fun(init, {StreamID, Req, Opts}),
tracer_loop(Parent, Fun, State).
@@ -148,7 +150,7 @@ tracer_loop(Parent, Fun, State) ->
Fun(Msg, State),
tracer_loop(Parent, Fun, State);
{'EXIT', Parent, Reason} ->
- exit(Reason);
+ tracer_terminate(Reason, Fun, State);
{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], {Fun, State});
Msg ->
@@ -157,6 +159,10 @@ tracer_loop(Parent, Fun, State) ->
tracer_loop(Parent, Fun, State)
end.
+tracer_terminate(Reason, Fun, State) ->
+ _ = Fun(terminate, State),
+ exit(Reason).
+
%% System callbacks.
-spec system_continue(pid(), _, {fun(), any()}) -> no_return().
@@ -164,8 +170,8 @@ system_continue(Parent, _, {Fun, State}) ->
tracer_loop(Parent, Fun, State).
-spec system_terminate(any(), _, _, _) -> no_return().
-system_terminate(Reason, _, _, _) ->
- exit(Reason).
+system_terminate(Reason, _, _, {Fun, State}) ->
+ tracer_terminate(Reason, Fun, State).
-spec system_code_change(Misc, _, _, _) -> {ok, Misc} when Misc::any().
system_code_change(Misc, _, _, _) ->
diff --git a/test/tracer_SUITE.erl b/test/tracer_SUITE.erl
index 40ede6c..6f83fd3 100644
--- a/test/tracer_SUITE.erl
+++ b/test/tracer_SUITE.erl
@@ -93,16 +93,69 @@ do_get(Path, Config) ->
{ok, _Body} = gun:await_body(ConnPid, Ref),
gun:close(ConnPid).
-%% We only care about cowboy_req:reply/4 calls.
+%% We only care about cowboy_req:reply/4 calls and init/terminate events.
do_tracer_callback(Pid) ->
fun
- (init, _) -> undefined;
- (Event={trace_ts, _, call, {cowboy_req, reply, _}, _}, State) -> Pid ! Event, State;
- (_, State) -> State
+ (Event, _) when Event =:= init; Event =:= terminate ->
+ Pid ! Event,
+ undefined;
+ (Event={trace_ts, _, call, {cowboy_req, reply, _}, _}, State) ->
+ Pid ! Event,
+ State;
+ (_, State) ->
+ State
end.
%% Tests.
+init(Config) ->
+ doc("Ensure the init event is triggered."),
+ Ref = config(ref, Config),
+ Opts = ranch:get_protocol_options(Ref),
+ ranch:set_protocol_options(Ref, Opts#{
+ tracer_callback => do_tracer_callback(self()),
+ tracer_match_specs => [fun(_,_,_) -> true end]
+ }),
+ do_get("/", Config),
+ receive
+ init ->
+ ok
+ after 100 ->
+ error(timeout)
+ end.
+
+terminate(Config) ->
+ doc("Ensure the terminate event is triggered."),
+ Ref = config(ref, Config),
+ Opts = ranch:get_protocol_options(Ref),
+ ranch:set_protocol_options(Ref, Opts#{
+ tracer_callback => do_tracer_callback(self()),
+ tracer_match_specs => [fun(_,_,_) -> true end]
+ }),
+ do_get("/", Config),
+ receive
+ terminate ->
+ ok
+ after 100 ->
+ error(timeout)
+ end.
+
+empty(Config) ->
+ doc("Empty match specs unconditionally enable tracing."),
+ Ref = config(ref, Config),
+ Opts = ranch:get_protocol_options(Ref),
+ ranch:set_protocol_options(Ref, Opts#{
+ tracer_callback => do_tracer_callback(self()),
+ tracer_match_specs => []
+ }),
+ do_get("/", Config),
+ receive
+ {trace_ts, _, call, {cowboy_req, reply, [200, _, _, _]}, _} ->
+ ok
+ after 100 ->
+ error(timeout)
+ end.
+
predicate_true(Config) ->
doc("Predicate function returns true, unconditionally enable tracing."),
Ref = config(ref, Config),