feat: implement beam_stats_msg_graphite:to_bin/1
[beam_stats.git] / src / beam_stats_msg_graphite.erl
CommitLineData
a9ed8751
SK
1-module(beam_stats_msg_graphite).
2
3-include("include/beam_stats.hrl").
6e1a5b00 4-include("include/beam_stats_ets_table.hrl").
a9ed8751 5-include("include/beam_stats_msg_graphite.hrl").
4bb8ddfe
SK
6-include("include/beam_stats_process.hrl").
7-include("include/beam_stats_process_ancestry.hrl").
8-include("include/beam_stats_processes.hrl").
a9ed8751
SK
9
10-export_type(
11 [ t/0
12 ]).
13
14-export(
15 [ of_beam_stats/1
67948b18 16 , to_bin/1
a9ed8751
SK
17 ]).
18
19-define(T, #?MODULE).
20
21-type t() ::
22 ?T{}.
23
67948b18
SK
24%% ============================================================================
25%% API
26%% ============================================================================
27
a9ed8751
SK
28-spec of_beam_stats(beam_stats:t()) ->
29 [t()].
30of_beam_stats(#beam_stats{node_id=NodeID}=BeamStats) ->
31 NodeIDBin = node_id_to_bin(NodeID),
32 of_beam_stats(BeamStats, NodeIDBin).
33
34-spec of_beam_stats(beam_stats:t(), binary()) ->
35 [t()].
36of_beam_stats(#beam_stats
37 { timestamp = Timestamp
38 , node_id = _
39 , memory = Memory
a37cd038
SK
40 % TODO: Handle the rest of data points
41 , io_bytes_in = IOBytesIn
42 , io_bytes_out = IOBytesOut
43 , context_switches = ContextSwitches
44 , reductions = Reductions
45 , run_queue = RunQueue
6e1a5b00 46 , ets = ETS
4bb8ddfe 47 , processes = Processes
a9ed8751
SK
48 },
49 <<NodeID/binary>>
50) ->
a37cd038
SK
51 Ts = Timestamp,
52 N = NodeID,
53 [ cons([N, <<"io">> , <<"bytes_in">> ], IOBytesIn , Ts)
54 , cons([N, <<"io">> , <<"bytes_out">>], IOBytesOut , Ts)
55 , cons([N, <<"context_switches">> ], ContextSwitches, Ts)
56 , cons([N, <<"reductions">> ], Reductions , Ts)
57 , cons([N, <<"run_queue">> ], RunQueue , Ts)
58 | of_memory(Memory, NodeID, Ts)
6e1a5b00
SK
59 ]
60 ++ of_ets(ETS, NodeID, Ts)
4bb8ddfe 61 ++ of_processes(Processes, NodeID, Ts).
a9ed8751 62
67948b18
SK
63-spec to_bin(t()) ->
64 binary().
65to_bin(
66 ?T
67 { path = Path
68 , value = Value
69 , timestamp = Timestamp
70 }
71) ->
72 PathBin = bin_join(Path, <<".">>),
73 ValueBin = integer_to_binary(Value),
74 TimestampInt = timestamp_to_integer(Timestamp),
75 TimestampBin = integer_to_binary(TimestampInt),
76 <<PathBin/binary, " ", ValueBin/binary, " ", TimestampBin/binary>>.
77
78%% ============================================================================
79%% Helpers
80%% ============================================================================
81
82-spec bin_join([binary()], binary()) ->
83 binary().
84bin_join([] , <<_/binary>> ) -> <<>>;
85bin_join([<<B/binary>> | []] , <<_/binary>> ) -> B;
86bin_join([<<B/binary>> | [_|_]=Bins], <<Sep/binary>>) ->
87 BinsBin = bin_join(Bins, Sep),
88 <<B/binary, Sep/binary, BinsBin/binary>>.
89
90-spec timestamp_to_integer(erlang:timestamp()) ->
91 non_neg_integer().
92timestamp_to_integer({Megaseconds, Seconds, _}) ->
93 Megaseconds * 1000000 + Seconds.
94
a9ed8751
SK
95-spec of_memory([{atom(), non_neg_integer()}], binary(), erlang:timestamp()) ->
96 [t()].
97of_memory(Memory, <<NodeID/binary>>, Timestamp) ->
98 ComponentToMessage =
99 fun ({Key, Value}) ->
100 KeyBin = atom_to_binary(Key, latin1),
d07a494b 101 cons([NodeID, <<"memory">>, KeyBin], Value, Timestamp)
a9ed8751
SK
102 end,
103 lists:map(ComponentToMessage, Memory).
104
6e1a5b00
SK
105-spec of_ets(beam_stats_ets_table:t(), binary(), erlang:timestamp()) ->
106 [t()].
107of_ets(PerTableStats, <<NodeID/binary>>, Timestamp) ->
108 OfEtsTable = fun (Table) -> of_ets_table(Table, NodeID, Timestamp) end,
109 NestedMsgs = lists:map(OfEtsTable, PerTableStats),
110 lists:append(NestedMsgs).
111
112-spec of_ets_table(beam_stats_ets_table:t(), binary(), erlang:timestamp()) ->
113 [t()].
114of_ets_table(#beam_stats_ets_table
115 { id = ID
116 , name = Name
117 , size = Size
118 , memory = Memory
119 },
120 <<NodeID/binary>>,
121 Timestamp
122) ->
123 IDBin = beam_stats_ets_table:id_to_bin(ID),
124 NameBin = atom_to_binary(Name, latin1),
125 NameAndID = [NameBin, IDBin],
126 [ cons([NodeID, <<"ets_table">>, <<"size">> | NameAndID], Size , Timestamp)
127 , cons([NodeID, <<"ets_table">>, <<"memory">> | NameAndID], Memory, Timestamp)
128 ].
129
4bb8ddfe
SK
130-spec of_processes(beam_stats_processes:t(), binary(), erlang:timestamp()) ->
131 [t()].
132of_processes(
133 #beam_stats_processes
134 { individual_stats = Processes
135 , count_all = CountAll
136 , count_exiting = CountExiting
137 , count_garbage_collecting = CountGarbageCollecting
138 , count_registered = CountRegistered
139 , count_runnable = CountRunnable
140 , count_running = CountRunning
141 , count_suspended = CountSuspended
142 , count_waiting = CountWaiting
143 },
144 <<NodeID/binary>>,
145 Timestamp
146) ->
147 OfProcess = fun (P) -> of_process(P, NodeID, Timestamp) end,
148 PerProcessMsgsNested = lists:map(OfProcess, Processes),
149 PerProcessMsgsFlattened = lists:append(PerProcessMsgsNested),
150 Ts = Timestamp,
151 N = NodeID,
152 [ cons([N, <<"processes_count_all">> ], CountAll , Ts)
153 , cons([N, <<"processes_count_exiting">> ], CountExiting , Ts)
154 , cons([N, <<"processes_count_garbage_collecting">>], CountGarbageCollecting, Ts)
155 , cons([N, <<"processes_count_registered">> ], CountRegistered , Ts)
156 , cons([N, <<"processes_count_runnable">> ], CountRunnable , Ts)
157 , cons([N, <<"processes_count_running">> ], CountRunning , Ts)
158 , cons([N, <<"processes_count_suspended">> ], CountSuspended , Ts)
159 , cons([N, <<"processes_count_waiting">> ], CountWaiting , Ts)
160 | PerProcessMsgsFlattened
161 ].
162
163-spec of_process(beam_stats_process:t(), binary(), erlang:timestamp()) ->
164 [t()].
165of_process(
166 #beam_stats_process
167 { pid = Pid
168 , memory = Memory
169 , total_heap_size = TotalHeapSize
170 , stack_size = StackSize
171 , message_queue_len = MsgQueueLen
172 }=Process,
173 <<NodeID/binary>>,
174 Timestamp
175) ->
176 Origin = beam_stats_process:get_best_known_origin(Process),
177 OriginBin = proc_origin_to_bin(Origin),
178 PidBin = pid_to_bin(Pid),
179 OriginAndPid = [OriginBin, PidBin],
180 Ts = Timestamp,
181 N = NodeID,
182 [ cons([N, <<"process_memory">> , OriginAndPid], Memory , Ts)
183 , cons([N, <<"process_total_heap_size">> , OriginAndPid], TotalHeapSize , Ts)
184 , cons([N, <<"process_stack_size">> , OriginAndPid], StackSize , Ts)
185 , cons([N, <<"process_message_queue_len">> , OriginAndPid], MsgQueueLen , Ts)
186 ].
187
188-spec proc_origin_to_bin(beam_stats_process:best_known_origin()) ->
189 binary().
190proc_origin_to_bin({registered_name, Name}) ->
191 atom_to_binary(Name, utf8);
192proc_origin_to_bin({ancestry, Ancestry}) ->
193 #beam_stats_process_ancestry
194 { raw_initial_call = InitCallRaw
195 , otp_initial_call = InitCallOTPOpt
196 , otp_ancestors = AncestorsOpt
197 } = Ancestry,
198 Blank = <<"NONE">>,
199 InitCallOTPBinOpt = hope_option:map(InitCallOTPOpt , fun mfa_to_bin/1),
200 InitCallOTPBin = hope_option:get(InitCallOTPBinOpt, Blank),
201 AncestorsBinOpt = hope_option:map(AncestorsOpt , fun ancestors_to_bin/1),
202 AncestorsBin = hope_option:get(AncestorsBinOpt , Blank),
203 InitCallRawBin = mfa_to_bin(InitCallRaw),
204 << InitCallRawBin/binary
205 , "--"
206 , InitCallOTPBin/binary
207 , "--"
208 , AncestorsBin/binary
209 >>.
210
211ancestors_to_bin([]) ->
212 <<>>;
213ancestors_to_bin([A | Ancestors]) ->
214 ABin = ancestor_to_bin(A),
215 case ancestors_to_bin(Ancestors)
216 of <<>> ->
217 ABin
218 ; <<AncestorsBin/binary>> ->
219 <<ABin/binary, "-", AncestorsBin/binary>>
220 end.
221
222ancestor_to_bin(A) when is_atom(A) ->
223 atom_to_binary(A, utf8);
224ancestor_to_bin(A) when is_pid(A) ->
225 pid_to_bin(A).
226
227pid_to_bin(Pid) ->
228 PidList = erlang:pid_to_list(Pid),
229 PidBin = re:replace(PidList, "[\.]", "_", [global, {return, binary}]),
230 re:replace(PidBin , "[><]", "" , [global, {return, binary}]).
231
232-spec mfa_to_bin(mfa()) ->
233 binary().
234mfa_to_bin({Module, Function, Arity}) ->
235 ModuleBin = atom_to_binary(Module , utf8),
236 FunctionBin = atom_to_binary(Function, utf8),
237 ArityBin = erlang:integer_to_binary(Arity),
238 <<ModuleBin/binary, "-", FunctionBin/binary, "-", ArityBin/binary>>.
239
a37cd038
SK
240-spec cons([binary()], integer(), erlang:timestamp()) ->
241 t().
242cons(Path, Value, Timestamp) ->
243 ?T
244 { path = Path
245 , value = Value
246 , timestamp = Timestamp
247 }.
248
a9ed8751
SK
249-spec node_id_to_bin(node()) ->
250 binary().
251node_id_to_bin(NodeID) ->
252 NodeIDBin = atom_to_binary(NodeID, utf8),
253 re:replace(NodeIDBin, "[\@\.]", "_", [global, {return, binary}]).
This page took 0.034937 seconds and 4 git commands to generate.