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:41 UTC

[couchdb] 08/11: WIP: Trace spans into FDB land

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 5464e38d645d1a1707c94b0ed2ea117eaae32ef5
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Tue Nov 5 17:19:51 2019 -0600

    WIP: Trace spans into FDB land
---
 src/chttpd/src/chttpd.erl       |  12 ++++
 src/fabric/src/fabric2_fdb.erl  |  11 +++
 support/load-fdb-traces.escript | 155 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+)

diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index a28a33c..956a635 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -151,9 +151,21 @@ stop() ->
     catch mochiweb_http:stop(https),
     mochiweb_http:stop(?MODULE).
 
+
+ctrace_id() ->
+    TraceId = hexify(ctrace:get_trace_id()),
+    SpanId = hexify(ctrace:get_span_id()),
+    <<TraceId/binary, ":", SpanId/binary>>.
+
+hexify(Value) ->
+    Bin = binary:encode_unsigned(Value, little),
+    fabric2_util:to_hex(Bin).
+
+
 handle_request(MochiReq0) ->
     fabric2_fdb:clear_state(),
     ctrace:start_span('http.request'),
+    erlang:put(erlfdb_trace, ctrace_id()),
     erlang:put(?REWRITE_COUNT, 0),
     MochiReq = couch_httpd_vhost:dispatch_host(MochiReq0),
     handle_request_int(MochiReq).
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 2922a14..2945ee9 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -169,6 +169,17 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) ->
     end.
 
 
+ctrace_id() ->
+    TraceId = hexify(ctrace:get_trace_id()),
+    SpanId = hexify(ctrace:get_span_id()),
+    <<TraceId/binary, ":", SpanId/binary, 0:8/integer>>.
+
+
+hexify(Value) ->
+    Bin = ?uint2bin(Value),
+    fabric2_util:to_hex(Bin).
+
+
 maybe_reuse_transaction(Db, UserFun) ->
     Tx = case get(?PDICT_PREV_TRANSACTION) of
         undefined ->
diff --git a/support/load-fdb-traces.escript b/support/load-fdb-traces.escript
new file mode 100755
index 0000000..e3e1354
--- /dev/null
+++ b/support/load-fdb-traces.escript
@@ -0,0 +1,155 @@
+#!/usr/bin/env escript
+%%! -env ERL_LIBS src -noshell -s escript start
+
+-mode(compile).
+
+-export([main/1]).
+
+-define(ANCESTORS_KEY, passage_span_ancestors).
+-define(SPAN_TYPES, [
+    <<"TransactionTrace_Commit">>,
+    <<"TransactionTrace_Get">>,
+    <<"TransactionTrace_GetRange">>,
+    <<"TransactionTrace_GetVersion">>
+]).
+-define(TAG_KEYS, [
+    {<<"Key">>, key},
+    {<<"StartKey">>, 'start-key'},
+    {<<"EndKey">>, 'end-key'},
+    {<<"ValueSizeBytes">>, 'value-size-bytes'},
+    {<<"RangeSizeBytes">>, 'range-size-bytes'},
+    {<<"NumMutations">>, 'num-mutations'},
+    {<<"CommitSizeBytes">>, 'commit-size-bytes'}
+]).
+
+
+main(Args) ->
+    start_apps(),
+    start_tracer(),
+
+    lists:foreach(fun(FileName) ->
+        load_file(FileName)
+    end, Args),
+    timer:sleep(1000).
+
+
+load_file(FileName) ->
+    {ok, Data} = file:read_file(FileName),
+    Lines = binary:split(Data, <<"\r\n">>, [global]),
+    lists:foreach(fun(Line) ->
+        case string:trim(Line) of
+            <<>> ->
+                ok;
+            Else ->
+                {Props} = jiffy:decode(Else),
+                maybe_create_span(Props)
+        end
+    end, Lines).
+
+
+maybe_create_span(Props) ->
+    {_, Type} = lists:keyfind(<<"Type">>, 1, Props),
+    case lists:member(Type, ?SPAN_TYPES) of
+        true ->
+            create_span(Type, Props);
+        false ->
+            ok
+    end.
+
+
+create_span(Type, Props) ->
+    %io:format(standard_error, "~p~n", [Props]),
+    {StartTime, EndTime} = get_time(Props),
+    {TraceId, SpanId} = get_trace_ids(Props),
+    Tags = get_tags(Props),
+
+    fake_root(TraceId, SpanId),
+    passage_pd:start_span(binary_to_atom(Type, utf8), [
+        {time, StartTime},
+        {tags, Tags}
+    ]),
+    passage_pd:finish_span([{time, EndTime}]).
+
+
+get_time(Props) ->
+    {_, EndTimeBin} = lists:keyfind(<<"Time">>, 1, Props),
+    {_, LatencyBin} = lists:keyfind(<<"Latency">>, 1, Props),
+    EndTimeFloat = binary_to_float(EndTimeBin),
+    Latency = binary_to_float(LatencyBin),
+    {float_to_time(EndTimeFloat - Latency), float_to_time(EndTimeFloat)}.
+
+
+float_to_time(Val) ->
+    Mega = trunc(Val / 1000000),
+    Secs = trunc(Val) rem 1000000,
+    Micro = trunc(Val * 1000000) rem 1000000,
+    {Mega, Secs, Micro}.
+
+
+get_trace_ids(Props) ->
+    {_, TxId} = lists:keyfind(<<"TransactionID">>, 1, Props),
+    [TraceIdBin, SpanIdBin] = binary:split(TxId, <<":">>),
+    TraceId = mochihex:to_bin(binary_to_list(TraceIdBin)),
+    SpanId = mochihex:to_bin(binary_to_list(SpanIdBin)),
+    {
+        binary:decode_unsigned(TraceId, little),
+        binary:decode_unsigned(SpanId, little)
+    }.
+
+
+get_tags(Props) ->
+    lists:foldl(fun({BinKey, AtomKey}, Tags) ->
+        case lists:keyfind(BinKey, 1, Props) of
+            {_, Value} ->
+                Tags#{AtomKey => Value};
+            false ->
+                Tags
+        end
+    end, #{}, ?TAG_KEYS).
+
+
+start_apps() ->
+    Apps = [
+        jiffy,
+        passage,
+        jaeger_passage
+    ],
+    lists:foreach(fun(App) ->
+        {ok, _} = application:ensure_all_started(App)
+    end, Apps).
+
+
+start_tracer() ->
+    Sampler = passage_sampler_all:new(),
+    Options = [
+        {thrift_format, compact},
+        {agent_host, "127.0.0.1"},
+        {agent_port, 6831},
+        {default_service_name, 'fdb-client'}
+    ],
+    ok = jaeger_passage:start_tracer(main, Sampler, Options).
+
+
+fake_root(TraceId, SpanId) ->
+    Root = [{child_of, {
+        passage_span,
+        main,
+        foo,
+        {0, 0, 0},
+        undefined,
+        [],
+        #{},
+        [],
+        {
+            passage_span_context,
+            {
+                jaeger_passage_span_context,
+                TraceId,
+                SpanId,
+                true,
+                undefined
+            },
+            #{}
+        }
+    }}],
+    put(?ANCESTORS_KEY, Root).
\ No newline at end of file