You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2019/12/05 19:35:35 UTC
[couchdb] 02/11: Add tracing to chttpd
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to branch opentracing-davisp
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 2d0915320ecaa0d9c70d0763d6fec7e9879cadc5
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Mon Nov 4 12:50:02 2019 -0600
Add tracing to chttpd
---
src/chttpd/src/chttpd.app.src | 1 +
src/chttpd/src/chttpd.erl | 48 ++++++++++++++++++++++++++++++++++++------
src/chttpd/src/chttpd_auth.erl | 8 +++++--
src/chttpd/src/chttpd_db.erl | 27 +++++++++++++++++++-----
4 files changed, 71 insertions(+), 13 deletions(-)
diff --git a/src/chttpd/src/chttpd.app.src b/src/chttpd/src/chttpd.app.src
index 3526745..af330e0 100644
--- a/src/chttpd/src/chttpd.app.src
+++ b/src/chttpd/src/chttpd.app.src
@@ -26,6 +26,7 @@
couch_stats,
config,
couch,
+ ctrace,
ets_lru,
fabric
]},
diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index 2f4bbcf..284b325 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -152,6 +152,7 @@ stop() ->
mochiweb_http:stop(?MODULE).
handle_request(MochiReq0) ->
+ ctrace:start_span('http.request'),
erlang:put(?REWRITE_COUNT, 0),
MochiReq = couch_httpd_vhost:dispatch_host(MochiReq0),
handle_request_int(MochiReq).
@@ -231,6 +232,15 @@ handle_request_int(MochiReq) ->
|| Part <- string:tokens(RequestedPath, "/")]
},
+ ctrace:add_tags(#{
+ peer => Peer,
+ 'http.method' => Method,
+ nonce => Nonce,
+ 'http.url' => Path,
+ 'span.kind' => <<"server">>,
+ component => <<"couchdb.chttpd">>
+ }),
+
% put small token on heap to keep requests synced to backend calls
erlang:put(nonce, Nonce),
@@ -258,7 +268,12 @@ handle_request_int(MochiReq) ->
},
case after_request(HttpReq2, HttpResp) of
- #httpd_resp{status = ok, response = Resp} ->
+ #httpd_resp{status = ok, code = Code, response = Resp} ->
+ ctrace:add_tags(#{
+ error => false,
+ 'http.status_code' => Code
+ }),
+ ctrace:finish_span(),
{ok, Resp};
#httpd_resp{status = aborted, reason = Reason} ->
couch_log:error("Response abnormally terminated: ~p", [Reason]),
@@ -321,7 +336,10 @@ handle_req_after_auth(HandlerKey, HttpReq) ->
fun chttpd_db:handle_request/1),
AuthorizedReq = chttpd_auth:authorize(possibly_hack(HttpReq),
fun chttpd_auth_request:authorize_request/1),
- {AuthorizedReq, HandlerFun(AuthorizedReq)}
+ OpName = ctrace:fun_to_op(HandlerFun),
+ ctrace:with_span(OpName, fun() ->
+ {AuthorizedReq, HandlerFun(AuthorizedReq)}
+ end)
catch Tag:Error ->
{HttpReq, catch_error(HttpReq, Tag, Error)}
end.
@@ -1050,16 +1068,34 @@ send_error(#httpd{} = Req, Code, ErrorStr, ReasonStr) ->
send_error(Req, Code, [], ErrorStr, ReasonStr, []).
send_error(Req, Code, Headers, ErrorStr, ReasonStr, []) ->
- send_json(Req, Code, Headers,
+ Result = send_json(Req, Code, Headers,
{[{<<"error">>, ErrorStr},
- {<<"reason">>, ReasonStr}]});
+ {<<"reason">>, ReasonStr}]}),
+ finish_span_error(Code, ErrorStr, ReasonStr, []),
+ Result;
send_error(Req, Code, Headers, ErrorStr, ReasonStr, Stack) ->
log_error_with_stack_trace({ErrorStr, ReasonStr, Stack}),
- send_json(Req, Code, [stack_trace_id(Stack) | Headers],
+ Result = send_json(Req, Code, [stack_trace_id(Stack) | Headers],
{[{<<"error">>, ErrorStr},
{<<"reason">>, ReasonStr} |
case Stack of [] -> []; _ -> [{<<"ref">>, stack_hash(Stack)}] end
- ]}).
+ ]}),
+ finish_span_error(Code, ErrorStr, ReasonStr, Stack),
+ Result.
+
+
+finish_span_error(Code, ErrorStr, ReasonStr, Stack) ->
+ ctrace:add_tags(#{
+ error => true,
+ 'http.status_code' => Code
+ }),
+ ctrace:log(#{
+ 'error.kind' => ErrorStr,
+ message => ReasonStr,
+ stack => Stack
+ }),
+ ctrace:finish_span().
+
update_timeout_stats(<<"timeout">>, #httpd{requested_path_parts = PathParts}) ->
update_timeout_stats(PathParts);
diff --git a/src/chttpd/src/chttpd_auth.erl b/src/chttpd/src/chttpd_auth.erl
index 6602468..e2ae1dd 100644
--- a/src/chttpd/src/chttpd_auth.erl
+++ b/src/chttpd/src/chttpd_auth.erl
@@ -32,10 +32,14 @@
%% ------------------------------------------------------------------
authenticate(HttpReq, Default) ->
- maybe_handle(authenticate, [HttpReq], Default).
+ ctrace:with_span('http.authenticate', fun() ->
+ maybe_handle(authenticate, [HttpReq], Default)
+ end).
authorize(HttpReq, Default) ->
- maybe_handle(authorize, [HttpReq], Default).
+ ctrace:with_span('http.authorize', fun() ->
+ maybe_handle(authorize, [HttpReq], Default)
+ end).
%% ------------------------------------------------------------------
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 8cfa1f4..b53ee25 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -66,21 +66,35 @@
handle_request(#httpd{path_parts=[DbName|RestParts],method=Method}=Req)->
case {Method, RestParts} of
{'PUT', []} ->
- create_db_req(Req, DbName);
+ OpName = ctrace:fun_to_op(fun create_db_req/2),
+ ctrace:with_span(OpName, fun() ->
+ create_db_req(Req, DbName)
+ end);
{'DELETE', []} ->
% if we get ?rev=... the user is using a faulty script where the
% document id is empty by accident. Let them recover safely.
case chttpd:qs_value(Req, "rev", false) of
- false -> delete_db_req(Req, DbName);
+ false ->
+ OpName = ctrace:fun_to_op(fun delete_db_req/2),
+ ctrace:with_span(OpName, fun() ->
+ delete_db_req(Req, DbName)
+ end);
_Rev -> throw({bad_request,
"You tried to DELETE a database with a ?=rev parameter. "
++ "Did you mean to DELETE a document instead?"})
end;
{_, []} ->
- do_db_req(Req, fun db_req/2);
+ Handler = fun db_req/2,
+ OpName = ctrace:fun_to_op(Handler),
+ ctrace:with_span(OpName, fun() ->
+ do_db_req(Req, fun db_req/2)
+ end);
{_, [SecondPart|_]} ->
Handler = chttpd_handlers:db_handler(SecondPart, fun db_req/2),
- do_db_req(Req, Handler)
+ OpName = ctrace:fun_to_op(fun ?MODULE:db_req/2),
+ ctrace:with_span(OpName, fun() ->
+ do_db_req(Req, Handler)
+ end)
end.
handle_changes_req(#httpd{method='POST'}=Req, Db) ->
@@ -336,7 +350,10 @@ handle_design_req(#httpd{
case fabric2_db:open_doc(Db, <<"_design/", Name/binary>>) of
{ok, DDoc} ->
Handler = chttpd_handlers:design_handler(Action, fun bad_action_req/3),
- Handler(Req, Db, DDoc);
+ OpName = ctrace:fun_to_op(Handler),
+ ctrace:with_span(OpName, fun() ->
+ Handler(Req, Db, DDoc)
+ end);
Error ->
throw(Error)
end;