Просмотр исходного кода

Add a terminate event to the tracer and more tests

Loïc Hoguin 7 лет назад
Родитель
Сommit
da304799fe
2 измененных файлов с 67 добавлено и 8 удалено
  1. 10 4
      src/cowboy_tracer_h.erl
  2. 57 4
      test/tracer_SUITE.erl

+ 10 - 4
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, _, _, _) ->

+ 57 - 4
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),