diff --git a/doc/operation-and-maintenance/MongooseIM-metrics.md b/doc/operation-and-maintenance/MongooseIM-metrics.md index 24ca91c2b05..751ea86d0c7 100644 --- a/doc/operation-and-maintenance/MongooseIM-metrics.md +++ b/doc/operation-and-maintenance/MongooseIM-metrics.md @@ -27,20 +27,20 @@ All metrics are divided into the following groups: === "Prometheus"

`counter`

- + A monotonically increasing metric type. It is used for events like the number of stanzas processed by the system. - + **Example:** ``` # TYPE c2s_element_in_message_count counter # HELP c2s_element_in_message_count Event: c2s_element_in, Metric: message_count c2s_element_in_message_count{host_type="localhost"} 0 ``` - +

`gauge`

- + A metric that represents a current value in the system. - + **Example:** ``` # TYPE mnesia_info_running_db_nodes gauge @@ -49,9 +49,9 @@ All metrics are divided into the following groups: ```

`histogram`

- + A histogram collects values and groups them in buckets. - + **Example:** ``` # TYPE c2s_xmpp_element_size_in_byte_size histogram @@ -61,35 +61,35 @@ All metrics are divided into the following groups: c2s_xmpp_element_size_in_byte_size_bucket{le="1073741824"} 0 c2s_xmpp_element_size_in_byte_size_bucket{le="+Inf"} 0 ``` - + === "Exometer" - +

`spiral`

- + This kind of metric provides 2 values: `total` event count (e.g. stanzas processed) and a value in 60s window (`one` value). Dividing `one` value by 60 provides an average per-second value over last minute. - + **Example:** `[{total, 1000}, {one, 20}]` - +

`counter`

- + A simple monotonically increasing value. It consists of two properties: - + **Example:** `[{value, 12}, {ms_since_reset, 91761}]` - +

`gauge`

- + It is similar to a `counter` type but can be set to any value. - + * `value` * `ms_since_reset` - Time in milliseconds elapsed from the last metric update. - + **Example:** `[{value, 12}, {ms_since_reset, 91761}]`

`histogram`

- + A histogram collects values over a sliding window of 60s and exposes the following stats: - + * `n` - A number of samples. * `mean` - An arithmetic mean. * `min` @@ -228,26 +228,26 @@ Since Exometer doesn't support labels, the host types and tags are part of the m | Name | Type | Description (when it gets incremented) | | ---- | ---- | -------------------------------------- | | `wpool_rdbms_stats_workers` | gauge | Number of workers in the pool | - | `wpool_rdbms_stats_recv_oct` | counter | Number of bytes received | - | `wpool_rdbms_stats_recv_cnt` | counter | Number of packets received | - | `wpool_rdbms_stats_recv_max` | gauge | Size of the largest packet, in bytes | - | `wpool_rdbms_stats_send_oct` | counter | Number of bytes sent | - | `wpool_rdbms_stats_send_max` | gauge | Size of the largest packet | - | `wpool_rdbms_stats_send_cnt` | counter | Number of packets sent | - | `wpool_rdbms_stats_send_pend` | counter | Number of bytes waiting to be sent | + | `wpool_rdbms_stats_recv_oct` | gauge | Number of bytes received | + | `wpool_rdbms_stats_recv_cnt` | gauge | Number of packets received | + | `wpool_rdbms_stats_recv_max` | gauge | Size of the largest packet, in bytes | + | `wpool_rdbms_stats_send_oct` | gauge | Number of bytes sent | + | `wpool_rdbms_stats_send_max` | gauge | Size of the largest packet | + | `wpool_rdbms_stats_send_cnt` | gauge | Number of packets sent | + | `wpool_rdbms_stats_send_pend` | gauge | Number of bytes waiting to be sent | === "Exometer" | Name | Type | Description (when it gets incremented) | |--------------------------------------------------------------|---------|----------------------------------------| - | `[HostType, wpool_rdbms_stats, PoolTag, workers]` | counter | Number of workers in the pool | - | `[HostType, wpool_rdbms_stats, PoolTag, recv_oct]` | spiral | Number of bytes received | - | `[HostType, wpool_rdbms_stats, PoolTag, recv_cnt]` | spiral | Number of packets received | - | `[HostType, wpool_rdbms_stats, PoolTag, recv_max]` | gauge | Size of the largest packet, in bytes | - | `[HostType, wpool_rdbms_stats, PoolTag, send_oct]` | spiral | Number of bytes sent | - | `[HostType, wpool_rdbms_stats, PoolTag, send_max]` | gauge | Size of the largest packet | - | `[HostType, wpool_rdbms_stats, PoolTag, send_cnt]` | spiral | Number of packets sent | - | `[HostType, wpool_rdbms_stats, PoolTag, send_pend]` | spiral | Number of bytes waiting to be sent | + | `[HostType, wpool_rdbms_stats, PoolTag, workers]` | gauge | Number of workers in the pool | + | `[HostType, wpool_rdbms_stats, PoolTag, recv_oct]` | gauge | Number of bytes received | + | `[HostType, wpool_rdbms_stats, PoolTag, recv_cnt]` | gauge | Number of packets received | + | `[HostType, wpool_rdbms_stats, PoolTag, recv_max]` | gauge | Size of the largest packet, in bytes | + | `[HostType, wpool_rdbms_stats, PoolTag, send_oct]` | gauge | Number of bytes sent | + | `[HostType, wpool_rdbms_stats, PoolTag, send_max]` | gauge | Size of the largest packet | + | `[HostType, wpool_rdbms_stats, PoolTag, send_cnt]` | gauge | Number of packets sent | + | `[HostType, wpool_rdbms_stats, PoolTag, send_pend]` | gauge | Number of bytes waiting to be sent | When using a Rabbit worker pool, metrics defined in [mod_event_pusher_rabbit](../modules/mod_event_pusher_rabbit.md) are available. diff --git a/src/instrument/mongoose_instrument.erl b/src/instrument/mongoose_instrument.erl index c1b717c0a16..ad9fd9e1c12 100644 --- a/src/instrument/mongoose_instrument.erl +++ b/src/instrument/mongoose_instrument.erl @@ -46,6 +46,7 @@ -type handler_key() :: atom(). % key in the `instrumentation' section of the config file -type handler_fun() :: fun((event_name(), labels(), config(), measurements()) -> any()). -type handlers() :: {[handler_fun()], config()}. +-type handler_map() :: #{labels() => handlers()}. -type execution_time() :: integer(). -type measure_fun(Result) :: fun((execution_time(), Result) -> measurements()). -type handler_module_opts() :: #{atom() => any()}. @@ -274,16 +275,45 @@ set_up_and_register_event(EventName, Labels, Config, Events) -> {ExistingLabels, _, _} = maps:next(maps:iterator(HandlerMap)), case label_keys(ExistingLabels) of LabelKeys -> - Handlers = do_set_up(EventName, Labels, Config), - Events#{EventName := HandlerMap#{Labels => Handlers}}; + handle_metrics_config(EventName, Labels, Config, HandlerMap, Events); ExistingKeys -> {error, #{what => inconsistent_labels, event_name => EventName, labels => Labels, existing_label_keys => ExistingKeys}} end; #{} -> + handle_metrics_config(EventName, Labels, Config, new, Events) + end. + +-spec handle_metrics_config(event_name(), labels(), config(), handler_map() | new, event_map()) -> + event_map() | {error, map()}. +handle_metrics_config(EventName, Labels, Config, HandlerMap, Events) -> + case filter_improper_probe_metrics(Config) of + {ok, _} -> Handlers = do_set_up(EventName, Labels, Config), - Events#{EventName => #{Labels => Handlers}} + case HandlerMap of + new -> + Events#{EventName => #{Labels => Handlers}}; + _ -> + Events#{EventName := HandlerMap#{Labels => Handlers}} + end; + {error, FilteredMetrics} -> + {error, #{what => non_gauge_metrics_in_probe, + event_name => EventName, labels => Labels, + improper_metrics => FilteredMetrics}} + end. + +-spec filter_improper_probe_metrics(config()) -> {ok, #{}} | {error, metrics()}. +filter_improper_probe_metrics(Config) -> + case Config of + #{probe := _, metrics := Metrics} -> + FilteredMetrics = maps:filter(fun(_, V) -> V =/= gauge end, Metrics), + case map_size(FilteredMetrics) of + 0 -> {ok, FilteredMetrics}; + _ -> {error, FilteredMetrics} + end; + _ -> + {ok, #{}} end. -spec do_set_up(event_name(), labels(), config()) -> handlers(). diff --git a/src/wpool/mongoose_wpool_rdbms.erl b/src/wpool/mongoose_wpool_rdbms.erl index b6e7d8f98a1..12ee2754670 100644 --- a/src/wpool/mongoose_wpool_rdbms.erl +++ b/src/wpool/mongoose_wpool_rdbms.erl @@ -45,10 +45,10 @@ instrumentation(global, Tag) -> % Services use global pools. Since the same number of labels for a metric is expected, for an % event, global pool has to emit an event under a different name. [{wpool_global_rdbms_stats, #{pool_tag => Tag}, - #{probe => #{module => ?MODULE}, metrics => rdbms_data_stats_measurement_types()}}]; + #{probe => #{module => ?MODULE}, metrics => gauges([workers | inet_stats()])}}]; instrumentation(HostType, Tag) -> [{wpool_rdbms_stats, #{host_type => HostType, pool_tag => Tag}, - #{probe => #{module => ?MODULE}, metrics => rdbms_data_stats_measurement_types()}}]. + #{probe => #{module => ?MODULE}, metrics => gauges([workers | inet_stats()])}}]. -spec probe(mongoose_instrument:event_name(), mongoose_instrument:labels()) -> mongoose_instrument:measurements(). @@ -166,12 +166,6 @@ empty_inet_stats_measurements() -> send_cnt => 0, send_pend => 0}. -rdbms_data_stats_measurement_types() -> - #{workers => counter, - recv_oct => spiral, - recv_cnt => spiral, - recv_max => gauge, - send_oct => spiral, - send_max => gauge, - send_cnt => spiral, - send_pend => spiral}. +-spec gauges([mongoose_instrument:metric_name()]) -> mongoose_instrument:metrics(). +gauges(Keys) -> + maps:from_keys(Keys, gauge). diff --git a/test/mongoose_instrument_SUITE.erl b/test/mongoose_instrument_SUITE.erl index feb0cccc953..7620e1580b0 100644 --- a/test/mongoose_instrument_SUITE.erl +++ b/test/mongoose_instrument_SUITE.erl @@ -37,6 +37,7 @@ api_test_cases() -> set_up_and_span_with_error, span_fails_when_not_set_up, set_up_probe, + set_up_probe_with_incorrect_metric_type, set_up_failing_probe, set_up_and_tear_down_probe, unexpected_events, @@ -224,6 +225,19 @@ set_up_probe(Config) -> fun(L) -> length(L) > 1 end), ?assertEqual([ExpectedEvent, ExpectedEvent], History2). +set_up_probe_with_incorrect_metric_type(Config) -> + Event = ?config(event, Config), + Cfg = #{metrics => #{test_metric => gauge}, + probe => #{module => ?MODULE, interval => 1}}, + Cfg1 = #{metrics => ImproperMetrics = #{test_metric => spiral}, + probe => #{module => ?MODULE, interval => 1}}, + Specs = [{Event, #{key => value1}, Cfg}, + {Event, #{key => value2}, Cfg1}], + ?assertError(#{what := non_gauge_metrics_in_probe, improper_metrics := ImproperMetrics}, + mongoose_instrument:set_up(Event, ?LABELS, Cfg1)), + ?assertError(#{what := non_gauge_metrics_in_probe, improper_metrics := ImproperMetrics}, + mongoose_instrument:set_up(Specs)). + set_up_failing_probe(Config) -> Event = ?config(event, Config), Labels = ?LABELS,