wifi-watch 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -7
- data/bin/wifi-watch +54 -37
- data/wifi-service/index.js +29 -0
- data/wifi-service/pinger.js +132 -0
- data/wifi-watch.gemspec +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9797d50586860cee6df38fdec51a3b14700bc21
|
4
|
+
data.tar.gz: b3b495a1b8ec39d7064493ffedff9995a0f79790
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6696aa3538b2673da41774062de6cd58dc3839e57bd337a56b8e07fe3b612df1fad66cb2021d89181d519f23b51d30caf8f750b085be321da741b8f2883e3b8d
|
7
|
+
data.tar.gz: a3759eafc8138bbaa6831326933cac144ba8aff3aab6e4004478300b38834b82a0ac141c7edbb0a07c5dca2bc554881b08ef2c86f7ff7f210f5902b93a33df53
|
data/README.md
CHANGED
@@ -60,9 +60,10 @@ sudo mv wifi-watch /usr/local/bin
|
|
60
60
|
|
61
61
|
```
|
62
62
|
-h, --host host Host to ping [ns.google.com].
|
63
|
-
-c, --count seconds Accounting period [600].
|
64
|
-
|
65
|
-
--
|
63
|
+
-c, --count seconds Accounting period length [600 seconds].
|
64
|
+
-p, --periods periods Accounting periods to run [infinite].
|
65
|
+
--ping-to file Write ping output to a file for debugging.
|
66
|
+
--ping-from file Read ping input from a file ('-' for stdin).
|
66
67
|
-v, --version Version.
|
67
68
|
--help This message.
|
68
69
|
```
|
@@ -173,7 +174,7 @@ It is easy to capture the raw ping output to a file for later
|
|
173
174
|
replay and testing.
|
174
175
|
|
175
176
|
```
|
176
|
-
wifi-watch --count 10 --
|
177
|
+
wifi-watch --count 10 --ping-to test1.log
|
177
178
|
PING ns.google.com (216.239.32.10): 56 data bytes
|
178
179
|
|
179
180
|
Time Ping Run Mode Failed Round Trip
|
@@ -189,7 +190,7 @@ so replaying the file later on should result in
|
|
189
190
|
identical appearing output.
|
190
191
|
|
191
192
|
```
|
192
|
-
wifi-watch --
|
193
|
+
wifi-watch --ping-from test1.log
|
193
194
|
PING ns.google.com (216.239.32.10): 56 data bytes
|
194
195
|
|
195
196
|
Time Ping Run Mode Failed Round Trip
|
@@ -200,7 +201,7 @@ Time Ping Run Mode Failed Round Trip
|
|
200
201
|
10:06 5 1 fail 20.0% 55.16 ms
|
201
202
|
```
|
202
203
|
|
203
|
-
Although the --
|
204
|
+
Although the --ping-from output should appear to be the same
|
204
205
|
as live ping monitoring there is a difference. Instead of emitting
|
205
206
|
every intermediate count on the current line, only the final
|
206
207
|
line is printed. This helps keep test cases short and readable.
|
@@ -213,7 +214,7 @@ Bug reports and pull requests are welcome on GitHub at
|
|
213
214
|
https://github.com/jgorman/wifi-watch.
|
214
215
|
|
215
216
|
If you discover a shortcoming capture the ping output
|
216
|
-
using --
|
217
|
+
using --ping-to and open an issue. Thanks!
|
217
218
|
|
218
219
|
## License
|
219
220
|
|
data/bin/wifi-watch
CHANGED
@@ -9,42 +9,46 @@ class WifiWatch
|
|
9
9
|
Default_host = "ns.google.com" # Ping target host.
|
10
10
|
Default_count = 600 # Accounting period in seconds.
|
11
11
|
Program = "wifi-watch"
|
12
|
-
Version = "1.0.
|
12
|
+
Version = "1.0.2"
|
13
13
|
|
14
14
|
def run
|
15
15
|
@shown_header = false # Have we shown the column headers yet?
|
16
16
|
@dns_failing = false # Are DNS lookups currently failing?
|
17
17
|
@display_line = nil # The current display line.
|
18
|
-
@
|
19
|
-
@
|
18
|
+
@ping_to = nil # Save timestamped ping output here.
|
19
|
+
@ping_from = nil # Read timestamped ping input here.
|
20
20
|
@options = get_options()
|
21
21
|
|
22
|
-
if @options.
|
22
|
+
if @options.ping_to
|
23
23
|
begin
|
24
|
-
@
|
24
|
+
@ping_to = File.open(@options.ping_to, "w")
|
25
25
|
rescue => e
|
26
26
|
puts
|
27
|
-
puts "
|
27
|
+
puts "ping_to=#{@options.ping_to}: #{e}"
|
28
28
|
puts
|
29
29
|
exit
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
if @options.
|
33
|
+
if @options.ping_from
|
34
34
|
|
35
|
-
# Debug mode simulates ping output from a captured --
|
35
|
+
# Debug mode simulates ping output from a captured --ping-to file.
|
36
36
|
begin
|
37
|
-
|
37
|
+
if @options.ping_from == "-"
|
38
|
+
@ping_from = STDIN
|
39
|
+
else
|
40
|
+
@ping_from = File.open(@options.ping_from, "r")
|
41
|
+
end
|
38
42
|
rescue => e
|
39
43
|
puts
|
40
|
-
puts "
|
44
|
+
puts "ping_from=#{@options.ping_from}: #{e}"
|
41
45
|
puts
|
42
46
|
exit
|
43
47
|
end
|
44
48
|
|
45
49
|
# Call ping_period() for each ping run section.
|
46
|
-
until @
|
47
|
-
ping_period(@
|
50
|
+
until @ping_from.eof?
|
51
|
+
ping_period(@ping_from) # Reads up to next "END_OF_PING" line.
|
48
52
|
end
|
49
53
|
if @dns_failing
|
50
54
|
commit_line() # Show that we ended up in dns failure mode.
|
@@ -53,12 +57,19 @@ class WifiWatch
|
|
53
57
|
else
|
54
58
|
|
55
59
|
# Run ping multiple times.
|
60
|
+
periods = 0
|
56
61
|
while true
|
57
62
|
count = beautiful_times()
|
58
63
|
cmd = "ping -c #{count} #{@options.host}"
|
59
64
|
stdin, stdout, pid = PTY.spawn( cmd )
|
60
65
|
ping_period(stdin) # Run one accounting period.
|
61
66
|
Process.waitall() # Soak up any zombie pings.
|
67
|
+
if @options.periods > 0
|
68
|
+
periods += 1
|
69
|
+
if periods >= @options.periods
|
70
|
+
break
|
71
|
+
end
|
72
|
+
end
|
62
73
|
end
|
63
74
|
|
64
75
|
end
|
@@ -66,15 +77,16 @@ class WifiWatch
|
|
66
77
|
rescue Interrupt
|
67
78
|
commit_line()
|
68
79
|
ensure
|
69
|
-
if @
|
70
|
-
@
|
80
|
+
if @ping_to
|
81
|
+
@ping_to.close
|
71
82
|
end
|
72
83
|
end
|
73
84
|
|
74
85
|
def get_options
|
75
|
-
options
|
76
|
-
options.host
|
77
|
-
options.count
|
86
|
+
options = OpenStruct.new
|
87
|
+
options.host = Default_host
|
88
|
+
options.count = Default_count
|
89
|
+
options.periods = 0
|
78
90
|
|
79
91
|
opt_parser = OptionParser.new do |opt|
|
80
92
|
opt.banner = "Usage: #{Program} [OPTIONS]"
|
@@ -85,19 +97,24 @@ class WifiWatch
|
|
85
97
|
end
|
86
98
|
|
87
99
|
opt.on("-c", "--count seconds", Integer,
|
88
|
-
"Accounting period [#{options.count}].") do |count|
|
100
|
+
"Accounting period length [#{options.count} seconds].") do |count|
|
89
101
|
raise "--count must be positive" unless count > 0
|
90
102
|
options.count = count
|
91
103
|
end
|
92
104
|
|
93
|
-
opt.on("
|
94
|
-
"
|
95
|
-
options.
|
105
|
+
opt.on("-p", "--periods periods", Integer,
|
106
|
+
"Accounting periods to run [infinite].") do |periods|
|
107
|
+
options.periods = periods
|
108
|
+
end
|
109
|
+
|
110
|
+
opt.on("--ping-to file",
|
111
|
+
"Write ping output to a file for debugging.") do |ping_to|
|
112
|
+
options.ping_to = ping_to
|
96
113
|
end
|
97
114
|
|
98
|
-
opt.on("--
|
99
|
-
"Read ping input from a file for
|
100
|
-
options.
|
115
|
+
opt.on("--ping-from file",
|
116
|
+
"Read ping input from a file ('-' for stdin).") do |ping_from|
|
117
|
+
options.ping_from = ping_from
|
101
118
|
end
|
102
119
|
|
103
120
|
opt.on("-v", "--version", "Version.") do
|
@@ -158,9 +175,9 @@ class WifiWatch
|
|
158
175
|
now = Time.now
|
159
176
|
if now - last_notified >= 1
|
160
177
|
hhmmss_line(now, "Waiting for dns lookup of #{@options.host} ...")
|
161
|
-
if @
|
162
|
-
@
|
163
|
-
@
|
178
|
+
if @ping_to
|
179
|
+
@ping_to.puts "#{now.to_i} DNS_LOOKUP #{@display_line}"
|
180
|
+
@ping_to.flush
|
164
181
|
end
|
165
182
|
last_notified = now
|
166
183
|
end
|
@@ -188,7 +205,7 @@ class WifiWatch
|
|
188
205
|
first_byte = nil
|
189
206
|
end
|
190
207
|
|
191
|
-
if @
|
208
|
+
if @ping_from
|
192
209
|
# Read from the debugging source file up to the end of this ping run.
|
193
210
|
if line == "END_OF_PING"
|
194
211
|
break # End this ping accounting period run.
|
@@ -200,17 +217,17 @@ class WifiWatch
|
|
200
217
|
line_time = Time.now
|
201
218
|
end
|
202
219
|
|
203
|
-
if @
|
220
|
+
if @ping_to
|
204
221
|
# Capture this ping output line with the timestamp for later debugging.
|
205
|
-
@
|
206
|
-
@
|
222
|
+
@ping_to.puts "#{line_time.to_i} #{line}"
|
223
|
+
@ping_to.flush
|
207
224
|
end
|
208
225
|
|
209
226
|
# DNS failure modes.
|
210
227
|
if line =~ /cannot resolve/
|
211
228
|
# ping: cannot resolve ns.google.com: Unknown host
|
212
229
|
hhmmss_line(line_time, line)
|
213
|
-
sleep 1 unless @
|
230
|
+
sleep 1 unless @ping_from # Speed up testing.
|
214
231
|
@dns_failing = true
|
215
232
|
elsif line =~ /DNS_LOOKUP (.*)/
|
216
233
|
# Waiting for dns lookup of ns.google.com ...
|
@@ -301,10 +318,10 @@ class WifiWatch
|
|
301
318
|
|
302
319
|
end
|
303
320
|
|
304
|
-
if @
|
321
|
+
if @ping_to
|
305
322
|
# Insert a ping run separator line into the debugging file.
|
306
|
-
@
|
307
|
-
@
|
323
|
+
@ping_to.puts "END_OF_PING"
|
324
|
+
@ping_to.flush
|
308
325
|
end
|
309
326
|
|
310
327
|
# Final summary line.
|
@@ -379,7 +396,7 @@ class WifiWatch
|
|
379
396
|
# Rewrite the current display line or save it for final debugging result.
|
380
397
|
def display_line(line)
|
381
398
|
@display_line = line
|
382
|
-
unless @
|
399
|
+
unless @ping_from
|
383
400
|
# Display this current line.
|
384
401
|
STDOUT.write "\r" # Move to the start of this line.
|
385
402
|
STDOUT.write line # Write over it.
|
@@ -389,7 +406,7 @@ class WifiWatch
|
|
389
406
|
# If there is a current display line, commit it to history.
|
390
407
|
def commit_line()
|
391
408
|
if @display_line
|
392
|
-
if @
|
409
|
+
if @ping_from
|
393
410
|
# Debug mode show final line value as history.
|
394
411
|
puts @display_line
|
395
412
|
else
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
const http = require("http");
|
4
|
+
const Pinger = require("./pinger");
|
5
|
+
|
6
|
+
const pinger = Pinger();
|
7
|
+
pinger.start();
|
8
|
+
|
9
|
+
const server = http.createServer();
|
10
|
+
server.on("request", (req, res) => {
|
11
|
+
const start_time = Date.now();
|
12
|
+
if (req.url === "/summary") {
|
13
|
+
pinger.summary().pipe(res)
|
14
|
+
} else if (req.url === "/pings") {
|
15
|
+
pinger.pings().pipe(res)
|
16
|
+
} else if (req.url === "/stop") {
|
17
|
+
pinger.stop();
|
18
|
+
res.end("Stopped\n")
|
19
|
+
} else if (req.url === "/start") {
|
20
|
+
pinger.start();
|
21
|
+
res.end("Started\n")
|
22
|
+
} else {
|
23
|
+
res.end("Okay\n")
|
24
|
+
}
|
25
|
+
const end_time = Date.now();
|
26
|
+
console.log(`Ran ${req.url} in ${end_time - start_time} ms.`);
|
27
|
+
});
|
28
|
+
|
29
|
+
server.listen(3000);
|
@@ -0,0 +1,132 @@
|
|
1
|
+
/*
|
2
|
+
* Gather ping logs.
|
3
|
+
*
|
4
|
+
* import Pinger from "./pinger";
|
5
|
+
* pinger = Pinger();
|
6
|
+
* pinger.start({ count: 600, logs: 6 });
|
7
|
+
* ping_stream = pinger.ping_stream();
|
8
|
+
* ping_stream.pipe(process.stdout);
|
9
|
+
* pinger.stop();
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
|
13
|
+
const { spawn } = require("child_process");
|
14
|
+
const { Readable } = require('stream');
|
15
|
+
|
16
|
+
const Pinger = () => {
|
17
|
+
|
18
|
+
const default_options = {
|
19
|
+
host: "ns.google.com",
|
20
|
+
count: 600,
|
21
|
+
logs: 6
|
22
|
+
};
|
23
|
+
let options = default_options;
|
24
|
+
let ping_proc;
|
25
|
+
const ping_logs = [];
|
26
|
+
|
27
|
+
const start = (opts = {}) => {
|
28
|
+
if (!ping_proc) {
|
29
|
+
options = { ...default_options, ...opts};
|
30
|
+
run();
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
const stop = () => {
|
35
|
+
if (ping_proc) {
|
36
|
+
ping_proc.kill();
|
37
|
+
ping_proc = undefined;
|
38
|
+
ping_logs.splice(0, ping_logs.length);
|
39
|
+
}
|
40
|
+
};
|
41
|
+
|
42
|
+
const run = () => {
|
43
|
+
const ping_log = [];
|
44
|
+
let pushed = false;
|
45
|
+
|
46
|
+
// Spawn a ping process.
|
47
|
+
ping_proc = spawn("ping", [ "-c", options.count, options.host ]);
|
48
|
+
|
49
|
+
// Catch any errors and exit.
|
50
|
+
ping_proc.on("error", (err) => {
|
51
|
+
console.error("spawn ping:", err.code, err.path, err.spawnargs);
|
52
|
+
process.exit(2);
|
53
|
+
});
|
54
|
+
|
55
|
+
// On ping close start a new one.
|
56
|
+
ping_proc.on("close", () => {
|
57
|
+
ping_log.push("END_OF_PING\n");
|
58
|
+
if (ping_proc) {
|
59
|
+
run();
|
60
|
+
}
|
61
|
+
});
|
62
|
+
|
63
|
+
// Capture each new ping line.
|
64
|
+
ping_proc.stdout.on("data", (data) => {
|
65
|
+
now = Math.round(Date.now() / 1000);
|
66
|
+
data_s = data.toString().trim();
|
67
|
+
lines = data_s.split("\n");
|
68
|
+
lines.forEach( (line) => {
|
69
|
+
timed_line = `${now} ${line}\n`;
|
70
|
+
ping_log.push(timed_line);
|
71
|
+
});
|
72
|
+
|
73
|
+
// Now that we have some data remove old logs and append this log.
|
74
|
+
if (!pushed) {
|
75
|
+
while (ping_logs.length >= options.logs) {
|
76
|
+
ping_logs.shift();
|
77
|
+
}
|
78
|
+
ping_logs.push(ping_log);
|
79
|
+
pushed = true;
|
80
|
+
}
|
81
|
+
});
|
82
|
+
}
|
83
|
+
|
84
|
+
// Create a new ping log stream.
|
85
|
+
const pings = () => {
|
86
|
+
let next_log = 0;
|
87
|
+
|
88
|
+
const reader = new Readable({
|
89
|
+
read(size) {
|
90
|
+
// Get the next log.
|
91
|
+
ping_log = ping_logs[next_log];
|
92
|
+
if (ping_log == undefined) {
|
93
|
+
this.push(null);
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
next_log += 1;
|
97
|
+
|
98
|
+
// If there are multiple lines, compact them.
|
99
|
+
if (ping_log.length > 0) {
|
100
|
+
compacted = ping_log.join('');
|
101
|
+
ping_log.splice(0, ping_log.length, compacted);
|
102
|
+
}
|
103
|
+
|
104
|
+
// Send out the log.
|
105
|
+
this.push(ping_log[0]);
|
106
|
+
}
|
107
|
+
});
|
108
|
+
|
109
|
+
return reader;
|
110
|
+
}
|
111
|
+
|
112
|
+
// Create a new ping summary stream.
|
113
|
+
const summary = () => {
|
114
|
+
const wifi_watch = spawn("wifi-watch", ["--ping-from=-"]);
|
115
|
+
wifi_watch.on("error", (err) => {
|
116
|
+
console.error("spawn wifi-watch:", err.code, err.path, err.spawnargs);
|
117
|
+
process.exit(2);
|
118
|
+
});
|
119
|
+
|
120
|
+
pings().pipe(wifi_watch.stdin);
|
121
|
+
return wifi_watch.stdout;
|
122
|
+
};
|
123
|
+
|
124
|
+
return {
|
125
|
+
start: start,
|
126
|
+
stop: stop,
|
127
|
+
pings: pings,
|
128
|
+
summary: summary
|
129
|
+
};
|
130
|
+
};
|
131
|
+
|
132
|
+
module.exports = Pinger;
|
data/wifi-watch.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wifi-watch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Gorman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Run wifi-watch in a terminal so that you can easily check your network
|
14
14
|
quality at this moment and how it has been holding up since you began recording
|
@@ -35,6 +35,8 @@ files:
|
|
35
35
|
- test/ping_logs/fail-mode.log
|
36
36
|
- test/ping_logs/wifi-login.log
|
37
37
|
- test/run_tests
|
38
|
+
- wifi-service/index.js
|
39
|
+
- wifi-service/pinger.js
|
38
40
|
- wifi-watch.gemspec
|
39
41
|
homepage: https://github.com/jgorman/wifi-watch
|
40
42
|
licenses:
|