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 <[email protected]> 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;
