From 46428088b70273cf43440a33094de4c94bc5d08e Mon Sep 17 00:00:00 2001 From: Ilya Khaprov Date: Wed, 4 Oct 2017 16:22:41 +0300 Subject: [PATCH] can set labels from span attributes, can export as histogram --- mix.exs | 2 +- mix.lock | 33 ++++++++-------- rebar.config | 4 +- rebar.lock | 4 +- src/oc_prometheus_reporter.erl | 68 ++++++++++++++++++++++++++------ test/ct/oep_SUITE.erl | 72 ++++++++++++++++++++++++++++++---- 6 files changed, 141 insertions(+), 42 deletions(-) diff --git a/mix.exs b/mix.exs index c920650..8aa62db 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,7 @@ defmodule OpencensusErlangPrometheus.Mixfile do defp deps do [{:prometheus, "~> 3.4", manager: :rebar3}, - {:opencensus, git: "https://github.com/deadtrickster/opencensus-erlang", branch: "fix-mix-dep"}, + {:opencensus, git: "https://github.com/deadtrickster/opencensus-erlang", branch: "dev"}, {:credo, "~> 0.8.7", only: [:dev, :test]}, {:excoveralls, "~> 0.7.3", only: [:test]}] end diff --git a/mix.lock b/mix.lock index 41bf2e5..0f6b331 100644 --- a/mix.lock +++ b/mix.lock @@ -1,17 +1,16 @@ -%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [], [], "hexpm"}, - "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [], [], "hexpm"}, - "credo": {:hex, :credo, "0.8.7", "b1aad9cd3aa7acdbaea49765bfc9f1605dc4555023a037dc9ea7a70539615bc8", [], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.7.3", "6c05cc452e6ebfc347fccc0de7339e9bc1ed8678c52765353303fa0d2c44c70d", [], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, - "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, - "hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, - "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [], [], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], [], "hexpm"}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], [], "hexpm"}, - "opencensus": {:git, "https://github.com/deadtrickster/opencensus-erlang", "c31853dfb1656f0d057cf69b569a8792ef5bd6c5", [branch: "fix-mix-dep"]}, - "prometheus": {:hex, :prometheus, "3.4.1", "90c4f37670c4dc7de9319a0c310bf12cb619715ebe285f583f3b46d955ee8f81", [], [], "hexpm"}, - "rebar_erl_vsn": {:hex, :rebar_erl_vsn, "0.1.3", "431667f3203f19130805a8ac7cde9666d1bff7235eb2b96e2048eb839db0ed1f", [], [], "hexpm"}, - "rfc3339": {:hex, :rfc3339, "0.9.0", "2075653dc9407541c84b1e15f8bda2abe95fb17c9694025e079583f2d19c1060", [], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [], [], "hexpm"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [], [], "hexpm"}, - "wts": {:hex, :wts, "0.3.0", "5cdf22c775cb1ebae24c326a5db6074d753c42f4bd12a9aa47cc62d3e2c71ad1", [], [{:rfc3339, "~>0.9.0", [hex: :rfc3339, repo: "hexpm", optional: false]}], "hexpm"}} +%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, + "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, + "credo": {:hex, :credo, "0.8.7", "b1aad9cd3aa7acdbaea49765bfc9f1605dc4555023a037dc9ea7a70539615bc8", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.7.3", "6c05cc452e6ebfc347fccc0de7339e9bc1ed8678c52765353303fa0d2c44c70d", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, + "hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, + "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, + "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, + "opencensus": {:git, "https://github.com/deadtrickster/opencensus-erlang", "7e248db230955fb3c441627dd2c7375aa67eb5a5", [branch: "dev"]}, + "prometheus": {:hex, :prometheus, "3.4.1", "90c4f37670c4dc7de9319a0c310bf12cb619715ebe285f583f3b46d955ee8f81", [:mix, :rebar3], [], "hexpm"}, + "rfc3339": {:hex, :rfc3339, "0.9.0", "2075653dc9407541c84b1e15f8bda2abe95fb17c9694025e079583f2d19c1060", [:mix, :rebar], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}, + "wts": {:hex, :wts, "0.3.0", "5cdf22c775cb1ebae24c326a5db6074d753c42f4bd12a9aa47cc62d3e2c71ad1", [:rebar3], [{:rfc3339, "~>0.9.0", [hex: :rfc3339, repo: "hexpm", optional: false]}], "hexpm"}} diff --git a/rebar.config b/rebar.config index 94b9df2..081819b 100644 --- a/rebar.config +++ b/rebar.config @@ -5,8 +5,8 @@ {deps, [{prometheus, "3.4.1"}, {opencensus, - {git, "https://github.com/census-instrumentation/opencensus-erlang", - {branch, "master"}}}]}. + {git, "https://github.com/deadtrickster/opencensus-erlang", + {branch, "dev"}}}]}. % {shell, [{apps, [opencensus_erlang_prometheus]}]}. {cover_enabled, true}. {cover_export_enabled, true}. diff --git a/rebar.lock b/rebar.lock index b5aa906..535e035 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.1.0", [{<<"opencensus">>, - {git,"https://github.com/census-instrumentation/opencensus-erlang", - {ref,"b8fecf303896a9bdbfe9d1f83371a5bc1e88a28a"}}, + {git,"https://github.com/deadtrickster/opencensus-erlang", + {ref,"7e248db230955fb3c441627dd2c7375aa67eb5a5"}}, 0}, {<<"prometheus">>,{pkg,<<"prometheus">>,<<"3.4.1">>},0}, {<<"rfc3339">>,{pkg,<<"rfc3339">>,<<"0.9.0">>},2}, diff --git a/src/oc_prometheus_reporter.erl b/src/oc_prometheus_reporter.erl index d8bbc69..b7b29c7 100644 --- a/src/oc_prometheus_reporter.erl +++ b/src/oc_prometheus_reporter.erl @@ -11,21 +11,65 @@ %% API %% =================================================================== -init(_) -> - prometheus_summary:declare([{name, "span"}, - {labels, [name]}, - {help, "Opencensus span"}]), - ok. - -report(Spans, _Opts) -> - [ - prometheus_summary:observe("span", [Span#span.name], - wts:duration(Span#span.start_time, Span#span.end_time)) +init(Config) -> + Type = config_metric_type(Config), + Name = config_metric_name(Config), + Labels = config_metric_labels(Config), + {LabelNames, Attributes} = lists:unzip(Labels), + Type:declare([{name, Name}, + {labels, [name] ++ LabelNames}, + {buckets, config_metric_buckets(Config)}, + {help, "Opencensus span metric"}]), + {Type, Name, Attributes}. - || Span <- Spans], +report(Spans, Opts) -> + [observe_span(Span, Opts) || Span <- Spans], ok. - %% =================================================================== %% Private functions %% =================================================================== + +config_metric_type(Config) -> + type_to_module(proplists:get_value(type, Config, summary)). + +config_metric_name(Config) -> + proplists:get_value(name, Config, span). + +config_metric_buckets(Config) -> + proplists:get_value(buckets, Config, default). + +config_metric_labels(Config) -> + [normalize_label(Label) + || Label <- proplists:get_value(labels, Config, [])]. + +normalize_label(Name) when is_atom(Name) -> + NameStr = atom_to_binary(Name, utf8), + {NameStr, NameStr}; +normalize_label(Name) when is_binary(Name) -> + {Name, Name}; +normalize_label(Name) when is_list(Name) -> + {Name, list_to_binary(Name)}; +normalize_label({Label, Attribute}) when is_binary(Attribute) -> + {Label, Attribute}. + +compute_labels(Span, Attributes) -> + Map = Span#span.attributes, + [maps:get(Attribute, Map, "N/A") || Attribute <- Attributes]. + +observe_span(Span, {Type, MetricName, Attributes}) -> + Labels = [Span#span.name] ++ compute_labels(Span, Attributes), + Type:observe(MetricName, Labels, Span#span.duration). + +type_to_module(counter) -> + prometheus_counter; +type_to_module(gauge) -> + prometheus_gauge; +type_to_module(summary) -> + prometheus_summary; +type_to_module(histogram) -> + prometheus_histogram; +type_to_module(boolean) -> + prometheus_boolean; +type_to_module(Type) -> + Type. diff --git a/test/ct/oep_SUITE.erl b/test/ct/oep_SUITE.erl index 8b1e995..aa6e003 100644 --- a/test/ct/oep_SUITE.erl +++ b/test/ct/oep_SUITE.erl @@ -8,23 +8,46 @@ -include_lib("opencensus/include/opencensus.hrl"). all() -> - [prometheus_reporter]. + [prometheus_reporter_default, + prometheus_reporter_labels, + prometheus_reporter_histogram]. init_per_suite(Config) -> + ok = application:load(opencensus), Config. end_per_suite(_Config) -> ok. +init_per_testcase(prometheus_reporter_default, Config) -> + application:set_env(opencensus, reporter, {oc_prometheus_reporter, []}), + {ok, _} = application:ensure_all_started(opencensus_erlang_prometheus), + Config; +init_per_testcase(prometheus_reporter_labels, Config) -> + application:set_env(opencensus, reporter, + {oc_prometheus_reporter, [{name, span_with_labels}, + {labels, [op_name, {common_name, <<"cname">>}]}]}), + {ok, _} = application:ensure_all_started(opencensus_erlang_prometheus), + Config; +init_per_testcase(prometheus_reporter_histogram, Config) -> + application:set_env(opencensus, reporter, + {oc_prometheus_reporter, [{type, histogram}, + {name, span_histogram_seconds}, + {buckets, [0, 1, 2]}]}), + {ok, _} = application:ensure_all_started(opencensus_erlang_prometheus), + Config. + +end_per_testcase(_, _Config) -> + ok = application:stop(opencensus_erlang_prometheus), + ok = application:stop(opencensus), + ok = application:stop(prometheus), + ok. + %% =================================================================== %% Tests %% =================================================================== -prometheus_reporter(_Config) -> - application:set_env(opencensus, reporter, {oc_prometheus_reporter, []}), - ok = application:load(opencensus), - application:set_env(opencensus, reporter, {oc_prometheus_reporter, []}), - {ok, _} = application:ensure_all_started(opencensus_erlang_prometheus), +prometheus_reporter_default(_Config) -> SpanName1 = <<"span-1">>, Span1 = opencensus:start_span(SpanName1, opencensus:generate_trace_id(), undefined), @@ -36,8 +59,41 @@ prometheus_reporter(_Config) -> timer:sleep(1000), - ?assertMatch({1, _}, prometheus_summary:value("span", [SpanName1])), - ?assertMatch({1, _}, prometheus_summary:value("span", [ChildSpanName1])). + ?assertMatch({1, _}, prometheus_summary:value(span, [SpanName1])), + ?assertMatch({1, _}, prometheus_summary:value(span, [ChildSpanName1])). + +prometheus_reporter_labels(_Config) -> + + SpanName1 = <<"span-1">>, + Span1 = opencensus:start_span(SpanName1, opencensus:generate_trace_id(), #{<<"op_name">> => "test"}), + + ChildSpanName1 = <<"child-span-1">>, + ChildSpan1 = opencensus:start_span(ChildSpanName1, Span1, #{<<"cname">> => "github"}), + + opencensus:finish_span(ChildSpan1), + opencensus:finish_span(Span1), + + timer:sleep(1000), + + ?assertMatch({1, _}, prometheus_summary:value(span_with_labels, [SpanName1, "test", "N/A"])), + ?assertMatch({1, _}, prometheus_summary:value(span_with_labels, [ChildSpanName1, "N/A", "github"])). + +prometheus_reporter_histogram(_Config) -> + + SpanName1 = <<"span-1">>, + Span1 = opencensus:start_span(SpanName1, opencensus:generate_trace_id(), #{<<"op_name">> => "test"}), + + ChildSpanName1 = <<"child-span-1">>, + ChildSpan1 = opencensus:start_span(ChildSpanName1, Span1, #{<<"cname">> => "github"}), + timer:sleep(1500), + opencensus:finish_span(ChildSpan1), + timer:sleep(1000), + opencensus:finish_span(Span1), + + timer:sleep(1000), + + ?assertMatch({[0,0,0,1], _}, prometheus_histogram:value(span_histogram_seconds, [SpanName1])), + ?assertMatch({[0,0,1,0], _}, prometheus_histogram:value(span_histogram_seconds, [ChildSpanName1])). %% =================================================================== %% Private functions