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
112
113
114
115
116
117
118
119
|
h1. Longboat
Longboat is a metric collection system. Intended for Viking, but theoretically generic.
It aggregates metrics collected by _raiders_, which are individual Ruby classes intended to gather and munge data from any source. It then present the data in Prometheus Exposition Format at a HTTP endpoint.
h2. Dependencies
Longboat depends on the @optimist@ and @sinatra@ gems (and optionally @thin@). You can install with gem or bundler in the usual ways.
bc. $ bundle install
h2. Usage
h3. Defaults
Longboat has some sensible defaults, so to get started pop your raiders in @lib/raiders@ and run:
bc. $ ./longboat
== Sinatra (v2.1.0) has taken the stage on 8564 for production with backup from Thin
Thin web server (v1.7.2 codename Bachmanity)
Maximum connections set to 1024
Listening on 127.0.0.1:8564, CTRL+C to stop
h3. Test
When testing new raiders, use the @--test@ flag. Rather than starting a web server and entering the raid loop, this will only run the raiders once then spit out the metrics on stdout:
bc. $ ./longboat --test
#HELP longboat_a_value A value specified at runtime
#TYPE longboat_a_value gauge
longboat_a_value{} 4 1604490345980
h3. Raider paths
Use @--raider-path@ to append a directory to the raider path. You can call this multiple times:
bc. $ ./longboat -a /some/global/raiders -a /some/more/raiders -a even_more_raiders
h2. Raiders
Raiders go out, raid things, and return to the longboat with metrics for the collector.
Longboat will pick up all raiders in the @lib/raiders@ directory by default.
h3. Raider structure
Each raider consists of:
* a file with a snake_case name, such as @my_raider.rb@
* containing a single class with a CamelCase name matching the file name, such as @MyRaider@
* with two methods:
** @initialize@, which takes two arguments of:
*** the collector to @report!@ the metrics to, and
*** a hash containing config relevant to raiders
** @raid@, no arguments, which triggers a raid and metric report
@Longboat::Collector#report!@ takes as arguments:
# The name of the metric
# The value of the metric
# Optionally, as a final hash:
#* @help@: The help string for the metric
#* @type@: The Prometheus type of the metric
#* @labels@: A hash containing the metric labels
#* @timestamp@: The timestamp when the metric was collected, defaults to the time @report!@ was called.
h4. Example
bc.. class Test
def initialize(collector, config)
@collector = collector
@config = config
end
def raid
# Do something useful
val = 4
# Clean up any previously reported metrics
# to prevent stale labelsets
@collector.redact!("value")
# Report new metrics
@collector.report!(
"value",
val,
help: "A fixed value",
type: "gauge",
labels: {
subvalue: 3
}
)
end
end
h3. Raider config
Longboat offers the @Longboat::Config.for_raider@ primitive to allow raiders to get command line arguments at runtime. It takes a block which is passed wholesale to @Optimist::Parser.new@, and returns a hash of parsed arguments. For more information see the "documentation":https://github.com/ManageIQ/optimist "for":https://www.manageiq.org/optimist/ "Optimist":https://github.com/ManageIQ/optimist/wiki.
Consider the following raider:
bc. class MyRaider
def initialize(collector, config)
@my_config = Longboat::Config.for_raider do
opt :myraider_an_argument, "An argument for myraider"
end
end
...
After calling longboat thusly:
bc. $ ./longboat --myraider-an-argument
The <code>@my_config</code> hash will look like:
bc. {:myraider_an_argument => true, :myraider_an_argument_given => true}
Be aware that there's no namespacing between raider arguments, so it's recommended that you prefix your argument with the raider's name, such as @--myraider-an-argument@. Also be aware that the automatic short-options are very likely to clash horribly, so try to avoid using these.
|