1: -module(mongoose_instrument_metrics_SUITE). 2: -compile([export_all, nowarn_export_all]). 3: 4: -include_lib("eunit/include/eunit.hrl"). 5: -include_lib("common_test/include/ct.hrl"). 6: 7: -define(LABELS, #{host_type => <<"localhost">>}). 8: -define(LABELS2, #{host_type => <<"test type">>}). 9: -define(HOST_TYPE, <<"localhost">>). 10: -define(HOST_TYPE2, <<"test type">>). 11: 12: %% Setup and teardown 13: 14: all() -> 15: [{group, prometheus}, 16: {group, exometer}, 17: {group, prometheus_and_exometer} 18: ]. 19: 20: groups() -> 21: [{prometheus, [parallel], [prometheus_skips_non_metric_event, 22: prometheus_counter_is_created_but_not_initialized, 23: prometheus_counter_is_updated_separately_for_different_labels, 24: prometheus_histogram_is_created_but_not_initialized, 25: prometheus_histogram_is_updated_separately_for_different_labels, 26: multiple_prometheus_metrics_are_updated]}, 27: {exometer, [parallel], [exometer_skips_non_metric_event, 28: exometer_spiral_is_created_and_initialized, 29: exometer_spiral_is_updated_separately_for_different_labels, 30: exometer_histogram_is_created_and_initialized, 31: exometer_histogram_is_updated_separately_for_different_labels, 32: multiple_exometer_metrics_are_updated]}, 33: {prometheus_and_exometer, [parallel], [prometheus_and_exometer_metrics_are_updated]} 34: ]. 35: 36: init_per_suite(Config) -> 37: Config1 = async_helper:start(Config, mongoose_instrument, start_link, []), 38: mongoose_instrument:persist(), 39: Config1. 40: 41: end_per_suite(Config) -> 42: async_helper:stop_all(Config). 43: 44: init_per_group(Group, Config) -> 45: [application:ensure_all_started(App) || App <- apps(Group)], 46: mongoose_config:set_opts(#{instrumentation => opts(Group)}), 47: Config. 48: 49: end_per_group(_Group, _Config) -> 50: mongoose_config:erase_opts(). 51: 52: init_per_testcase(Case, Config) -> 53: [{event, concat(Case, event)} | Config]. 54: 55: end_per_testcase(_Case, _Config) -> 56: ok. 57: 58: apps(prometheus) -> [prometheus]; 59: apps(exometer) -> [exometer_core]; 60: apps(prometheus_and_exometer) -> apps(prometheus) ++ apps(exometer). 61: 62: opts(prometheus) -> #{prometheus => #{}}; 63: opts(exometer) -> #{exometer => #{}}; 64: opts(prometheus_and_exometer) -> maps:merge(opts(prometheus), opts(exometer)). 65: 66: %% Test cases 67: 68: prometheus_skips_non_metric_event(Config) -> 69: Event = ?config(event, Config), 70: false = mongoose_instrument_prometheus:set_up(Event, ?LABELS, #{}), 71: false = mongoose_instrument_prometheus:set_up(Event, ?LABELS, #{loglevel => error}). 72: 73: prometheus_counter_is_created_but_not_initialized(Config) -> 74: Event = ?config(event, Config), 75: Metric = concat(Event, count), 76: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral}}), 77: ?assertEqual(undefined, prometheus_counter:value(Metric, [?HOST_TYPE])). 78: 79: prometheus_counter_is_updated_separately_for_different_labels(Config) -> 80: Event = ?config(event, Config), 81: Metric = concat(Event, count), 82: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral}}), 83: ok = mongoose_instrument:set_up(Event, ?LABELS2, #{metrics => #{count => spiral}}), 84: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 1}), 85: ok = mongoose_instrument:execute(Event, ?LABELS2, #{count => 2}), 86: ?assertEqual(1, prometheus_counter:value(Metric, [?HOST_TYPE])), 87: ?assertEqual(2, prometheus_counter:value(Metric, [?HOST_TYPE2])). 88: 89: prometheus_histogram_is_created_but_not_initialized(Config) -> 90: Event = ?config(event, Config), 91: Metric = concat(Event, time), 92: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{time => histogram}}), 93: ?assertEqual(undefined, prometheus_histogram:value(Metric, [?HOST_TYPE])). 94: 95: prometheus_histogram_is_updated_separately_for_different_labels(Config) -> 96: Event = ?config(event, Config), 97: Metric = concat(Event, time), 98: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{time => histogram}}), 99: ok = mongoose_instrument:set_up(Event, ?LABELS2, #{metrics => #{time => histogram}}), 100: ok = mongoose_instrument:execute(Event, ?LABELS, #{time => 1}), 101: ok = mongoose_instrument:execute(Event, ?LABELS2, #{time => 2}), 102: ?assertMatch({[1, 0|_], 1}, prometheus_histogram:value(Metric, [?HOST_TYPE])), 103: ?assertMatch({[0, 1|_], 2}, prometheus_histogram:value(Metric, [?HOST_TYPE2])). 104: 105: multiple_prometheus_metrics_are_updated(Config) -> 106: Event = ?config(event, Config), 107: Counter = concat(Event, count), 108: Histogram = concat(Event, time), 109: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral, 110: time => histogram}}), 111: %% Update both metrics 112: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 1, time => 2}), 113: ?assertEqual(1, prometheus_counter:value(Counter, [?HOST_TYPE])), 114: HistogramValue = prometheus_histogram:value(Histogram, [?HOST_TYPE]), 115: ?assertMatch({[0, 1|_], 2}, HistogramValue), 116: 117: %% Update only one metric 118: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 2}), 119: ?assertEqual(3, prometheus_counter:value(Counter, [?HOST_TYPE])), 120: ?assertEqual(HistogramValue, prometheus_histogram:value(Histogram, [?HOST_TYPE])), 121: 122: %% No update 123: ok = mongoose_instrument:execute(Event, ?LABELS, #{something => irrelevant}), 124: ?assertEqual(3, prometheus_counter:value(Counter, [?HOST_TYPE])), 125: ?assertEqual(HistogramValue, prometheus_histogram:value(Histogram, [?HOST_TYPE])). 126: 127: exometer_skips_non_metric_event(Config) -> 128: Event = ?config(event, Config), 129: false = mongoose_instrument_exometer:set_up(Event, ?LABELS, #{}), 130: false = mongoose_instrument_exometer:set_up(Event, ?LABELS, #{loglevel => error}). 131: 132: exometer_spiral_is_created_and_initialized(Config) -> 133: Event = ?config(event, Config), 134: Metric = [?HOST_TYPE, Event, count], 135: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral}}), 136: ?assertEqual({ok, [{count, 0}]}, exometer:get_value(Metric, count)). 137: 138: exometer_spiral_is_updated_separately_for_different_labels(Config) -> 139: Event = ?config(event, Config), 140: Metric1 = [?HOST_TYPE, Event, count], 141: Metric2 = [<<"test_type">>, Event, count], 142: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral}}), 143: ok = mongoose_instrument:set_up(Event, ?LABELS2, #{metrics => #{count => spiral}}), 144: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 1}), 145: ok = mongoose_instrument:execute(Event, ?LABELS2, #{count => 2}), 146: ?assertEqual({ok, [{count, 1}]}, exometer:get_value(Metric1, count)), 147: ?assertEqual({ok, [{count, 2}]}, exometer:get_value(Metric2, count)). 148: 149: exometer_histogram_is_created_and_initialized(Config) -> 150: Event = ?config(event, Config), 151: Metric = [?HOST_TYPE, Event, time], 152: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{time => histogram}}), 153: ?assertEqual({ok, [{mean, 0}]}, exometer:get_value(Metric, mean)). 154: 155: exometer_histogram_is_updated_separately_for_different_labels(Config) -> 156: Event = ?config(event, Config), 157: Metric1 = [?HOST_TYPE, Event, time], 158: Metric2 = [<<"test_type">>, Event, time], 159: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{time => histogram}}), 160: ok = mongoose_instrument:set_up(Event, ?LABELS2, #{metrics => #{time => histogram}}), 161: ok = mongoose_instrument:execute(Event, ?LABELS, #{time => 1}), 162: ok = mongoose_instrument:execute(Event, ?LABELS2, #{time => 3}), 163: ?assertEqual({ok, [{mean, 1}]}, exometer:get_value(Metric1, mean)), 164: ?assertEqual({ok, [{mean, 3}]}, exometer:get_value(Metric2, mean)). 165: 166: multiple_exometer_metrics_are_updated(Config) -> 167: Event = ?config(event, Config), 168: Counter = [?HOST_TYPE, Event, count], 169: Histogram = [?HOST_TYPE, Event, time], 170: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral, 171: time => histogram}}), 172: %% Update both metrics 173: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 1, time => 2}), 174: ?assertEqual({ok, [{count, 1}]}, exometer:get_value(Counter, count)), 175: ?assertEqual({ok, [{mean, 2}]}, exometer:get_value(Histogram, mean)), 176: 177: %% Update only one metric 178: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 5}), 179: ?assertEqual({ok, [{count, 6}]}, exometer:get_value(Counter, count)), 180: ?assertEqual({ok, [{mean, 2}]}, exometer:get_value(Histogram, mean)), 181: 182: %% No update 183: ok = mongoose_instrument:execute(Event, ?LABELS, #{something => irrelevant}), 184: ?assertEqual({ok, [{count, 6}]}, exometer:get_value(Counter, count)), 185: ?assertEqual({ok, [{mean, 2}]}, exometer:get_value(Histogram, mean)). 186: 187: prometheus_and_exometer_metrics_are_updated(Config) -> 188: Event = ?config(event, Config), 189: ok = mongoose_instrument:set_up(Event, ?LABELS, #{metrics => #{count => spiral, 190: time => histogram}}), 191: ok = mongoose_instrument:execute(Event, ?LABELS, #{count => 1, time => 2}), 192: ?assertEqual({ok, [{count, 1}]}, exometer:get_value([?HOST_TYPE, Event, count], count)), 193: ?assertEqual({ok, [{mean, 2}]}, exometer:get_value([?HOST_TYPE, Event, time], mean)), 194: ?assertEqual(1, prometheus_counter:value(concat(Event, count), [?HOST_TYPE])), 195: ?assertMatch({[0, 1|_], 2}, prometheus_histogram:value(concat(Event, time), [?HOST_TYPE])). 196: 197: %% Helpers 198: 199: concat(A1, A2) -> 200: list_to_atom(atom_to_list(A1) ++ "_" ++ atom_to_list(A2)).