-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmultiping.erl
executable file
·112 lines (95 loc) · 2.65 KB
/
multiping.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/escript
-define(PING_TIMEOUT,9000).
main(["config"])->
showConfig();
main([])->
Hosts=getHosts(),
forkGuards(Hosts),
readFromGuards(Hosts);
main(Unknown)->
io:format("Unknown parameters ~p",[Unknown]).
% Forks Guard processes commands for each host
forkGuards([]) ->
[];
forkGuards([Host|HTail]) ->
Master=self(),
spawn(fun()->pingGuard(Host,Master) end),
forkGuards(HTail).
% Reads messages from guards
readFromGuards([])->
ok;
readFromGuards(HostList) ->
receive
{Host, result, RTT, Lost} ->
printSingleVal(Host,RTT,Lost),
NewHostList=lists:delete(Host,HostList),
readFromGuards(NewHostList);
{Host, timeout} ->
printSingleVal(Host,timeout,timeout),
NewHostList=lists:delete(Host,HostList),
readFromGuards(NewHostList);
Other ->
io:format("#Got weird message : ~p\n",[Other]),
readFromGuards(HostList)
end.
% Process that runs single ping and guards time of the processing of it
pingGuard(Host,Master)->
Command=lists:concat(["ping -nq ", getPingArgs(), " ", Host]),
Port=open_port({spawn,Command},[]),
receive
{Port,{data,Data}} ->
RTT=getRTTFromResponse(Data),
Lost=getLostFromResponse(Data),
Master ! {Host, result, RTT, Lost}
after ?PING_TIMEOUT->
port_close(Port),
Master ! {Host, timeout}
end.
%% Munin protocol helpers
% Prints configuration block
showConfig()->
io:format("graph_title Multiping\n",[]),
Hosts=getHosts(),
lists:foreach(fun(Host)->printSingleConfig(Host) end,Hosts),
ok.
% Prints configuration for single host
printSingleConfig(Host) ->
EHost=escapeHost(Host),
io:format("~s_rtt.label ~s RTT\n",[EHost,Host]),
io:format("~s_lost.label ~s Lost packets\n",[EHost,Host]),
ok.
% Prints vlues for single host
printSingleVal(Host,RTT,Lost)->
EHost=escapeHost(Host),
io:format("~s_rtt.value ~s\n",[EHost,RTT]),
io:format("~s_lost.value ~s\n",[EHost,Lost]),
ok.
% Esape string to use as field name
escapeHost(Host)->
re:replace(Host,"\\.","_",[global,{return,list}]).
%% Ping command output scrapers
% Fetches Round-Trip-Time
getRTTFromResponse(Data)->
case re:run(Data,"min/avg/max.*\\s\\d+(?:\\.\\d+)?/(\\d+(?:\\.\\d+)?)/\\d+(?:\\.\\d+)?",[{capture,all_but_first,list}]) of
{match,[Val]} -> Val;
_ -> nomatch
end.
% Fetches count of lost packets
getLostFromResponse(Data)->
case re:run(Data,"received, (\\d+)% packet loss, time",[{capture,all_but_first,list}]) of
{match,[Val]} -> Val;
_ -> nomatch
end.
%% ENV Readings
% Returns host list to ping
getHosts()->
case os:getenv("host") of
false -> [];
Hosts -> string:tokens(Hosts," \t")
end.
% Returns ping command args
getPingArgs()->
case os:getenv("ping_args") of
false -> "-c 5 ";
Hosts -> Hosts
end.