0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 20:30:23 +00:00

Add a terminate event to the tracer and more tests

This commit is contained in:
Loïc Hoguin 2017-11-03 17:52:18 +00:00
parent af58babd94
commit da304799fe
No known key found for this signature in database
GPG key ID: 8A9DF795F6FED764
2 changed files with 67 additions and 8 deletions

View file

@ -80,7 +80,7 @@ init_tracer(StreamID, Req, Opts=#{tracer_match_specs := List, tracer_callback :=
start_tracer(StreamID, Req, Opts) start_tracer(StreamID, Req, Opts)
end; end;
%% When the options tracer_match_specs or tracer_callback %% 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(_, _, _) -> init_tracer(_, _, _) ->
no_tracing. no_tracing.
@ -138,6 +138,8 @@ start_tracer(StreamID, Req, Opts) ->
-spec tracer_process(_, _, _) -> no_return(). -spec tracer_process(_, _, _) -> no_return().
tracer_process(StreamID, Req=#{pid := Parent}, Opts=#{tracer_callback := Fun}) -> 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), process_flag(trap_exit, true),
State = Fun(init, {StreamID, Req, Opts}), State = Fun(init, {StreamID, Req, Opts}),
tracer_loop(Parent, Fun, State). tracer_loop(Parent, Fun, State).
@ -148,7 +150,7 @@ tracer_loop(Parent, Fun, State) ->
Fun(Msg, State), Fun(Msg, State),
tracer_loop(Parent, Fun, State); tracer_loop(Parent, Fun, State);
{'EXIT', Parent, Reason} -> {'EXIT', Parent, Reason} ->
exit(Reason); tracer_terminate(Reason, Fun, State);
{system, From, Request} -> {system, From, Request} ->
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], {Fun, State}); sys:handle_system_msg(Request, From, Parent, ?MODULE, [], {Fun, State});
Msg -> Msg ->
@ -157,6 +159,10 @@ tracer_loop(Parent, Fun, State) ->
tracer_loop(Parent, Fun, State) tracer_loop(Parent, Fun, State)
end. end.
tracer_terminate(Reason, Fun, State) ->
_ = Fun(terminate, State),
exit(Reason).
%% System callbacks. %% System callbacks.
-spec system_continue(pid(), _, {fun(), any()}) -> no_return(). -spec system_continue(pid(), _, {fun(), any()}) -> no_return().
@ -164,8 +170,8 @@ system_continue(Parent, _, {Fun, State}) ->
tracer_loop(Parent, Fun, State). tracer_loop(Parent, Fun, State).
-spec system_terminate(any(), _, _, _) -> no_return(). -spec system_terminate(any(), _, _, _) -> no_return().
system_terminate(Reason, _, _, _) -> system_terminate(Reason, _, _, {Fun, State}) ->
exit(Reason). tracer_terminate(Reason, Fun, State).
-spec system_code_change(Misc, _, _, _) -> {ok, Misc} when Misc::any(). -spec system_code_change(Misc, _, _, _) -> {ok, Misc} when Misc::any().
system_code_change(Misc, _, _, _) -> system_code_change(Misc, _, _, _) ->

View file

@ -93,16 +93,69 @@ do_get(Path, Config) ->
{ok, _Body} = gun:await_body(ConnPid, Ref), {ok, _Body} = gun:await_body(ConnPid, Ref),
gun:close(ConnPid). 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) -> do_tracer_callback(Pid) ->
fun fun
(init, _) -> undefined; (Event, _) when Event =:= init; Event =:= terminate ->
(Event={trace_ts, _, call, {cowboy_req, reply, _}, _}, State) -> Pid ! Event, State; Pid ! Event,
(_, State) -> State undefined;
(Event={trace_ts, _, call, {cowboy_req, reply, _}, _}, State) ->
Pid ! Event,
State;
(_, State) ->
State
end. end.
%% Tests. %% 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) -> predicate_true(Config) ->
doc("Predicate function returns true, unconditionally enable tracing."), doc("Predicate function returns true, unconditionally enable tracing."),
Ref = config(ref, Config), Ref = config(ref, Config),