sensu-plugins-outlyer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []