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
|
# tickwatch
# Author: Euxane TRAN-GIRARD
# Licence: EUPL-1.2
import std/sugar
import std/math
import std/times
import std/net
import std/posix
import std/paths
import std/strutils
import std/parseopt
import file
import ping
import logger
const
NAME = "tickwatch"
VERSION = staticExec("""
command -v git >/dev/null && git describe --tags --always || echo $VERSION
""").strip()
HELP_TEXT =
staticRead("readme.md")
.split("```helptext", 1)[1]
.split("```", 1)[0]
.strip()
proc registerTerminationHandlers() =
proc terminationHandler(sig: cint) {.noconv.} = flushAndQuit()
var action = SigAction(sa_handler: terminationHandler)
for signal in [SIGTERM, SIGHUP, SIGQUIT, SIGINT]:
discard sigaction(signal, action)
proc main() =
var
scale: Scale = log2
symbols = UNICODE_SYMBOLS
(min, max) = (0, 1000)
probe: (timeout: Duration) -> int
for optKind, key, val in getopt():
if optKind notin {cmdLongOption, cmdShortOption}:
raise newException(ValueError, "Invalid argument: " & key)
case key:
of "help", "h":
echo HELP_TEXT
quit(0)
of "version", "v":
echo NAME & " " & VERSION
quit(0)
of "scale":
case val:
of "logarithmic", "log", "log2": scale = log2
of "log10": scale = log10
of "ln": scale = ln
of "linear", "lin": scale = (val: float) => val
of "symbols":
case val:
of "unicode", "utf8", "utf-8": symbols = UNICODE_SYMBOLS
of "numeric", "ascii": symbols = NUMERIC_SYMBOLS
of "min": min = parseInt(val)
of "max": max = parseInt(val)
of "ping":
let targetIp = resolve(val)
let mon = initPingMonitor(targetIp, procIdent())
probe = (timeout: Duration) => mon.ping(timeout).inMilliseconds.int
of "value":
let mon = initFileValueMonitor(Path val)
probe = (timeout: Duration) => mon.readValue()
of "change":
let mon = initFileChangeMonitor(Path val)
probe = (timeout: Duration) => mon.readValue()
if probe == nil:
raise newException(ValueError, "Missing monitor argument")
loop(probe, (val: int) => symbols.indicator(min, max, val, scale))
when not defined(test):
try:
registerTerminationHandlers()
main()
except CatchableError as err:
stderr.writeLine err.msg
quit(1)
|