sensu-plugins-outlyer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d9d39213feb78b60d5374d32eda1ad3020e11fda
4
+ data.tar.gz: 84a8a8cb10cfdbfe8e28280219e04b880244d6a2
5
+ SHA512:
6
+ metadata.gz: 416334263bc3660066faa32db08ce55ea2102591f458145398944de8af8896d50f3764a23c028b253fd3d96249e45f9c993b1036f0408e86c73d4cd1d8b1032d
7
+ data.tar.gz: 9e0c2857294938983196546d18fc94fc296157f1e507a685cc72d7dbc129af3bf43a0aefa3bab6c4f59608171b62ce590b28574e11605418a84a8e4db41f1d36
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ #Change Log
2
+ This project adheres to [Semantic Versioning](http://semver.org/).
3
+
4
+ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
5
+
6
+ ## 0.0.1 - 2018-07-12
7
+ ### Added
8
+ - initial release
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2018 Dataloop Software, INC. Trading as Outlyer
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ Outlyer Sensu Handler Integration
2
+ =================================
3
+
4
+ == Description ==
5
+
6
+ This integration provides instructions to install and use the Outlyer Sensu Handler Integration
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.
9
+
10
+ Once installed and enabled you should see all your check metrics and check status's in Outlyer to
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:
17
+
18
+ ```
19
+ <check_name>.<metric_name>
20
+ ```
21
+
22
+ In addition the status code of each check is sent as the `service.status` metric
23
+ to Outlyer with the label `service: <check_name>`. You will be able to use this
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:
35
+
36
+ ```bash
37
+ sensu-install outlyer
38
+ ```
39
+
40
+ Next, we’ll enable the handlers by adding it to `/etc/sensu/conf.d/outlyer-handlers.json`:
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.
65
+
66
+ Finally add your Outlyer API configuration at /etc/sensu/conf.d/outlyer.json:
67
+
68
+ ```json
69
+ {
70
+ "outlyer": {
71
+ "api_key": "<API_KEY>",
72
+ "account": "<ACCOUNT_NAME>",
73
+ "tags": []
74
+ }
75
+ }
76
+ ```
77
+
78
+ Where:
79
+
80
+ * **api_key**: Your user's API key generated under user settings
81
+ * **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)
82
+ * **tags**: An array of tags you want to add to all your metrics from Sensu, i.e. region: us-west-1
83
+
84
+ Finally restart your Sensu server so the new handler is enabled:
85
+
86
+ ```bash
87
+ sudo systemctl restart sensu-{server,api}
88
+ ```
89
+
90
+ You will need to add the handler to all the checks you want metrics sent to Outlyer for by adding
91
+ `outlyer-nagios` or `outlyer-graphite` to your check handlers configuration as appropriate. Once
92
+ your checks have been configured to use the Outlyer handler you should start seeing all your
93
+ metrics from your configured Sensu checks appearing in Outlyer shortly afterwards.
94
+
95
+ Please read the Metrics Collected section of this guide to understand how your check metrics
96
+ are sent to Outlyer.
97
+
98
+ == Changelog ==
99
+
100
+ |Version|Release Date|Description |
101
+ |-------|------------|-----------------------------------------------------|
102
+ |1.0 |12-Jul-2018 |Initial version of the Outlyer Sensu Handler. |
@@ -0,0 +1,196 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # outlyer-metrics
4
+ #
5
+ # DESCRIPTION:
6
+ # Pushes metrics from Sensu Nagios Checks and Sensu Graphite Metric Checks
7
+ # to Outlyer. Will also send the check status as an additional `service.status`
8
+ # metric with label `check: sensu.<check_name>` so you can create status alerts and
9
+ # dashboard widgets for the check in Outlyer.
10
+ #
11
+ # OUTPUT:
12
+ # metric data
13
+ #
14
+ # PLATFORMS:
15
+ # Linux
16
+ #
17
+ # DEPENDENCIES:
18
+ # gem: sensu-handler
19
+ #
20
+ # USAGE:
21
+ # Takes the following optional parameters:
22
+ #
23
+ # -f: set the Handler's check output format to parse. Can either be `graphite` (default) or `nagios`.
24
+ # -t: Set the timeout in seconds for the Outlyer API requests
25
+ #
26
+ # NOTES:
27
+ #
28
+ # LICENSE:
29
+ # Copyright 2018 Dataloop Software, INC. trading as Outlyer (https://www.outlyer.com)
30
+ # Released under the same terms as Sensu (the MIT license); see LICENSE for details.
31
+ #
32
+
33
+ require 'sensu-handler'
34
+ require 'net/https'
35
+ require 'uri'
36
+ require 'json'
37
+
38
+ #
39
+ # Outlyer Metrics
40
+ #
41
+ class OutlyerMetrics < Sensu::Handler
42
+
43
+ option :output_format,
44
+ description: 'Output format of checks to process: graphite (default) or nagios',
45
+ short: '-f FORMAT',
46
+ long: '--format FORMAT',
47
+ default: 'graphite'
48
+
49
+ option :api_timeout,
50
+ description: 'The timeout in seconds for Outlyer API Requests',
51
+ short: '-t TIMEOUT',
52
+ long: '--timeout TIMEOUT',
53
+ default: '5'
54
+
55
+ # Override filters from Sensu::Handler.
56
+ # They are not appropriate for metric handlers
57
+ #
58
+ def filter
59
+ end
60
+
61
+ # Create a handle and event set
62
+ #
63
+ def handle
64
+
65
+ output = @event['check']['output']
66
+ check_status = @event['check']['status'].to_f
67
+ @check_name = @event['check']['name']
68
+ @host = @event['client']['name']
69
+ @environment = @event['client']['environment']
70
+ timestamp = @event['check']['executed'].to_i * 1000
71
+
72
+ # Uncomment this line for local testing outside Sensu
73
+ #@settings = { "outlyer" => {"account" => "", "api_key" => ""}}
74
+
75
+ # Parse output for metric data
76
+ metrics = if config[:output_format] == 'nagios' then
77
+ parse_nagios_output(output, timestamp)
78
+ else
79
+ parse_graphite_output(output)
80
+ end
81
+
82
+ # Add a service status metric
83
+ metrics.push(create_datapoint('service.status', check_status, timestamp, {service: "sensu.#{@check_name}"}))
84
+ puts metrics
85
+ # Post metrics to Outlyer
86
+ push_metrics(metrics)
87
+ end
88
+
89
+ # Create a single data point
90
+ #
91
+ # @param name [String] metric name
92
+ # @param value [Float] metric value
93
+ # @param time [Integer] epoch timestamp of metric in milliseconds
94
+ # @param labels [HashMap] (Optional) Additional labels to append to data point
95
+ #
96
+ def create_datapoint(name, value, time, labels = nil)
97
+ datapoint = {
98
+ host: @host,
99
+ labels: {
100
+ environment: @environment,
101
+ },
102
+ name: name,
103
+ timestamp: time,
104
+ type: 'gauge',
105
+ value: value
106
+ }
107
+ datapoint[:labels].merge!(labels) unless labels.nil?
108
+ datapoint
109
+ end
110
+
111
+ # Parse the Nagios output format:
112
+ # <message> | <metric path 1>=<metric value 1>, <metric path 2>=<metric value 2>...
113
+ #
114
+ # @param output [String] The full check output
115
+ # @param timestamp[Integer] The epoch timestamp in milliseconds the check was executed
116
+ #
117
+ def parse_nagios_output(output, timestamp)
118
+ data = []
119
+ parts = output.strip.split('|')
120
+
121
+ if parts.length < 2
122
+ # No performance data
123
+ return data
124
+ end
125
+
126
+ parts[1].strip.split.each do |metric|
127
+ metric_parts = metric.strip.split('=')
128
+ begin
129
+ name = metric_parts[0]
130
+ value = metric_parts[1].split(";")[0].to_f
131
+ data.push(create_datapoint(@check_name + '.' + name, value, timestamp))
132
+ rescue => error
133
+ # Raised when any metrics could not be parsed
134
+ puts "[OutlyerHandler] The Nagios metric '#{metric}' could not be parsed: #{error.message}"
135
+ end
136
+ end
137
+ data
138
+ end
139
+
140
+ # Parse the graphite output format:
141
+ # <metric path> <metric value> <metric timestamp>\n
142
+ #
143
+ # Each metric is separated by a newline character in the body
144
+ #
145
+ # @param output [String] The full check output
146
+ #
147
+ def parse_graphite_output(output)
148
+ data = []
149
+ output.split("\n").each do |metric|
150
+ m = metric.split
151
+ next unless m.count == 3
152
+ name = m[0].split('.', 2)[1]
153
+ value = m[1].to_f
154
+ time = m[2].to_i * 1000
155
+ point = create_datapoint(@check_name + '.' + name, value, time)
156
+ data.push(point)
157
+ end
158
+ data
159
+ end
160
+
161
+ # Post check metrics to Outlyer's Series API:
162
+ #
163
+ # POST https://api2.outlyer.com/v2/accounts/{account}/series
164
+ #
165
+ # @param datapoints [Object] Array of data points
166
+ #
167
+ def push_metrics(datapoints)
168
+ Timeout.timeout(config[:api_timeout].to_i) do
169
+ uri = URI.parse("https://api2.outlyer.com/v2/accounts/#{settings['outlyer']['account']}/series")
170
+
171
+ # Create the HTTP objects
172
+ http = Net::HTTP.new(uri.host, uri.port)
173
+ http.use_ssl = true
174
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
175
+ request = Net::HTTP::Post.new(uri.request_uri)
176
+ request.add_field("Authorization", "Bearer #{settings['outlyer']['api_key']}")
177
+ request.add_field("accept", "application/json")
178
+ request.add_field("Content-Type", "application/json")
179
+ request.body = {samples: datapoints}.to_json
180
+
181
+ # Send the request
182
+ response = http.request(request)
183
+ if response.code.to_i != 200
184
+ puts "[OutlyerHandler] Outlyer API Error -- API responded with status code " + response.code
185
+ puts response.body
186
+ end
187
+ end
188
+ # Raised when any metrics could not be sent
189
+ #
190
+ rescue Timeout::Error
191
+ puts '[OutlyerHandler] Outlyer API Error -- timed out while sending metrics'
192
+ rescue => error
193
+ puts "[OutlyerHandler] Outlyer API Error -- failed to send metrics: #{error.message}"
194
+ puts " #{error.backtrace.join("\n\t")}"
195
+ end
196
+ end
@@ -0,0 +1,9 @@
1
+ module SensuPluginsOutlyer
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 0
6
+
7
+ VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require 'sensu-plugins-outlyer/version'
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sensu-plugins-outlyer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dataloop Software, INC. Trading as Outlyer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-07-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sensu-plugin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: codeclimate-test-reporter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: github-markup
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.10'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: redcarpet
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.2'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.40.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.40.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.4'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.4'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.8'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.8'
153
+ description: Sensu plugins for Outlyer
154
+ email: "<support@outlyer.com>"
155
+ executables:
156
+ - outlyer-metrics.rb
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - CHANGELOG.md
161
+ - LICENSE
162
+ - README.md
163
+ - bin/outlyer-metrics.rb
164
+ - lib/sensu-plugins-outlyer.rb
165
+ - lib/sensu-plugins-outlyer/version.rb
166
+ homepage: https://www.outlyer.com
167
+ licenses:
168
+ - MIT
169
+ metadata:
170
+ maintainer: outlyer
171
+ development_status: unmaintained
172
+ production_status: unstable - testing recommended
173
+ release_draft: 'false'
174
+ release_prerelease: 'false'
175
+ post_install_message: You can use the embedded Ruby by setting EMBEDDED_RUBY=true
176
+ in /etc/default/sensu
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: 2.0.0
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubyforge_project:
192
+ rubygems_version: 2.5.2
193
+ signing_key:
194
+ specification_version: 4
195
+ summary: Sensu plugins for Outlyer
196
+ test_files: []