1: -module(mongooseim_metrics_SUITE). 2: 3: -include_lib("exml/include/exml.hrl"). 4: -include_lib("proper/include/proper.hrl"). 5: -include_lib("eunit/include/eunit.hrl"). 6: -include("jlib.hrl"). 7: -include_lib("common_test/include/ct.hrl"). 8: 9: -compile([export_all, nowarn_export_all]). 10: 11: all() -> 12: [ 13: {group, ordinary_mode}, 14: {group, all_metrics_are_global} 15: ]. 16: 17: groups() -> 18: [ 19: {ordinary_mode, [], all_metrics_list()}, 20: {all_metrics_are_global, [], all_metrics_list()} 21: ]. 22: 23: all_metrics_list() -> 24: [ 25: no_skip_metric, 26: subscriptions_initialised, 27: tcp_connections_detected, 28: tcp_metric_varies_with_tcp_variations, 29: up_time_positive, 30: queued_messages_increase, 31: function_ensure_subscribed_metric_subscribes 32: ]. 33: 34: init_per_suite(C) -> 35: application:load(exometer_core), 36: application:set_env(exometer_core, mongooseim_report_interval, 1000), 37: {Port, Socket} = carbon_cache_server:start(), 38: Sup = spawn(fun() -> 39: mim_ct_sup:start_link(ejabberd_sup), 40: Hooks = {gen_hook, 41: {mongooseim_helper, start_link_loaded_hooks, []}, 42: permanent, 43: brutal_kill, 44: worker, 45: [gen_hook]}, 46: supervisor:start_child(ejabberd_sup, Hooks), 47: receive 48: stop -> 49: ok 50: end 51: end), 52: Reporters = get_reporters_cfg(Port), 53: application:set_env(exometer_core, report, Reporters), 54: PortServer = carbon_cache_server:wait_for_accepting(), 55: gen_tcp:controlling_process(Socket, PortServer), 56: {ok, _Apps} = application:ensure_all_started(exometer_core), 57: exometer:new([carbon, packets], spiral), 58: [{carbon_port, Port}, {test_sup, Sup}, {carbon_server, PortServer}, {carbon_socket, Socket} | C]. 59: 60: end_per_suite(C) -> 61: Sup = ?config(test_sup, C), 62: Sup ! stop, 63: CarbonServer = ?config(carbon_server, C), 64: erlang:exit(CarbonServer, kill), 65: CarbonSocket = ?config(carbon_socket, C), 66: gen_tcp:close(CarbonSocket), 67: application:stop(exometer_core), 68: C. 69: 70: init_per_group(Group, C) -> 71: mongoose_config:set_opts(opts(Group)), 72: mongoose_metrics:init(), 73: mongoose_metrics:init_mongooseim_metrics(), 74: C. 75: 76: end_per_group(_Group, _C) -> 77: mongoose_metrics:remove_host_type_metrics(<<"localhost">>), 78: mongoose_metrics:remove_host_type_metrics(global), 79: mongoose_config:erase_opts(). 80: 81: init_per_testcase(CN, C) when tcp_connections_detected =:= CN; 82: tcp_metric_varies_with_tcp_variations =:= CN -> 83: exometer:setopts([global, tcpPortsUsed], [{sample_interval, 50}]), 84: exometer:repair([global, tcpPortsUsed]), 85: C; 86: init_per_testcase(queued_messages_increase, C) -> 87: exometer:setopts([global, processQueueLengths], [{sample_interval, 50}]), 88: exometer:repair([global, processQueueLengths]), 89: PidsFun = fun() -> put('$internal_queue_len', 1), 90: receive die -> ok 91: end 92: end, 93: Pids = [spawn(PidsFun) || _ <- lists:seq(1,5)], 94: lists:foreach(fun(Pid) -> Pid ! undefined end, Pids), 95: [{pids, Pids} | C]; 96: init_per_testcase(_N, C) -> 97: C. 98: 99: end_per_testcase(queued_messages_increase, C) -> 100: [Pid ! die || Pid <- ?config(pids, C)], 101: C; 102: end_per_testcase(_N, C) -> 103: C. 104: 105: up_time_positive(_C) -> 106: {ok, [{value, X}]} = mongoose_metrics:get_metric_value(global, nodeUpTime), 107: ?assert(X > 0). 108: 109: function_ensure_subscribed_metric_subscribes(_C) -> 110: SubMetric = [happy_metric], 111: UnsubMetric = [sad_metric], 112: mongoose_metrics:ensure_subscribed_metric(global, SubMetric, spiral), 113: mongoose_metrics:ensure_metric(global, UnsubMetric, spiral), 114: Subs = exometer_report:list_subscriptions(exometer_report_graphite), 115: try 116: true = lists:keymember([global|SubMetric], 1, Subs), 117: false = lists:keymember([global|UnsubMetric], 1, Subs) 118: catch C:E:S -> 119: ct:pal("Subs ~p", [Subs]), 120: erlang:raise(C, E, S) 121: end. 122: 123: get_new_tcp_metric_value(OldValue) -> 124: Validator = fun(NewValue) -> OldValue =/= NewValue end, 125: {ok, {ok, [{value, X}]}} = async_helper:wait_until( 126: fun() -> mongoose_metrics:get_metric_value(global, tcpPortsUsed) end, 127: Validator, #{sleep_time => 30, time_left => 500} 128: ), 129: X. 130: 131: tcp_connections_detected(_C) -> 132: get_new_tcp_metric_value({ok, []}). 133: 134: tcp_metric_varies_with_tcp_variations(_C) -> 135: X = get_new_tcp_metric_value({ok, []}), 136: {ok, Socket} = gen_tcp:listen(0, []), 137: Y = get_new_tcp_metric_value({ok, [{value, X}]}), 138: ?assert(Y == X + 1), 139: gen_tcp:close(Socket), 140: X = get_new_tcp_metric_value({ok, [{value, Y}]}). 141: 142: queued_messages_increase(_C) -> 143: Fun = fun(Value) -> 144: case Value of 145: [{fsm, 5}, {regular, 5}, {total, 10}] -> true; 146: 147: %% Sometimes there is an additional unprocessed message 148: %% in the standard I/O ('user') process 149: [{fsm, 5}, {regular, 6}, {total, 11}] -> true; 150: _ -> false 151: end 152: end, 153: async_helper:wait_until( 154: fun() -> 155: {ok, L} = mongoose_metrics:get_metric_value(global, processQueueLengths), 156: lists:sort(L) 157: end, Fun). 158: 159: no_skip_metric(_C) -> 160: ok = mongoose_metrics:create_generic_hook_metric(<<"localhost">>, sm_register_connection_hook), 161: undefined = exometer:info([<<"localhost">>, sm_register_connection_hook]). 162: 163: subscriptions_initialised(_C) -> 164: true = wait_for_update(exometer:get_value([carbon, packets], count), 60). 165: 166: wait_for_update({ok, [{count,X}]}, 0) -> 167: X > 0; 168: wait_for_update({ok, [{count,X}]}, _N) when X > 0 -> 169: true; 170: wait_for_update({ok, [{count,0}]}, N) -> 171: timer:sleep(1000), 172: wait_for_update(exometer:get_value([carbon, packets], count), N-1). 173: 174: opts(Group) -> 175: #{hosts => [<<"localhost">>], 176: host_types => [], 177: all_metrics_are_global => Group =:= all_metrics_are_global}. 178: 179: get_reporters_cfg(Port) -> 180: [{reporters, [ 181: {exometer_report_graphite, [ 182: {prefix, "mongooseim"}, 183: {connect_timeout, 10000}, 184: {host, "127.0.0.1"}, 185: {port, Port}, 186: {api_key, ""} 187: ]} 188: ]}].