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/11/05 17:26:53 UTC

[couchdb] 02/06: 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;