Commit | Line | Data |
---|---|---|
b0ab6ee2 SK |
1 | -module(beam_stats_consumer_statsd_SUITE). |
2 | ||
da5f2544 | 3 | -include_lib("beam_stats/include/beam_stats.hrl"). |
a8d431d1 | 4 | -include_lib("beam_stats/include/beam_stats_ets_table.hrl"). |
69ebab97 SK |
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"). | |
da5f2544 | 8 | |
b0ab6ee2 SK |
9 | -export( |
10 | [ all/0 | |
11 | , groups/0 | |
12 | ]). | |
13 | ||
14 | %% Test cases | |
15 | -export( | |
5681263f | 16 | [ t_send/1 |
7786d23b | 17 | , t_collect/1 |
b0ab6ee2 SK |
18 | ]). |
19 | ||
5681263f | 20 | -define(GROUP, beam_stats_consumer_statsd). |
b0ab6ee2 SK |
21 | |
22 | %% ============================================================================ | |
23 | %% Common Test callbacks | |
24 | %% ============================================================================ | |
25 | ||
26 | all() -> | |
27 | [{group, ?GROUP}]. | |
28 | ||
29 | groups() -> | |
30 | Tests = | |
5681263f | 31 | [ t_send |
7786d23b | 32 | , t_collect |
b0ab6ee2 SK |
33 | ], |
34 | Properties = [], | |
35 | [{?GROUP, Properties, Tests}]. | |
36 | ||
69ebab97 | 37 | %% ============================================================================ |
b0ab6ee2 | 38 | %% Test cases |
69ebab97 | 39 | %% ============================================================================ |
b0ab6ee2 | 40 | |
da5f2544 | 41 | t_send(_Cfg) -> |
69ebab97 SK |
42 | Pid0 = list_to_pid("<0.0.0>"), |
43 | Pid1 = list_to_pid("<0.1.0>"), | |
44 | Pid2 = list_to_pid("<0.2.0>"), | |
45 | Pid3 = list_to_pid("<0.3.0>"), | |
46 | Process1 = | |
47 | #beam_stats_process | |
48 | { pid = Pid1 | |
49 | , registered_name = {some, reg_name_foo} | |
50 | , ancestry = | |
51 | #beam_stats_process_ancestry | |
52 | { raw_initial_call = {foo_mod, foo_fun, 2} | |
53 | , otp_initial_call = none | |
54 | , otp_ancestors = none | |
55 | } | |
56 | , status = running | |
57 | , memory = 15 | |
58 | , total_heap_size = 25 | |
59 | , stack_size = 10 | |
60 | , message_queue_len = 0 | |
61 | }, | |
62 | Process2 = | |
63 | #beam_stats_process | |
64 | { pid = Pid2 | |
65 | , registered_name = none | |
66 | , ancestry = | |
67 | #beam_stats_process_ancestry | |
68 | { raw_initial_call = {bar_mod, bar_fun, 1} | |
69 | , otp_initial_call = none | |
70 | , otp_ancestors = none | |
71 | } | |
72 | , status = running | |
73 | , memory = 25 | |
74 | , total_heap_size = 35 | |
75 | , stack_size = 40 | |
76 | , message_queue_len = 5 | |
77 | }, | |
78 | Process3 = | |
79 | #beam_stats_process | |
80 | { pid = Pid3 | |
81 | , registered_name = none | |
82 | , ancestry = | |
83 | #beam_stats_process_ancestry | |
84 | { raw_initial_call = {baz_mod, baz_fun, 3} | |
85 | , otp_initial_call = {some, {baz_otp_mod, baz_otp_fun, 2}} | |
86 | , otp_ancestors = {some, [Pid0, Pid1]} | |
87 | } | |
88 | , status = running | |
89 | , memory = 25 | |
90 | , total_heap_size = 35 | |
91 | , stack_size = 40 | |
92 | , message_queue_len = 1 | |
93 | }, | |
94 | Processes = | |
95 | #beam_stats_processes | |
96 | { individual_stats = | |
97 | [ Process1 | |
98 | , Process2 | |
99 | , Process3 | |
100 | ] | |
101 | , count_all = 3 | |
102 | , count_exiting = 0 | |
103 | , count_garbage_collecting = 0 | |
104 | , count_registered = 1 | |
105 | , count_runnable = 0 | |
106 | , count_running = 3 | |
107 | , count_suspended = 0 | |
108 | , count_waiting = 0 | |
109 | }, | |
a8d431d1 SK |
110 | ETSTableStatsFoo = |
111 | #beam_stats_ets_table | |
112 | { id = foo | |
113 | , name = foo | |
114 | , size = 5 | |
115 | , memory = 25 | |
116 | }, | |
117 | ETSTableStatsBar = | |
118 | #beam_stats_ets_table | |
119 | { id = 37 | |
120 | , name = bar | |
121 | , size = 8 | |
122 | , memory = 38 | |
123 | }, | |
124 | % TODO: Indent #beam_stats as #beam_stats_ets_table | |
da5f2544 SK |
125 | BEAMStats = #beam_stats |
126 | { timestamp = {1, 2, 3} | |
127 | , node_id = 'node_foo@host_bar' | |
4d24f3b7 | 128 | , memory = [{mem_type_foo, 1}, {mem_type_bar, 2}, {mem_type_baz, 3}] |
b4e2333f SK |
129 | , io_bytes_in = 3 |
130 | , io_bytes_out = 7 | |
3fe887d7 | 131 | , context_switches = 5 |
142c0796 | 132 | , reductions = 9 |
deefeb3c | 133 | , run_queue = 17 |
a8d431d1 | 134 | , ets = [ETSTableStatsFoo, ETSTableStatsBar] |
69ebab97 | 135 | , processes = Processes |
da5f2544 SK |
136 | }, |
137 | ServerPort = 8125, | |
138 | {ok, ServerSocket} = gen_udp:open(ServerPort, [binary, {active, false}]), | |
139 | BEAMStatsQ = queue:in(BEAMStats, queue:new()), | |
140 | Options = [{dst_port, ServerPort}], | |
141 | {_, State1} = beam_stats_consumer_statsd:init(Options), | |
142 | State2 = beam_stats_consumer_statsd:consume(BEAMStatsQ, State1), | |
143 | {} = beam_stats_consumer_statsd:terminate(State2), | |
4d24f3b7 | 144 | ResultOfReceive1 = gen_udp:recv(ServerSocket, 0), |
4d24f3b7 | 145 | ResultOfReceive2 = gen_udp:recv(ServerSocket, 0), |
69ebab97 SK |
146 | ResultOfReceive3 = gen_udp:recv(ServerSocket, 0), |
147 | ResultOfReceive4 = gen_udp:recv(ServerSocket, 0), | |
da5f2544 | 148 | ok = gen_udp:close(ServerSocket), |
69ebab97 SK |
149 | {ok, {_, _, PacketReceived1}} = ResultOfReceive1, |
150 | {ok, {_, _, PacketReceived2}} = ResultOfReceive2, | |
151 | {ok, {_, _, PacketReceived3}} = ResultOfReceive3, | |
152 | {ok, {_, _, PacketReceived4}} = ResultOfReceive4, | |
4d24f3b7 SK |
153 | ct:log("PacketReceived1: ~n~s~n", [PacketReceived1]), |
154 | ct:log("PacketReceived2: ~n~s~n", [PacketReceived2]), | |
69ebab97 SK |
155 | ct:log("PacketReceived3: ~n~s~n", [PacketReceived3]), |
156 | ct:log("PacketReceived4: ~n~s~n", [PacketReceived4]), | |
157 | PacketsCombined = | |
158 | << PacketReceived1/binary | |
159 | , PacketReceived2/binary | |
160 | , PacketReceived3/binary | |
161 | , PacketReceived4/binary | |
162 | >>, | |
4d24f3b7 SK |
163 | ct:log("PacketsCombined: ~n~s~n", [PacketsCombined]), |
164 | MsgsExpected = | |
165 | [ <<"beam_stats.node_foo_host_bar.io.bytes_in:3|g">> | |
166 | , <<"beam_stats.node_foo_host_bar.io.bytes_out:7|g">> | |
167 | , <<"beam_stats.node_foo_host_bar.context_switches:5|g">> | |
168 | , <<"beam_stats.node_foo_host_bar.reductions:9|g">> | |
169 | , <<"beam_stats.node_foo_host_bar.run_queue:17|g">> | |
170 | , <<"beam_stats.node_foo_host_bar.memory.mem_type_foo:1|g">> | |
171 | , <<"beam_stats.node_foo_host_bar.memory.mem_type_bar:2|g">> | |
172 | , <<"beam_stats.node_foo_host_bar.memory.mem_type_baz:3|g">> | |
173 | , <<"beam_stats.node_foo_host_bar.ets_table.size.foo.foo:5|g">> | |
174 | , <<"beam_stats.node_foo_host_bar.ets_table.memory.foo.foo:25|g">> | |
175 | , <<"beam_stats.node_foo_host_bar.ets_table.size.bar.37:8|g">> | |
176 | , <<"beam_stats.node_foo_host_bar.ets_table.memory.bar.37:38|g">> | |
69ebab97 SK |
177 | |
178 | % Processes totals | |
179 | , <<"beam_stats.node_foo_host_bar.processes_count_all:3|g">> | |
180 | , <<"beam_stats.node_foo_host_bar.processes_count_exiting:0|g">> | |
181 | , <<"beam_stats.node_foo_host_bar.processes_count_garbage_collecting:0|g">> | |
182 | , <<"beam_stats.node_foo_host_bar.processes_count_registered:1|g">> | |
183 | , <<"beam_stats.node_foo_host_bar.processes_count_runnable:0|g">> | |
184 | , <<"beam_stats.node_foo_host_bar.processes_count_running:3|g">> | |
185 | , <<"beam_stats.node_foo_host_bar.processes_count_suspended:0|g">> | |
186 | , <<"beam_stats.node_foo_host_bar.processes_count_waiting:0|g">> | |
187 | ||
188 | % Process 1 | |
189 | , <<"beam_stats.node_foo_host_bar.process_memory.reg_name_foo.0_1_0:15|g">> | |
190 | , <<"beam_stats.node_foo_host_bar.process_total_heap_size.reg_name_foo.0_1_0:25|g">> | |
191 | , <<"beam_stats.node_foo_host_bar.process_stack_size.reg_name_foo.0_1_0:10|g">> | |
192 | , <<"beam_stats.node_foo_host_bar.process_message_queue_len.reg_name_foo.0_1_0:0|g">> | |
193 | ||
194 | % Process 2 | |
195 | , <<"beam_stats.node_foo_host_bar.process_memory.bar_mod-bar_fun-1--NONE--NONE.0_2_0:25|g">> | |
196 | , <<"beam_stats.node_foo_host_bar.process_total_heap_size.bar_mod-bar_fun-1--NONE--NONE.0_2_0:35|g">> | |
197 | , <<"beam_stats.node_foo_host_bar.process_stack_size.bar_mod-bar_fun-1--NONE--NONE.0_2_0:40|g">> | |
198 | , <<"beam_stats.node_foo_host_bar.process_message_queue_len.bar_mod-bar_fun-1--NONE--NONE.0_2_0:5|g">> | |
199 | ||
200 | % Process 3 | |
201 | , <<"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">> | |
202 | , <<"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">> | |
203 | , <<"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">> | |
204 | , <<"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">> | |
4d24f3b7 SK |
205 | ], |
206 | MsgsReceived = binary:split(PacketsCombined, <<"\n">>, [global, trim]), | |
207 | RemoveExpectedFromReceived = | |
208 | fun (Expected, Received) -> | |
209 | ct:log( | |
210 | "Looking for expected msg ~p in remaining received ~p~n", | |
211 | [Expected, Received] | |
212 | ), | |
213 | true = lists:member(Expected, Received), | |
214 | Received -- [Expected] | |
215 | end, | |
216 | [] = lists:foldl(RemoveExpectedFromReceived, MsgsReceived, MsgsExpected). | |
7786d23b SK |
217 | |
218 | t_collect(_Cfg) -> | |
219 | Pid0 = list_to_pid("<0.0.0>"), | |
220 | Pid1 = list_to_pid("<0.1.0>"), | |
221 | Pid2 = list_to_pid("<0.2.0>"), | |
222 | Pid3 = list_to_pid("<0.3.0>"), | |
223 | Process1 = | |
224 | #beam_stats_process | |
225 | { pid = Pid1 | |
226 | , registered_name = {some, reg_name_foo} | |
227 | , ancestry = | |
228 | #beam_stats_process_ancestry | |
229 | { raw_initial_call = {foo_mod, foo_fun, 2} | |
230 | , otp_initial_call = none | |
231 | , otp_ancestors = none | |
232 | } | |
233 | , status = running | |
234 | , memory = 15 | |
235 | , total_heap_size = 25 | |
236 | , stack_size = 10 | |
237 | , message_queue_len = 0 | |
238 | }, | |
239 | Process2 = | |
240 | #beam_stats_process | |
241 | { pid = Pid2 | |
242 | , registered_name = none | |
243 | , ancestry = | |
244 | #beam_stats_process_ancestry | |
245 | { raw_initial_call = {bar_mod, bar_fun, 1} | |
246 | , otp_initial_call = none | |
247 | , otp_ancestors = none | |
248 | } | |
249 | , status = running | |
250 | , memory = 25 | |
251 | , total_heap_size = 35 | |
252 | , stack_size = 40 | |
253 | , message_queue_len = 5 | |
254 | }, | |
255 | Process3 = | |
256 | #beam_stats_process | |
257 | { pid = Pid3 | |
258 | , registered_name = none | |
259 | , ancestry = | |
260 | #beam_stats_process_ancestry | |
261 | { raw_initial_call = {baz_mod, baz_fun, 3} | |
262 | , otp_initial_call = {some, {baz_otp_mod, baz_otp_fun, 2}} | |
263 | , otp_ancestors = {some, [Pid0, Pid1]} | |
264 | } | |
265 | , status = running | |
266 | , memory = 25 | |
267 | , total_heap_size = 35 | |
268 | , stack_size = 40 | |
269 | , message_queue_len = 1 | |
270 | }, | |
271 | Processes = | |
272 | #beam_stats_processes | |
273 | { individual_stats = | |
274 | [ Process1 | |
275 | , Process2 | |
276 | , Process3 | |
277 | ] | |
278 | , count_all = 3 | |
279 | , count_exiting = 0 | |
280 | , count_garbage_collecting = 0 | |
281 | , count_registered = 1 | |
282 | , count_runnable = 0 | |
283 | , count_running = 3 | |
284 | , count_suspended = 0 | |
285 | , count_waiting = 0 | |
286 | }, | |
287 | ETSTableStatsFoo = | |
288 | #beam_stats_ets_table | |
289 | { id = foo | |
290 | , name = foo | |
291 | , size = 5 | |
292 | , memory = 40 | |
293 | }, | |
294 | ETSTableStatsBar = | |
295 | #beam_stats_ets_table | |
296 | { id = 37 | |
297 | , name = bar | |
298 | , size = 8 | |
299 | , memory = 64 | |
300 | }, | |
301 | meck:new(beam_stats_source), | |
302 | meck:expect(beam_stats_source, erlang_memory, | |
303 | fun () -> [{mem_type_foo, 1}, {mem_type_bar, 2}, {mem_type_baz, 3}] end), | |
304 | meck:expect(beam_stats_source, erlang_node, | |
305 | fun () -> 'node_foo@host_bar' end), | |
306 | meck:expect(beam_stats_source, erlang_registered, | |
307 | fun () -> [reg_name_foo] end), | |
308 | meck:expect(beam_stats_source, erlang_statistics, | |
309 | fun (io ) -> {{input, 3}, {output, 7}} | |
310 | ; (context_switches) -> {5, 0} | |
311 | ; (reductions ) -> {0, 9} % 1st element is unused | |
312 | ; (run_queue ) -> 17 | |
313 | end | |
314 | ), | |
315 | meck:expect(beam_stats_source, ets_all, | |
316 | fun () -> [foo, 37] end), | |
317 | meck:expect(beam_stats_source, erlang_system_info, | |
318 | fun (wordsize) -> 8 end), | |
319 | meck:expect(beam_stats_source, ets_info, | |
320 | fun (foo, memory) -> 5 | |
321 | ; (foo, name ) -> foo | |
322 | ; (foo, size ) -> 5 | |
323 | ; (37 , memory) -> 8 | |
324 | ; (37 , name ) -> bar | |
325 | ; (37 , size ) -> 8 | |
326 | end | |
327 | ), | |
328 | meck:expect(beam_stats_source, erlang_processes, | |
329 | fun () -> [Pid1, Pid2, Pid3] end), | |
330 | meck:expect(beam_stats_source, os_timestamp, | |
331 | fun () -> {1, 2, 3} end), | |
332 | meck:expect(beam_stats_source, erlang_process_info, | |
333 | fun (P, K) when P == Pid1 -> | |
334 | case K | |
335 | of dictionary -> {K, []} | |
336 | ; initial_call -> {K, {foo_mod, foo_fun, 2}} | |
337 | ; registered_name -> {K, reg_name_foo} | |
338 | ; status -> {K, running} | |
339 | ; memory -> {K, 15} | |
340 | ; total_heap_size -> {K, 25} | |
341 | ; stack_size -> {K, 10} | |
342 | ; message_queue_len -> {K, 0} | |
343 | end | |
344 | ; (P, K) when P == Pid2 -> | |
345 | case K | |
346 | of dictionary -> {K, []} | |
347 | ; initial_call -> {K, {bar_mod, bar_fun, 1}} | |
348 | ; registered_name -> [] | |
349 | ; status -> {K, running} | |
350 | ; memory -> {K, 25} | |
351 | ; total_heap_size -> {K, 35} | |
352 | ; stack_size -> {K, 40} | |
353 | ; message_queue_len -> {K, 5} | |
354 | end | |
355 | ; (P, K) when P == Pid3 -> | |
356 | Dict = | |
357 | [ {'$initial_call', {baz_otp_mod, baz_otp_fun, 2}} | |
358 | , {'$ancestors' , [Pid0, Pid1]} | |
359 | ], | |
360 | case K | |
361 | of dictionary -> {K, Dict} | |
362 | ; initial_call -> {K, {baz_mod, baz_fun, 3}} | |
363 | ; registered_name -> [] | |
364 | ; status -> {K, running} | |
365 | ; memory -> {K, 25} | |
366 | ; total_heap_size -> {K, 35} | |
367 | ; stack_size -> {K, 40} | |
368 | ; message_queue_len -> {K, 1} | |
369 | end | |
370 | end | |
371 | ), | |
372 | BEAMStatsExpected = | |
373 | #beam_stats | |
374 | { timestamp = {1, 2, 3} | |
375 | , node_id = 'node_foo@host_bar' | |
376 | , memory = [{mem_type_foo, 1}, {mem_type_bar, 2}, {mem_type_baz, 3}] | |
377 | , io_bytes_in = 3 | |
378 | , io_bytes_out = 7 | |
379 | , context_switches = 5 | |
380 | , reductions = 9 | |
381 | , run_queue = 17 | |
382 | , ets = [ETSTableStatsFoo, ETSTableStatsBar] | |
383 | , processes = Processes | |
384 | }, | |
385 | BEAMStatsComputed = beam_stats_state:export(beam_stats_state:new()), | |
386 | ct:log("BEAMStatsExpected: ~p~n", [BEAMStatsExpected]), | |
387 | ct:log("BEAMStatsComputed: ~p~n", [BEAMStatsComputed]), | |
388 | BEAMStatsExpected = BEAMStatsComputed, | |
389 | meck:unload(beam_stats_source). |