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

Add informational responses to metrics

This commit is contained in:
Loïc Hoguin 2017-10-31 15:04:00 +00:00
parent 217fac7f44
commit a97640d56d
No known key found for this signature in database
GPG key ID: 8A9DF795F6FED764
3 changed files with 46 additions and 8 deletions

View file

@ -908,9 +908,9 @@ commands(State0=#state{ref=Ref, parent=Parent, socket=Socket, transport=Transpor
[{switch_protocol, Headers, Protocol, InitialState}|_Tail]) ->
%% @todo This should be the last stream running otherwise we need to wait before switching.
%% @todo If there's streams opened after this one, fail instead of 101.
State = cancel_timeout(State0),
State1 = cancel_timeout(State0),
%% Send a 101 response, then terminate the stream.
State = #state{streams=Streams} = commands(State, StreamID, [{inform, 101, Headers}]),
State = #state{streams=Streams} = info(State1, StreamID, {inform, 101, Headers}),
#stream{state=StreamState} = lists:keyfind(StreamID, #stream.id, Streams),
%% @todo We need to shutdown processes here first.
stream_call_terminate(StreamID, switch_protocol, StreamState),

View file

@ -32,6 +32,17 @@
reason => any()
}}.
-type informational_metrics() :: #{
%% Informational response status.
status := cowboy:http_status(),
%% Headers sent with the informational response.
headers := cowboy:http_headers(),
%% Time when the informational response was sent.
time := integer()
}.
-type metrics() :: #{
%% The identifier for this listener.
ref := ranch:ref(),
@ -86,6 +97,9 @@
%% process: the request process.
procs => proc_metrics(),
%% Informational responses sent before the final response.
informational => [informational_metrics()],
%% Length of the request and response bodies. This does
%% not include the framing.
req_body_length => non_neg_integer(),
@ -108,6 +122,7 @@
resp_start :: undefined | integer(),
resp_end :: undefined | integer(),
procs = #{} :: proc_metrics(),
informational = [] :: [informational_metrics()],
req_body_length = 0 :: non_neg_integer(),
resp_body_length = 0 :: non_neg_integer()
}).
@ -184,6 +199,14 @@ fold([{spawn, Pid, _}|Tail], State0=#state{procs=Procs}) ->
ProcStart = erlang:monotonic_time(),
State = State0#state{procs=Procs#{Pid => #{spawn => ProcStart}}},
fold(Tail, State);
fold([{inform, Status, Headers}|Tail],
State=#state{informational=Infos}) ->
Time = erlang:monotonic_time(),
fold(Tail, State#state{informational=[#{
status => Status,
headers => Headers,
time => Time
}|Infos]});
fold([{response, Status, Headers, Body}|Tail],
State=#state{resp_headers_filter=RespHeadersFilter}) ->
Resp = erlang:monotonic_time(),
@ -226,7 +249,8 @@ terminate(StreamID, Reason, #state{next=Next, callback=Fun,
req=Req, resp_status=RespStatus, resp_headers=RespHeaders, ref=Ref,
req_start=ReqStart, req_body_start=ReqBodyStart,
req_body_end=ReqBodyEnd, resp_start=RespStart, resp_end=RespEnd,
procs=Procs, req_body_length=ReqBodyLen, resp_body_length=RespBodyLen}) ->
procs=Procs, informational=Infos,
req_body_length=ReqBodyLen, resp_body_length=RespBodyLen}) ->
Res = cowboy_stream:terminate(StreamID, Reason, Next),
ReqEnd = erlang:monotonic_time(),
Metrics = #{
@ -244,6 +268,7 @@ terminate(StreamID, Reason, #state{next=Next, callback=Fun,
resp_start => RespStart,
resp_end => RespEnd,
procs => Procs,
informational => lists:reverse(Infos),
req_body_length => ReqBodyLen,
resp_body_length => RespBodyLen
},

View file

@ -143,7 +143,8 @@ do_get(Path, Config) ->
pid := From,
streamid := 1,
reason := normal,
req := #{}
req := #{},
informational := []
} = Metrics,
%% All good!
ok
@ -205,7 +206,8 @@ post_body(Config) ->
pid := From,
streamid := 1,
reason := normal,
req := #{}
req := #{},
informational := []
} = Metrics,
%% All good!
ok
@ -261,7 +263,8 @@ no_resp_body(Config) ->
pid := From,
streamid := 1,
reason := normal,
req := #{}
req := #{},
informational := []
} = Metrics,
%% All good!
ok
@ -353,7 +356,7 @@ do_ws(Config) ->
%% is called. We therefore only check when it spawned.
#{procs := Procs} = Metrics,
[{_, #{
spawn := ProcSpawn
spawn := _
}}] = maps:to_list(Procs),
%% Confirm other metadata are as expected.
#{
@ -361,7 +364,17 @@ do_ws(Config) ->
pid := From,
streamid := 1,
reason := switch_protocol,
req := #{}
req := #{},
%% A 101 upgrade response was sent.
informational := [#{
status := 101,
headers := #{
<<"connection">> := <<"Upgrade">>,
<<"upgrade">> := <<"websocket">>,
<<"sec-websocket-accept">> := _
},
time := _
}]
} = Metrics,
%% All good!
ok