| 1 | -module(beam_stats_consumer_statsd_SUITE). |
| 2 | |
| 3 | -include_lib("beam_stats/include/beam_stats.hrl"). |
| 4 | -include_lib("beam_stats/include/beam_stats_ets_table.hrl"). |
| 5 | -include_lib("beam_stats/include/beam_stats_process.hrl"). |
| 6 | -include_lib("beam_stats/include/beam_stats_process_ancestry.hrl"). |
| 7 | -include_lib("beam_stats/include/beam_stats_processes.hrl"). |
| 8 | |
| 9 | -export( |
| 10 | [ all/0 |
| 11 | , groups/0 |
| 12 | ]). |
| 13 | |
| 14 | %% Test cases |
| 15 | -export( |
| 16 | [ t_send/1 |
| 17 | ]). |
| 18 | |
| 19 | -define(GROUP, beam_stats_consumer_statsd). |
| 20 | |
| 21 | %% ============================================================================ |
| 22 | %% Common Test callbacks |
| 23 | %% ============================================================================ |
| 24 | |
| 25 | all() -> |
| 26 | [{group, ?GROUP}]. |
| 27 | |
| 28 | groups() -> |
| 29 | Tests = |
| 30 | [ t_send |
| 31 | ], |
| 32 | Properties = [], |
| 33 | [{?GROUP, Properties, Tests}]. |
| 34 | |
| 35 | %% ============================================================================ |
| 36 | %% Test cases |
| 37 | %% ============================================================================ |
| 38 | |
| 39 | t_send(_Cfg) -> |
| 40 | Pid0 = list_to_pid("<0.0.0>"), |
| 41 | Pid1 = list_to_pid("<0.1.0>"), |
| 42 | Pid2 = list_to_pid("<0.2.0>"), |
| 43 | Pid3 = list_to_pid("<0.3.0>"), |
| 44 | Process1 = |
| 45 | #beam_stats_process |
| 46 | { pid = Pid1 |
| 47 | , registered_name = {some, reg_name_foo} |
| 48 | , ancestry = |
| 49 | #beam_stats_process_ancestry |
| 50 | { raw_initial_call = {foo_mod, foo_fun, 2} |
| 51 | , otp_initial_call = none |
| 52 | , otp_ancestors = none |
| 53 | } |
| 54 | , status = running |
| 55 | , memory = 15 |
| 56 | , total_heap_size = 25 |
| 57 | , stack_size = 10 |
| 58 | , message_queue_len = 0 |
| 59 | }, |
| 60 | Process2 = |
| 61 | #beam_stats_process |
| 62 | { pid = Pid2 |
| 63 | , registered_name = none |
| 64 | , ancestry = |
| 65 | #beam_stats_process_ancestry |
| 66 | { raw_initial_call = {bar_mod, bar_fun, 1} |
| 67 | , otp_initial_call = none |
| 68 | , otp_ancestors = none |
| 69 | } |
| 70 | , status = running |
| 71 | , memory = 25 |
| 72 | , total_heap_size = 35 |
| 73 | , stack_size = 40 |
| 74 | , message_queue_len = 5 |
| 75 | }, |
| 76 | Process3 = |
| 77 | #beam_stats_process |
| 78 | { pid = Pid3 |
| 79 | , registered_name = none |
| 80 | , ancestry = |
| 81 | #beam_stats_process_ancestry |
| 82 | { raw_initial_call = {baz_mod, baz_fun, 3} |
| 83 | , otp_initial_call = {some, {baz_otp_mod, baz_otp_fun, 2}} |
| 84 | , otp_ancestors = {some, [Pid0, Pid1]} |
| 85 | } |
| 86 | , status = running |
| 87 | , memory = 25 |
| 88 | , total_heap_size = 35 |
| 89 | , stack_size = 40 |
| 90 | , message_queue_len = 1 |
| 91 | }, |
| 92 | Processes = |
| 93 | #beam_stats_processes |
| 94 | { individual_stats = |
| 95 | [ Process1 |
| 96 | , Process2 |
| 97 | , Process3 |
| 98 | ] |
| 99 | , count_all = 3 |
| 100 | , count_exiting = 0 |
| 101 | , count_garbage_collecting = 0 |
| 102 | , count_registered = 1 |
| 103 | , count_runnable = 0 |
| 104 | , count_running = 3 |
| 105 | , count_suspended = 0 |
| 106 | , count_waiting = 0 |
| 107 | }, |
| 108 | ETSTableStatsFoo = |
| 109 | #beam_stats_ets_table |
| 110 | { id = foo |
| 111 | , name = foo |
| 112 | , size = 5 |
| 113 | , memory = 25 |
| 114 | }, |
| 115 | ETSTableStatsBar = |
| 116 | #beam_stats_ets_table |
| 117 | { id = 37 |
| 118 | , name = bar |
| 119 | , size = 8 |
| 120 | , memory = 38 |
| 121 | }, |
| 122 | % TODO: Indent #beam_stats as #beam_stats_ets_table |
| 123 | BEAMStats = #beam_stats |
| 124 | { timestamp = {1, 2, 3} |
| 125 | , node_id = 'node_foo@host_bar' |
| 126 | , memory = [{mem_type_foo, 1}, {mem_type_bar, 2}, {mem_type_baz, 3}] |
| 127 | , io_bytes_in = 3 |
| 128 | , io_bytes_out = 7 |
| 129 | , context_switches = 5 |
| 130 | , reductions = 9 |
| 131 | , run_queue = 17 |
| 132 | , ets = [ETSTableStatsFoo, ETSTableStatsBar] |
| 133 | , processes = Processes |
| 134 | }, |
| 135 | ServerPort = 8125, |
| 136 | {ok, ServerSocket} = gen_udp:open(ServerPort, [binary, {active, false}]), |
| 137 | BEAMStatsQ = queue:in(BEAMStats, queue:new()), |
| 138 | Options = [{dst_port, ServerPort}], |
| 139 | {_, State1} = beam_stats_consumer_statsd:init(Options), |
| 140 | State2 = beam_stats_consumer_statsd:consume(BEAMStatsQ, State1), |
| 141 | {} = beam_stats_consumer_statsd:terminate(State2), |
| 142 | ResultOfReceive1 = gen_udp:recv(ServerSocket, 0), |
| 143 | ResultOfReceive2 = gen_udp:recv(ServerSocket, 0), |
| 144 | ResultOfReceive3 = gen_udp:recv(ServerSocket, 0), |
| 145 | ResultOfReceive4 = gen_udp:recv(ServerSocket, 0), |
| 146 | ok = gen_udp:close(ServerSocket), |
| 147 | {ok, {_, _, PacketReceived1}} = ResultOfReceive1, |
| 148 | {ok, {_, _, PacketReceived2}} = ResultOfReceive2, |
| 149 | {ok, {_, _, PacketReceived3}} = ResultOfReceive3, |
| 150 | {ok, {_, _, PacketReceived4}} = ResultOfReceive4, |
| 151 | ct:log("PacketReceived1: ~n~s~n", [PacketReceived1]), |
| 152 | ct:log("PacketReceived2: ~n~s~n", [PacketReceived2]), |
| 153 | ct:log("PacketReceived3: ~n~s~n", [PacketReceived3]), |
| 154 | ct:log("PacketReceived4: ~n~s~n", [PacketReceived4]), |
| 155 | PacketsCombined = |
| 156 | << PacketReceived1/binary |
| 157 | , PacketReceived2/binary |
| 158 | , PacketReceived3/binary |
| 159 | , PacketReceived4/binary |
| 160 | >>, |
| 161 | ct:log("PacketsCombined: ~n~s~n", [PacketsCombined]), |
| 162 | MsgsExpected = |
| 163 | [ <<"beam_stats.node_foo_host_bar.io.bytes_in:3|g">> |
| 164 | , <<"beam_stats.node_foo_host_bar.io.bytes_out:7|g">> |
| 165 | , <<"beam_stats.node_foo_host_bar.context_switches:5|g">> |
| 166 | , <<"beam_stats.node_foo_host_bar.reductions:9|g">> |
| 167 | , <<"beam_stats.node_foo_host_bar.run_queue:17|g">> |
| 168 | , <<"beam_stats.node_foo_host_bar.memory.mem_type_foo:1|g">> |
| 169 | , <<"beam_stats.node_foo_host_bar.memory.mem_type_bar:2|g">> |
| 170 | , <<"beam_stats.node_foo_host_bar.memory.mem_type_baz:3|g">> |
| 171 | , <<"beam_stats.node_foo_host_bar.ets_table.size.foo.foo:5|g">> |
| 172 | , <<"beam_stats.node_foo_host_bar.ets_table.memory.foo.foo:25|g">> |
| 173 | , <<"beam_stats.node_foo_host_bar.ets_table.size.bar.37:8|g">> |
| 174 | , <<"beam_stats.node_foo_host_bar.ets_table.memory.bar.37:38|g">> |
| 175 | |
| 176 | % Processes totals |
| 177 | , <<"beam_stats.node_foo_host_bar.processes_count_all:3|g">> |
| 178 | , <<"beam_stats.node_foo_host_bar.processes_count_exiting:0|g">> |
| 179 | , <<"beam_stats.node_foo_host_bar.processes_count_garbage_collecting:0|g">> |
| 180 | , <<"beam_stats.node_foo_host_bar.processes_count_registered:1|g">> |
| 181 | , <<"beam_stats.node_foo_host_bar.processes_count_runnable:0|g">> |
| 182 | , <<"beam_stats.node_foo_host_bar.processes_count_running:3|g">> |
| 183 | , <<"beam_stats.node_foo_host_bar.processes_count_suspended:0|g">> |
| 184 | , <<"beam_stats.node_foo_host_bar.processes_count_waiting:0|g">> |
| 185 | |
| 186 | % Process 1 |
| 187 | , <<"beam_stats.node_foo_host_bar.process_memory.reg_name_foo.0_1_0:15|g">> |
| 188 | , <<"beam_stats.node_foo_host_bar.process_total_heap_size.reg_name_foo.0_1_0:25|g">> |
| 189 | , <<"beam_stats.node_foo_host_bar.process_stack_size.reg_name_foo.0_1_0:10|g">> |
| 190 | , <<"beam_stats.node_foo_host_bar.process_message_queue_len.reg_name_foo.0_1_0:0|g">> |
| 191 | |
| 192 | % Process 2 |
| 193 | , <<"beam_stats.node_foo_host_bar.process_memory.bar_mod-bar_fun-1--NONE--NONE.0_2_0:25|g">> |
| 194 | , <<"beam_stats.node_foo_host_bar.process_total_heap_size.bar_mod-bar_fun-1--NONE--NONE.0_2_0:35|g">> |
| 195 | , <<"beam_stats.node_foo_host_bar.process_stack_size.bar_mod-bar_fun-1--NONE--NONE.0_2_0:40|g">> |
| 196 | , <<"beam_stats.node_foo_host_bar.process_message_queue_len.bar_mod-bar_fun-1--NONE--NONE.0_2_0:5|g">> |
| 197 | |
| 198 | % Process 3 |
| 199 | , <<"beam_stats.node_foo_host_bar.process_memory.baz_mod-baz_fun-3--baz_otp_mod-baz_otp_fun-2--0_0_0-0_1_0.0_3_0:25|g">> |
| 200 | , <<"beam_stats.node_foo_host_bar.process_total_heap_size.baz_mod-baz_fun-3--baz_otp_mod-baz_otp_fun-2--0_0_0-0_1_0.0_3_0:35|g">> |
| 201 | , <<"beam_stats.node_foo_host_bar.process_stack_size.baz_mod-baz_fun-3--baz_otp_mod-baz_otp_fun-2--0_0_0-0_1_0.0_3_0:40|g">> |
| 202 | , <<"beam_stats.node_foo_host_bar.process_message_queue_len.baz_mod-baz_fun-3--baz_otp_mod-baz_otp_fun-2--0_0_0-0_1_0.0_3_0:1|g">> |
| 203 | ], |
| 204 | MsgsReceived = binary:split(PacketsCombined, <<"\n">>, [global, trim]), |
| 205 | RemoveExpectedFromReceived = |
| 206 | fun (Expected, Received) -> |
| 207 | ct:log( |
| 208 | "Looking for expected msg ~p in remaining received ~p~n", |
| 209 | [Expected, Received] |
| 210 | ), |
| 211 | true = lists:member(Expected, Received), |
| 212 | Received -- [Expected] |
| 213 | end, |
| 214 | [] = lists:foldl(RemoveExpectedFromReceived, MsgsReceived, MsgsExpected). |