Current section

5 Versions

Jump to

Compare versions

6 files changed
+159 additions
-94 deletions
  @@ -1,16 +1,78 @@
1 1
2 2
3 - # opencensus_erlang_prometheus #
3 + # Opencensus Prometheus integration for Erlang/BEAM #
4 4
5 5 Copyright (c) 2018 Ilya Khaprov <<i.khaprov@gmail.com>>.
6 6
7 - __Version:__ 0.0.1
7 + __Version:__ 0.3.0
8 8
9 9 [![Hex.pm][Hex badge]][Hex link]
10 10 [![Hex.pm Downloads][Hex downloads badge]][Hex link]
11 11 [![Build Status][Travis badge]][Travis link]
12 12 [![Coverage Status][Coveralls badge]][Coveralls link]
13 13
14 + > [Opencensus][Opencensus Erlang link]: Erlang stats collection and distributed tracing framework.
15 +
16 + > [Prometheus.io][Prometheus Erlang link]: monitoring system and time series database client in Erlang.
17 +
18 + ## Using
19 +
20 + Opencensus has trace and stats packages, trace package if for distributed tracing and
21 + stats package is for backend-agnostic metrics collection.
22 +
23 + This library implements a trace `reporter` for exporting spans duration as prometheus metrics and
24 + a stats `exporter` for exporting metrics collected using Opencensus.
25 +
26 + Example configuration:
27 +
28 + ```erlang
29 +
30 + {opencensus, [
31 + {reporter, {oc_reporter_sequential, [
32 + {oc_reporter_zipkin, [
33 + {url, "http://localhost:9411"},
34 + {service_name, "service_name"}
35 + ]},
36 + {oc_prometheus_reporter, [{type, histogram}, %% metric type
37 + {name, span_histogram_seconds}, %% metric name, note the time unit
38 + {buckets, [0, 1, 2]}]} %% histogram buckets with bounds in the time unit
39 + ]}},
40 + {sampler, {oc_sampler_probability, [
41 + {probability, 0.001} %% one in a thousand
42 + ]}}
43 + ]}
44 +
45 + ```
46 +
47 + Since Prometheus uses push model you don't need to set up Opencensus stats exporter as usual.
48 + Instead, this library provides `oc_stat_exporter_prometheus` which implements Prometheus collector interface.
49 +
50 + ```erlang
51 +
52 + prometheus_registry:register_collector(oc_stat_exporter_prometheus)
53 +
54 + ```
55 +
56 + ## Other Prometheus and Opencensus Links
57 +
58 + ## Opencensus
59 +
60 + - [Cowboy 2 Integration](https://github.com/deadtrickster/opencensus-cowboy)
61 + - [Google Cloud Trace](https://github.com/tsloughter/oc_google_reporter)
62 +
63 + ### Prometheus
64 +
65 + - [Cowboy1/2 Exporters and Cowboy2 instrumenter](https://hex.pm/packages/prometheus_cowboy)
66 + - [Ecto Instrumenter](https://hex.pm/packages/prometheus_ecto)
67 + - [Elixir client](https://github.com/deadtrickster/prometheus.ex)
68 + - [Elixir plugs Instrumenters and Exporter](https://hex.pm/packages/prometheus_plugs)
69 + - [Extatus - App to report metrics to Prometheus from Elixir GenServers](https://github.com/gmtprime/extatus)
70 + - [Fuse plugin](https://github.com/jlouis/fuse#fuse_stats_prometheus)
71 + - [Inets HTTPD Exporter](https://github.com/deadtrickster/prometheus_httpd)
72 + - [OS process info Collector](https://hex.pm/packages/prometheus_process_collector) (linux, freebsd, macos)
73 + - [Phoenix Instrumenter](https://hex.pm/packages/prometheus_phoenix)
74 + - [RabbitMQ Exporter](https://github.com/deadtrickster/prometheus_rabbitmq_exporter).
75 +
14 76 ## Contributing
15 77
16 78 Section order:
  @@ -43,12 +105,14 @@ MIT
43 105 [Travis link]: https://travis-ci.org/deadtrickster/opencensus_erlang_prometheus
44 106 [Coveralls badge]: https://coveralls.io/repos/github/deadtrickster/opencensus_erlang_prometheus/badge.svg?branch=master
45 107 [Coveralls link]: https://coveralls.io/github/deadtrickster/opencensus_erlang_prometheus?branch=master
108 + [Opencensus Erlang link]: https://github.com/census-instrumentation/opencensus-erlang
109 + [Prometheus Erlang link]: https://github.com/deadtrickster/prometheus.erl
46 110
47 111
48 112 ## Modules ##
49 113
50 114
51 115 <table width="100%" border="0" summary="list of modules">
52 - <tr><td><a href="https://github.com/deadtrickster/opencensus-erlang-prometheus/blob/master/doc/oc_prometheus_reporter.md" class="module">oc_prometheus_reporter</a></td></tr>
116 + <tr><td><a href="https://github.com/deadtrickster/opencensus-erlang-prometheus/blob/master/doc/oc_reporter_prometheus.md" class="module">oc_reporter_prometheus</a></td></tr>
53 117 <tr><td><a href="https://github.com/deadtrickster/opencensus-erlang-prometheus/blob/master/doc/oc_stat_exporter_prometheus.md" class="module">oc_stat_exporter_prometheus</a></td></tr></table>
  @@ -3,7 +3,7 @@
3 3 {<<"description">>,<<"opencensus_erlang_prometheus">>}.
4 4 {<<"elixir">>,<<"~> 1.4">>}.
5 5 {<<"files">>,
6 - [<<"src">>,<<"src/oc_prometheus_reporter.erl">>,
6 + [<<"src">>,<<"src/oc_reporter_prometheus.erl">>,
7 7 <<"src/oc_stat_exporter_prometheus.erl">>,
8 8 <<"src/opencensus_erlang_prometheus.app.src">>,<<"README.md">>,
9 9 <<"rebar.config">>]}.
  @@ -24,4 +24,4 @@
24 24 {<<"optional">>,false},
25 25 {<<"repository">>,<<"hexpm">>},
26 26 {<<"requirement">>,<<"~> 0.3">>}]]}.
27 - {<<"version">>,<<"0.2.0">>}.
27 + {<<"version">>,<<"0.3.0">>}.
  @@ -1,82 +0,0 @@
1 - -module(oc_prometheus_reporter).
2 -
3 - -include_lib("opencensus/include/opencensus.hrl").
4 -
5 - -behaviour(oc_reporter).
6 -
7 - -export([init/1,
8 - report/2]).
9 -
10 - %% ===================================================================
11 - %% API
12 - %% ===================================================================
13 -
14 - init(Config) ->
15 - Type = config_metric_type(Config),
16 - Name = config_metric_name(Config),
17 - Labels = config_metric_labels(Config),
18 - {LabelNames, Attributes} = lists:unzip(Labels),
19 - Type:declare([{name, Name},
20 - {labels, [name] ++ LabelNames},
21 - {buckets, config_metric_buckets(Config)},
22 - {help, "Opencensus span metric"}]),
23 - {Type, Name, Attributes}.
24 -
25 - report(Spans, Opts) ->
26 - [observe_span(Span, Opts) || Span <- Spans],
27 - ok.
28 -
29 - %% ===================================================================
30 - %% Private functions
31 - %% ===================================================================
32 -
33 - config_metric_type(Config) ->
34 - type_to_module(proplists:get_value(type, Config, summary)).
35 -
36 - config_metric_name(Config) ->
37 - proplists:get_value(name, Config, span).
38 -
39 - config_metric_buckets(Config) ->
40 - proplists:get_value(buckets, Config, default).
41 -
42 - config_metric_labels(Config) ->
43 - [normalize_label(Label)
44 - || Label <- proplists:get_value(labels, Config, [])].
45 -
46 - normalize_label(Name) when is_atom(Name) ->
47 - NameStr = atom_to_binary(Name, utf8),
48 - {NameStr, NameStr};
49 - normalize_label(Name) when is_binary(Name) ->
50 - {Name, Name};
51 - normalize_label(Name) when is_list(Name) ->
52 - {Name, list_to_binary(Name)};
53 - normalize_label({Label, Attribute}) when is_binary(Attribute) ->
54 - {Label, Attribute}.
55 -
56 - compute_labels(Span, Attributes) ->
57 - Map = Span#span.attributes,
58 - [maps:get(Attribute, Map, "N/A") || Attribute <- Attributes].
59 -
60 - observe_span(Span, {MetricType, MetricName, Attributes}) ->
61 - Labels = [Span#span.name] ++ compute_labels(Span, Attributes),
62 - observe_span(MetricType, MetricName, Labels, Span).
63 -
64 - observe_span(prometheus_summary, MetricName, Labels, Span) ->
65 - prometheus_summary:observe(MetricName, Labels, span_duration(Span));
66 - observe_span(prometheus_histogram, MetricName, Labels, Span) ->
67 - prometheus_histogram:observe(MetricName, Labels, span_duration(Span));
68 - observe_span(prometheus_counter, MetricName, Labels, _Span) ->
69 - prometheus_counter:inc(MetricName, Labels).
70 -
71 - type_to_module(counter) ->
72 - prometheus_counter;
73 - type_to_module(summary) ->
74 - prometheus_summary;
75 - type_to_module(histogram) ->
76 - prometheus_histogram;
77 - type_to_module(Type) ->
78 - Type.
79 -
80 - -spec span_duration(opencensus:span()) -> integer().
81 - span_duration(#span{start_time={StartTime,_}, end_time={EndTime,_}}) ->
82 - EndTime - StartTime.
  @@ -0,0 +1,82 @@
1 + -module(oc_reporter_prometheus).
2 +
3 + -include_lib("opencensus/include/opencensus.hrl").
4 +
5 + -behaviour(oc_reporter).
6 +
7 + -export([init/1,
8 + report/2]).
9 +
10 + %% ===================================================================
11 + %% API
12 + %% ===================================================================
13 +
14 + init(Config) ->
15 + Type = config_metric_type(Config),
16 + Name = config_metric_name(Config),
17 + Labels = config_metric_labels(Config),
18 + {LabelNames, Attributes} = lists:unzip(Labels),
19 + Type:declare([{name, Name},
20 + {labels, [name] ++ LabelNames},
21 + {buckets, config_metric_buckets(Config)},
22 + {help, "Opencensus span metric"}]),
23 + {Type, Name, Attributes}.
24 +
25 + report(Spans, Opts) ->
26 + [observe_span(Span, Opts) || Span <- Spans],
27 + ok.
28 +
29 + %% ===================================================================
30 + %% Private functions
31 + %% ===================================================================
32 +
33 + config_metric_type(Config) ->
34 + type_to_module(proplists:get_value(type, Config, summary)).
35 +
36 + config_metric_name(Config) ->
37 + proplists:get_value(name, Config, span).
38 +
39 + config_metric_buckets(Config) ->
40 + proplists:get_value(buckets, Config, default).
41 +
42 + config_metric_labels(Config) ->
43 + [normalize_label(Label)
44 + || Label <- proplists:get_value(labels, Config, [])].
45 +
46 + normalize_label(Name) when is_atom(Name) ->
47 + NameStr = atom_to_binary(Name, utf8),
48 + {NameStr, NameStr};
49 + normalize_label(Name) when is_binary(Name) ->
50 + {Name, Name};
51 + normalize_label(Name) when is_list(Name) ->
52 + {Name, list_to_binary(Name)};
53 + normalize_label({Label, Attribute}) when is_binary(Attribute) ->
54 + {Label, Attribute}.
55 +
56 + compute_labels(Span, Attributes) ->
57 + Map = Span#span.attributes,
58 + [maps:get(Attribute, Map, "N/A") || Attribute <- Attributes].
59 +
60 + observe_span(Span, {MetricType, MetricName, Attributes}) ->
61 + Labels = [Span#span.name] ++ compute_labels(Span, Attributes),
62 + observe_span(MetricType, MetricName, Labels, Span).
63 +
64 + observe_span(prometheus_summary, MetricName, Labels, Span) ->
65 + prometheus_summary:observe(MetricName, Labels, span_duration(Span));
66 + observe_span(prometheus_histogram, MetricName, Labels, Span) ->
67 + prometheus_histogram:observe(MetricName, Labels, span_duration(Span));
68 + observe_span(prometheus_counter, MetricName, Labels, _Span) ->
69 + prometheus_counter:inc(MetricName, Labels).
70 +
71 + type_to_module(counter) ->
72 + prometheus_counter;
73 + type_to_module(summary) ->
74 + prometheus_summary;
75 + type_to_module(histogram) ->
76 + prometheus_histogram;
77 + type_to_module(Type) ->
78 + Type.
79 +
80 + -spec span_duration(opencensus:span()) -> integer().
81 + span_duration(#span{start_time={StartTime, _}, end_time={EndTime, _}}) ->
82 + EndTime - StartTime.
  @@ -13,7 +13,8 @@ collect_mf(_Registry, Callback) ->
13 13 deregister_cleanup(_Registry) ->
14 14 ok.
15 15
16 - -spec view_data_to_mf(oc_stat_view:view_data()) -> prometheus_model:'MetricFamily'().
16 + -spec view_data_to_mf(oc_stat_view:view_data()) ->
17 + prometheus_model:'MetricFamily'().
17 18 view_data_to_mf(#{name := Name,
18 19 description := Description,
19 20 ctags := CTags,
  @@ -22,7 +23,7 @@ view_data_to_mf(#{name := Name,
22 23 rows := Rows}}) ->
23 24 FullRows = augment_rows_tags(Rows, Tags, CTags),
24 25 Metrics = rows_to_metrics(Type, FullRows),
25 - prometheus_model_helpers:create_mf(Name, Description, to_prometheus_type(Type), Metrics).
26 + prometheus_model_helpers:create_mf(Name, Description, to_prom_type(Type), Metrics).
26 27
27 28 augment_rows_tags(Rows, Tags, CTags) ->
28 29 [{maps:to_list(maps:merge(CTags, maps:from_list(lists:zip(Tags, TagsV)))), Value}
  @@ -48,11 +49,11 @@ sum_bucket_counters([], LAcc, _CAcc) ->
48 49 sum_bucket_counters([{Bucket, Counter} | Counters], LAcc, CAcc) ->
49 50 sum_bucket_counters(Counters, LAcc ++ [{Bucket, CAcc + Counter}], CAcc + Counter).
50 51
51 - to_prometheus_type(latest) ->
52 + to_prom_type(latest) ->
52 53 gauge;
53 - to_prometheus_type(count) ->
54 + to_prom_type(count) ->
54 55 counter;
55 - to_prometheus_type(sum) ->
56 + to_prom_type(sum) ->
56 57 summary;
57 - to_prometheus_type(distribution) ->
58 + to_prom_type(distribution) ->
58 59 histogram.
Loading more files…