aboutsummaryrefslogtreecommitdiff
path: root/Readme.textile
blob: 320a09439add8ae2675d0cc4f04348ba76fc44f9 (plain)
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.