aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-10-31 15:04:00 +0000
committerLoïc Hoguin <[email protected]>2017-10-31 15:04:00 +0000
commita97640d56dcb1a32ea44cb3be6575d2a4d6136c9 (patch)
treef80a72668727e850beaab14c46e935e4df247bd3
parent217fac7f4414f5ff5eda85079a179e2462aba61c (diff)
downloadcowboy-a97640d56dcb1a32ea44cb3be6575d2a4d6136c9.tar.gz
cowboy-a97640d56dcb1a32ea44cb3be6575d2a4d6136c9.tar.bz2
cowboy-a97640d56dcb1a32ea44cb3be6575d2a4d6136c9.zip
Add informational responses to metrics
-rw-r--r--src/cowboy_http.erl4
-rw-r--r--src/cowboy_metrics_h.erl27
-rw-r--r--test/metrics_SUITE.erl23
3 files changed, 46 insertions, 8 deletions
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
index f6d064e..7d19c05 100644
--- a/src/cowboy_http.erl
+++ b/src/cowboy_http.erl
@@ -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),
diff --git a/src/cowboy_metrics_h.erl b/src/cowboy_metrics_h.erl
index 1203518..03bac36 100644
--- a/src/cowboy_metrics_h.erl
+++ b/src/cowboy_metrics_h.erl
@@ -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
},
diff --git a/test/metrics_SUITE.erl b/test/metrics_SUITE.erl
index d41ae1d..1883014 100644
--- a/test/metrics_SUITE.erl
+++ b/test/metrics_SUITE.erl
@@ -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