[couchdb] 01/01: introduce prometheus endpoint

2020-12-03 Thread jiangphcn
This is an automated email from the ASF dual-hosted git repository.

jiangphcn pushed a commit to branch prometheus-endpoint
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 7deab47e90da8aa5bade8a58393cd1709d05ee96
Author: jiangph 
AuthorDate: Thu Dec 3 20:41:36 2020 +0800

introduce prometheus endpoint
---
 src/chttpd/src/chttpd_node.erl | 102 +
 1 file changed, 102 insertions(+)

diff --git a/src/chttpd/src/chttpd_node.erl b/src/chttpd/src/chttpd_node.erl
index 6407df1..ce4c349 100644
--- a/src/chttpd/src/chttpd_node.erl
+++ b/src/chttpd/src/chttpd_node.erl
@@ -122,6 +122,23 @@ handle_node_req(#httpd{method='GET', path_parts=[_, Node, 
<<"_system">>]}=Req) -
 send_json(Req, EJSON);
 handle_node_req(#httpd{path_parts=[_, _Node, <<"_system">>]}=Req) ->
 send_method_not_allowed(Req, "GET");
+
+% GET /_node/$node/metrics
+handle_node_req(#httpd{method='GET', path_parts=[_, Node, <<"metrics">>]}=Req) 
->
+Stats = call_node(Node, chttpd_node, get_stats, []),
+EJSON = couch_stats_httpd:to_ejson(Stats),
+Headers = [{<<"Content-Type">>, <<"text/plain">>}],
+CouchDB = get_couchdb_stats(),
+%System = couch_stats_httpd:to_ejson(get_system_stats()),
+Body = to_bin(lists:map(fun(Line) ->
+io_lib:format("~s~n", [Line])
+end, CouchDB)),
+{ok, Resp} = chttpd:start_response_length(Req, 200, Headers, size(Body)),
+chttpd:send(Resp, Body);
+handle_node_req(#httpd{path_parts=[_, _Node, <<"metrics">>]}=Req) ->
+send_method_not_allowed(Req, "GET");
+
+
 % POST /_node/$node/_restart
 handle_node_req(#httpd{method='POST', path_parts=[_, Node, 
<<"_restart">>]}=Req) ->
 call_node(Node, init, restart, []),
@@ -298,3 +315,88 @@ run_queues() ->
 [DCQ | SQs] = lists:reverse(statistics(run_queue_lengths)),
 {lists:sum(SQs), DCQ}
 end.
+
+json_to_prom(SystemJson) ->
+SystemMap  = jiffy:decode(SystemJson, [return_maps]),
+SystemList = maps:to_list(SystemMap),
+ListA = lists:map(fun({Key, Value}) ->
+couch_to_prom(<<"couchdb">>, Key, Value)
+  end, SystemList),
+lists:flatten(ListA).
+
+couch_to_prom(Prefix, Key, Value) when is_map(Value) ->
+case maps:is_key(<<"value">>, Value) of
+false ->
+ValueList = maps:to_list(Value),
+Prefix1 =  list_to_binary(binary_to_list(Prefix) ++ "_" ++ 
binary_to_list(Key)),
+lists:foldl(fun({K, V}, Results0) ->
+NewResult = couch_to_prom(Prefix1, K, V),
+[NewResult | Results0]
+end, [], ValueList);
+true ->
+MV = maps:get(<<"value">>, Value),
+MD = maps:get(<<"desc">>, Value),
+Type = maps:get(<<"type">>, Value),
+to_prom(Prefix, Key, Type, MV)
+end;
+couch_to_prom(Prefix, Key, Value) ->
+to_prom(Prefix, Key, Value).
+
+to_prom(Prefix, Metric, Value) ->
+to_prom_list(Prefix, Metric, Value).
+
+to_prom(Prefix, Metric, <<"counter">>, Value) ->
+to_prom_list(Prefix, Metric, Value);
+to_prom(Prefix, Metric, <<"gauge">>, Value) ->
+to_prom_list(Prefix, Metric, Value);
+to_prom(Prefix, Metric, <<"histogram">>, Value) when is_map(Value)  ->
+maps:fold(fun (K, V, Acc) ->
+case K of
+<<"percentile">> ->
+PN = ?l2b(?b2l(Metric)  ++ "_percentile"),
+Quantiles = lists:map(fun([Perc, Val]) ->
+case Perc of
+50 -> to_prom_list(Prefix, PN, [{quantile, 
<<"0.5">>}], Val);
+75 -> to_prom_list(Prefix, PN, [{quantile, 
<<"0.75">>}], Val);
+90 -> to_prom_list(Prefix, PN, [{quantile, 
<<"0.9">>}], Val);
+95 -> to_prom_list(Prefix, PN, [{quantile, 
<<"0.95">>}], Val);
+99 -> to_prom_list(Prefix, PN, [{quantile, 
<<"0.99">>}], Val);
+999 -> to_prom_list(Prefix, PN, [{quantile, 
<<"0.999">>}], Val)
+end
+  end, V),
+[Quantiles, Acc];
+_ ->
+[to_prom_list(Prefix, ?l2b(?b2l(Metric) ++ "_" ++ K), V), Acc]
+end
+  end, [], Value).
+
+
+to_prom_list(Prefix, Metric, Value) ->
+[to_bin(io_lib:format("~s ~p", [to_prom_name(Prefix, Metric), Value]))].
+
+to_prom_list(Prefix, Metric, Label, Value) ->
+[to_bin(io_lib:format("~s ~p", [to_prom_name(Prefix, Metric, Label), 
Value]))].
+
+to_prom_name(Prefix, Metric) ->
+to_bin(io_lib:format("~s_~s", [Prefix, Metric])).
+
+to_prom_name(Prefix, Metric, Labels) ->
+LabelParts = lists:map(fun({K, V}) ->
+lists:flatten(io_lib:format("~s=\"~s\"", [to_bin(K), to_bin(V)]))
+   end, Labels),
+case length(LabelParts) > 0 of
+true ->
+LabelStr = string:join(LabelParts, ", "),
+to_bin(io_lib:format("~s_~s{~s}", [Prefix

[couchdb] branch prometheus-endpoint created (now 7deab47)

2020-12-03 Thread jiangphcn
This is an automated email from the ASF dual-hosted git repository.

jiangphcn pushed a change to branch prometheus-endpoint
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 7deab47  introduce prometheus endpoint

This branch includes the following new commits:

 new 7deab47  introduce prometheus endpoint

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.