sensu-plugins-outlyer 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -4
- data/README.md +24 -90
- data/bin/outlyer-metrics.rb +88 -17
- data/lib/sensu-plugins-outlyer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06fefcec9b4ad9d5c308b13f85f547b0bd4b8b53
|
4
|
+
data.tar.gz: e2b9db23d1252b2eeb1874eb3fd13a5c5290af91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2219ff7def5ba400bac2ed178d395ce94d786b95b3dc2102a5a86f5ae7c4c440fc0bfa7476ae663597425cea75f46ddd0d852b3c46804fa13555f8063be44da4
|
7
|
+
data.tar.gz: 680a766582636eaf7b826bc8b7eccee35967b66c99ac98804cd9da1a5d039d6c247c740d67eb29e50cd7956a52419a4a75095fbefb9d31ac6f77bce001917113
|
data/CHANGELOG.md
CHANGED
@@ -3,10 +3,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
3
3
|
|
4
4
|
This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
|
5
5
|
|
6
|
-
## 0.
|
7
|
-
|
6
|
+
## [0.4.0] - 2018-07-13
|
7
|
+
- Added handling for client environments set as array of values
|
8
|
+
- Added schemas so graphite metric names can be parsed into dimensional metrics
|
9
|
+
- Added debug option
|
10
|
+
|
11
|
+
## [0.3.0] - 2018-07-13
|
8
12
|
- Better logging
|
9
13
|
|
10
|
-
## 0.1.0 - 2018-07-12
|
11
|
-
### Added
|
14
|
+
## [0.1.0] - 2018-07-12
|
12
15
|
- initial release
|
data/README.md
CHANGED
@@ -1,113 +1,47 @@
|
|
1
|
-
|
2
|
-
=================================
|
1
|
+
# Sensu Outlyer Handler Plugin
|
3
2
|
|
4
|
-
|
3
|
+
This readme includes development instructions for building, packaging and testing the Sensu plugin in Ruby.
|
5
4
|
|
6
|
-
|
7
|
-
to push all your check event metrics and check status's from Sensu checks into Outlyer. It supports
|
8
|
-
both Nagios checks and Graphite Metric check outputs from Sensu.
|
5
|
+
## Packaging and Publishing
|
9
6
|
|
10
|
-
|
11
|
-
use on custom dashboards and alerts.
|
12
|
-
|
13
|
-
== Metrics Collected ==
|
14
|
-
|
15
|
-
The Sensu integration will push any metric collected by your Sensu checks with metric
|
16
|
-
names namespaced to the check name as follows:
|
7
|
+
First build the gem:
|
17
8
|
|
18
9
|
```
|
19
|
-
|
10
|
+
gem build sensu-plugins-outlyer.gemspec
|
20
11
|
```
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
metric to configure dashboad status widgets and service check alerts in Outlyer.
|
25
|
-
|
26
|
-
For Nagios checks, the timestamp of when the check was executed is used for all the
|
27
|
-
metric data points. For Graphite metric checks the timestamp of each metric data
|
28
|
-
point is used, apart from the service.status which uses the check execution time
|
29
|
-
like Nagios checks.
|
30
|
-
|
31
|
-
== Installation ==
|
32
|
-
|
33
|
-
Firstly install the Outlyer Sensu plugin on your Sensu machine(s) using the following
|
34
|
-
command:
|
13
|
+
Then publish the sensu-plugins-outlyer gem to the Outlyer account on the RubyGems server
|
14
|
+
using the following command:
|
35
15
|
|
36
16
|
```bash
|
37
|
-
sensu-
|
17
|
+
gem push sensu-plugins-outlyer-<version_number>.gem
|
38
18
|
```
|
39
19
|
|
40
|
-
|
41
|
-
|
42
|
-
```json
|
43
|
-
{
|
44
|
-
"handlers": {
|
45
|
-
"outlyer-graphite": {
|
46
|
-
"type": "pipe",
|
47
|
-
"command": "/opt/sensu/embedded/bin/outlyer-metrics.rb"
|
48
|
-
},
|
49
|
-
"outlyer-nagios": {
|
50
|
-
"type": "pipe",
|
51
|
-
"command": "/opt/sensu/embedded/bin/outlyer-metrics.rb -f nagios"
|
52
|
-
}
|
53
|
-
}
|
54
|
-
}
|
55
|
-
```
|
56
|
-
|
57
|
-
Two handlers have been configured, one for your Nagios checks `outlyer-nagios` and
|
58
|
-
one for your Graphite metric checks `outlyer-graphite`. You can refer to these handlers
|
59
|
-
in your check configurations to ensure they are handled by the Outlyer handler with
|
60
|
-
the correct check output parsing.
|
61
|
-
|
62
|
-
You can also add the optional `-t` parameter to the handler command to change the default
|
63
|
-
timeout for Outlyer API requests from 5 seconds. This is useful if you notice the handler
|
64
|
-
timing out as your checks send more metrics creating larger payloads.
|
20
|
+
## Testing
|
65
21
|
|
66
|
-
|
22
|
+
First copy the example config file under `test/test-config.json` to a path outside your
|
23
|
+
project and set the account and your API key in the new file. Then set the path to your
|
24
|
+
handler configuration file with your API details as an environment variable:
|
67
25
|
|
68
|
-
```
|
69
|
-
|
70
|
-
"outlyer": {
|
71
|
-
"api_key": "<API_KEY>",
|
72
|
-
"account": "<ACCOUNT_NAME>"
|
73
|
-
}
|
74
|
-
}
|
26
|
+
```bash
|
27
|
+
export SENSU_CONFIG_FILES='/Users/dgildeh/Development/Outlyer/sensu-config.json'
|
75
28
|
```
|
76
29
|
|
77
|
-
|
78
|
-
|
79
|
-
* **api_key**: Your user's API key generated under user settings
|
80
|
-
* **account**: The unique account name of the account you want to push metrics too (you will see this in the URL when using the app)
|
81
|
-
|
82
|
-
Finally restart your Sensu server so the new handler is enabled:
|
30
|
+
Then you can use the following command to test the handler with example Nagios
|
31
|
+
output data using the following command:
|
83
32
|
|
84
33
|
```bash
|
85
|
-
|
34
|
+
cat ./test/test-nagios-data.json | ruby ./bin/outlyer-metrics.rb -f nagios
|
86
35
|
```
|
87
|
-
|
88
|
-
You will need to add the handler to all the checks you want metrics sent to Outlyer for by adding
|
89
|
-
`outlyer-nagios` or `outlyer-graphite` to your check handlers configuration as appropriate. Once
|
90
|
-
your checks have been configured to use the Outlyer handler you should start seeing all your
|
91
|
-
metrics from your configured Sensu checks appearing in Outlyer shortly afterwards.
|
92
|
-
|
93
|
-
Also ensure any Sensu checks that send metrics have type `metric` otherwise the output will not
|
94
|
-
be processed everytime the check runs.
|
95
|
-
|
96
|
-
Please read the Metrics Collected section of this guide to understand how your check metrics
|
97
|
-
are sent to Outlyer.
|
98
|
-
|
99
|
-
## Troubleshooting
|
100
|
-
|
101
|
-
If you don't see metrics appearing in Outlyer after enabling the handlers and checks
|
102
|
-
you should use the following command to view the Sensu server logs to see if any
|
103
|
-
errors are being output by the hander:
|
36
|
+
For Graphite metric test:
|
104
37
|
|
105
38
|
```bash
|
106
|
-
|
39
|
+
cat ./test/test-graphite-data.json | ruby ./bin/outlyer-metrics.rb
|
107
40
|
```
|
108
41
|
|
109
|
-
|
42
|
+
Note you will have to override the check timestamp to the current time so your
|
43
|
+
metrics will appear in Outlyer using the test above:
|
110
44
|
|
111
|
-
|
112
|
-
|
113
|
-
|
45
|
+
```ruby
|
46
|
+
timestamp = Time.now.to_i * 1000
|
47
|
+
```
|
data/bin/outlyer-metrics.rb
CHANGED
@@ -51,6 +51,12 @@ class OutlyerMetrics < Sensu::Handler
|
|
51
51
|
short: '-t TIMEOUT',
|
52
52
|
long: '--timeout TIMEOUT',
|
53
53
|
default: '5'
|
54
|
+
|
55
|
+
option :debug,
|
56
|
+
description: 'Enable debug for more verbose output',
|
57
|
+
short: '-d DEBUG',
|
58
|
+
long: '--debug DEBUG',
|
59
|
+
default: 'false'
|
54
60
|
|
55
61
|
# Override filters from Sensu::Handler.
|
56
62
|
# They are not appropriate for metric handlers
|
@@ -62,16 +68,22 @@ class OutlyerMetrics < Sensu::Handler
|
|
62
68
|
#
|
63
69
|
def handle
|
64
70
|
|
71
|
+
@debug = false
|
72
|
+
if config[:debug] == 'true'
|
73
|
+
@debug = true
|
74
|
+
end
|
75
|
+
|
65
76
|
output = @event['check']['output']
|
66
77
|
check_status = @event['check']['status'].to_f
|
67
78
|
@check_name = @event['check']['name']
|
68
|
-
@host = @event['client']['name']
|
79
|
+
@host = @event['client']['name'].strip.to_s
|
69
80
|
@environment = @event['client']['environment']
|
81
|
+
if @environment.kind_of?(Array)
|
82
|
+
# environment can be an array, so merge values with hyphens
|
83
|
+
@environment = @environment.join("-")
|
84
|
+
end
|
70
85
|
timestamp = @event['check']['executed'].to_i * 1000
|
71
86
|
|
72
|
-
# Uncomment this line for local testing outside Sensu
|
73
|
-
#@settings = { "outlyer" => {"account" => "", "api_key" => ""}}
|
74
|
-
|
75
87
|
# Parse output for metric data
|
76
88
|
metrics = if config[:output_format] == 'nagios' then
|
77
89
|
parse_nagios_output(output, timestamp)
|
@@ -80,7 +92,7 @@ class OutlyerMetrics < Sensu::Handler
|
|
80
92
|
end
|
81
93
|
|
82
94
|
# Add a service status metric
|
83
|
-
metrics.push(create_datapoint('service.status', check_status, timestamp, {service: "sensu.#{@check_name}"}))
|
95
|
+
metrics.push(create_datapoint('service.status', check_status, timestamp, {service: "sensu.#{sanitize_value(@check_name)}"}))
|
84
96
|
# Post metrics to Outlyer
|
85
97
|
push_metrics(metrics)
|
86
98
|
end
|
@@ -127,10 +139,11 @@ class OutlyerMetrics < Sensu::Handler
|
|
127
139
|
begin
|
128
140
|
name = metric_parts[0]
|
129
141
|
value = metric_parts[1].split(";")[0].to_f
|
130
|
-
|
142
|
+
labels = {service: "sensu.#{sanitize_value(@check_name)}"}
|
143
|
+
data.push(create_datapoint(name, value, timestamp, labels))
|
131
144
|
rescue => error
|
132
145
|
# Raised when any metrics could not be parsed
|
133
|
-
puts "
|
146
|
+
puts "The Nagios metric '#{metric}' could not be parsed: #{error.message}"
|
134
147
|
end
|
135
148
|
end
|
136
149
|
data
|
@@ -145,17 +158,71 @@ class OutlyerMetrics < Sensu::Handler
|
|
145
158
|
#
|
146
159
|
def parse_graphite_output(output)
|
147
160
|
data = []
|
161
|
+
|
162
|
+
# Get Scheme to parse Graphite metrics if exists
|
163
|
+
scheme = nil
|
164
|
+
if settings['outlyer'].key?('schemes') && settings['outlyer']['schemes'] != nil
|
165
|
+
if settings['outlyer']['schemes'].key?(@check_name)
|
166
|
+
scheme = settings['outlyer']['schemes'][@check_name]
|
167
|
+
else
|
168
|
+
# Get default scheme if check specific scheme not defined
|
169
|
+
scheme = settings['outlyer']['schemes']['default']
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Parse the metric on each line in graphite format
|
148
174
|
output.split("\n").each do |metric|
|
149
175
|
m = metric.split
|
150
176
|
next unless m.count == 3
|
151
|
-
name
|
177
|
+
# Get name and extract labels - we remove hostname if in metric name
|
178
|
+
# as it contains dots and breaks parsing
|
179
|
+
metric_parts = m[0].gsub("#{@host}", 'host').split('.')
|
180
|
+
labels = {service: "sensu.#{sanitize_value(@check_name)}"}
|
181
|
+
if scheme
|
182
|
+
metric_name = metric_parts.last(scheme['metric_name_length'].to_i).join('.')
|
183
|
+
# Get dimensions from metric name
|
184
|
+
schema_parts = scheme['scheme'].split('.')
|
185
|
+
if (metric_parts.length - scheme['metric_name_length'].to_i) != schema_parts.length
|
186
|
+
puts "Schema Parsing Error: metric parts (#{metric_parts.length - scheme['metric_name_length'].to_i}) is not same length as schema (#{schema_parts.length})"
|
187
|
+
puts "Example metric: m[0]"
|
188
|
+
return []
|
189
|
+
end
|
190
|
+
schema_parts.each_with_index do |val,index|
|
191
|
+
if val != 'host' && val != 'hostname' && val != 'name'
|
192
|
+
labels.merge!(Hash[sanitize_value(val, 40),sanitize_value(metric_parts[index])])
|
193
|
+
end
|
194
|
+
end
|
195
|
+
else
|
196
|
+
metric_name = sanitize_value(metric_parts.join('.'))
|
197
|
+
end
|
152
198
|
value = m[1].to_f
|
153
|
-
time =
|
154
|
-
point = create_datapoint(
|
199
|
+
time = Time.now.to_i * 1000
|
200
|
+
point = create_datapoint(metric_name, value, time, labels)
|
155
201
|
data.push(point)
|
156
202
|
end
|
157
203
|
data
|
158
204
|
end
|
205
|
+
|
206
|
+
# Ensures all label values conform to Outlyer's data format requirements:
|
207
|
+
#
|
208
|
+
# * values can only contain the characters `-._A-Za-z0-9`, other characters
|
209
|
+
# will be replaced by underscore including spaces
|
210
|
+
# * values can only be 80 characters or less
|
211
|
+
#
|
212
|
+
# @param value [String] The value to sanitize
|
213
|
+
# @param max_length [Integer] The maximum length of string, default 80
|
214
|
+
#
|
215
|
+
def sanitize_value(value, max_length = 80)
|
216
|
+
if !value
|
217
|
+
return ''
|
218
|
+
end
|
219
|
+
value = value.gsub(/[^-._A-Za-z0-9]/i, '_').downcase
|
220
|
+
if value.length > max_length
|
221
|
+
puts "Warning: value '#{value}' is greater than 80 characters and will be truncated to last 80 characters"
|
222
|
+
value = value.split(//).last(max_length).join
|
223
|
+
end
|
224
|
+
value
|
225
|
+
end
|
159
226
|
|
160
227
|
# Post check metrics to Outlyer's Series API:
|
161
228
|
#
|
@@ -166,7 +233,7 @@ class OutlyerMetrics < Sensu::Handler
|
|
166
233
|
def push_metrics(datapoints)
|
167
234
|
Timeout.timeout(config[:api_timeout].to_i) do
|
168
235
|
uri = URI.parse("https://api2.outlyer.com/v2/accounts/#{settings['outlyer']['account']}/series")
|
169
|
-
|
236
|
+
|
170
237
|
# Create the HTTP objects
|
171
238
|
http = Net::HTTP.new(uri.host, uri.port)
|
172
239
|
http.use_ssl = true
|
@@ -176,13 +243,17 @@ class OutlyerMetrics < Sensu::Handler
|
|
176
243
|
request.add_field("accept", "application/json")
|
177
244
|
request.add_field("Content-Type", "application/json")
|
178
245
|
request.body = {samples: datapoints}.to_json
|
179
|
-
|
246
|
+
|
247
|
+
if @debug
|
248
|
+
puts "DEBUG: Outlyer API Payload: #{request.body}"
|
249
|
+
end
|
250
|
+
|
180
251
|
# Send the request
|
181
252
|
response = http.request(request)
|
182
253
|
if response.code.to_i != 200
|
183
|
-
puts "
|
184
|
-
puts "
|
185
|
-
puts "
|
254
|
+
puts "Outlyer API Error -- API responded with status code #{response.code}"
|
255
|
+
puts "Outlyer API Response: #{response.body}"
|
256
|
+
puts "Outlyer API Request Body: #{request.body}"
|
186
257
|
return
|
187
258
|
end
|
188
259
|
puts "Successfully pushed #{datapoints.length} metrics to Outlyer"
|
@@ -190,9 +261,9 @@ class OutlyerMetrics < Sensu::Handler
|
|
190
261
|
# Raised when any metrics could not be sent
|
191
262
|
#
|
192
263
|
rescue Timeout::Error
|
193
|
-
puts '
|
264
|
+
puts 'Outlyer API Error -- timed out while sending metrics'
|
194
265
|
rescue => error
|
195
|
-
puts "
|
266
|
+
puts "Outlyer API Error -- failed to send metrics: #{error.message}"
|
196
267
|
puts " #{error.backtrace.join("\n\t")}"
|
197
268
|
end
|
198
269
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu-plugins-outlyer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dataloop Software, INC. Trading as Outlyer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sensu-plugin
|