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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
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.
For gauges and counters, the value is simply the vale of the metric.
For histograms, the value is a hash containing:
* @buckets@: A hash mapping the upper bound to the number of observations in the bucket
* @count@: The total number of observations
* @sum@: The sum of all observations
For summaries, the value is a hash containing:
* @quantiles@: A hash mapping the quantile to the value
* @count@: The total number of observations
* @sum@: The sum of all observations
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.
|