sensu-extensions-graphite 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20e5033101eebbf77f983701353d0c687c986ac1
4
- data.tar.gz: 8613bc14341c7f02a97a4ecbd2e19c7b23659709
3
+ metadata.gz: d1d8587d5770be44d412655c81f21444ac88223e
4
+ data.tar.gz: 7c763e16d03096b7af47314fbf0860a255780bc7
5
5
  SHA512:
6
- metadata.gz: eaae41d8d0a45a4127e7e71a7eb241330e59438446420bb3ed9cde1498e2765a02031b214f78497e6158e590df8c22e235d0545c8e4459bde90bb6ff49bf3195
7
- data.tar.gz: 660a6799d4ea65dd9de23eb1575f2817c4b990ccf5b1136afb5de4b770cee4631f6e0f8d0da7aa8ef5523cb868d26fef8cb9efe0c2e4f600abac1b4d2bc442bc
6
+ metadata.gz: d2e236edd197147bacca5b22ee83f082597b510e9cc36dc1a2ec735d2110fd0fb191d140917f431c997fe5a8665b8cc5e7ccbc2dbd7a39152165d10b5c892545
7
+ data.tar.gz: 86cf8ce0812d543243957daefdb65a76b6751a106f3960fa3417b4994e219d9f3d07c5a82dc8d9486081f639c8980ce75f6892e0c6e89efbe13b821605ffda62
data/README.md CHANGED
@@ -1,2 +1,11 @@
1
- # Sensu::Extensions::Graphite
1
+ # Sensu::Extensions::Template
2
2
 
3
+ Welcome to the Sensu Extensions repository template! In this repository, you will find the files you need to be able to author your own Sensu Extension for Sensu Core (>= 0.26).
4
+
5
+ ## Usage
6
+
7
+ 1. Fork this repository and name the fork after your new extension, e.g. `"sensu-extensions-docker"`
8
+
9
+ 2. Write your extension (with tests!)
10
+
11
+ 3. Create a GitHub issue on [sensu-extensions/template](https://github.com/sensu-extensions/template/issues) to request a review of your extension, to determine if it is ready to be moved to the [sensu-extensions GitHub organization](https://github.com/sensu-extensions) to be shared with the Sensu community!
@@ -2,19 +2,238 @@ require "sensu/extension"
2
2
 
3
3
  module Sensu
4
4
  module Extension
5
- class Template < Handler
6
- def name
7
- "graphite"
5
+
6
+ ######################################
7
+ # ExponentialDecayTimer
8
+ #
9
+ # Implement an exponential backoff timer for reconnecting to metrics
10
+ # backends.
11
+ ######################################
12
+ class ExponentialDecayTimer
13
+ attr_accessor :reconnect_time
14
+
15
+ def initialize
16
+ @reconnect_time = 0
17
+ end
18
+
19
+ def get_reconnect_time(max_reconnect_time, connection_attempt_count)
20
+ if @reconnect_time < max_reconnect_time
21
+ seconds = @reconnect_time + (2**(connection_attempt_count - 1))
22
+ seconds = seconds * (0.5 * (1.0 + rand))
23
+ @reconnect_time = if seconds <= max_reconnect_time
24
+ seconds
25
+ else
26
+ max_reconnect_time
27
+ end
28
+ end
29
+ @reconnect_time
30
+ end
31
+ end
32
+
33
+ #########################################
34
+ # Connection Handler
35
+ #########################################
36
+ class ConnectionHandler < EM::Connection
37
+
38
+ # XXX: These should be runtime configurable.
39
+ MAX_RECONNECT_ATTEMPTS = 0 # Attempt no reconnects. Drop if it can't in favor for speed.
40
+ MAX_RECONNECT_TIME = 0 # seconds
41
+
42
+ attr_accessor :message_queue, :connection_pool
43
+ attr_accessor :name, :host, :port, :connected
44
+ attr_accessor :reconnect_timer
45
+
46
+ # ignore :reek:TooManyStatements
47
+ def post_init
48
+ @is_closed = false
49
+ @connection_attempt_count = 0
50
+ @max_reconnect_time = MAX_RECONNECT_TIME
51
+ @comm_inactivity_timeout = 0 # disable inactivity timeout
52
+ @pending_connect_timeout = 30 # seconds
53
+ @reconnect_timer = ExponentialDecayTimer.new
54
+ end
55
+
56
+ def connection_completed
57
+ @connected = true
58
+ end
59
+
60
+ def close_connection(*args)
61
+ @is_closed = true
62
+ @connected = false
63
+ super(*args)
64
+ end
65
+
66
+ def comm_inactivity_timeout
67
+ logger.info("Graphite: Connection to #{@name} timed out.")
68
+ schedule_reconnect
69
+ end
70
+
71
+ def unbind
72
+ @connected = false
73
+ unless @is_closed
74
+ logger.info('Graphite: Connection closed unintentionally.')
75
+ schedule_reconnect
76
+ end
77
+ end
78
+
79
+ def send_data(*args)
80
+ super(*args)
81
+ end
82
+
83
+ # Override EM::Connection.receive_data to prevent it from calling
84
+ # puts and randomly logging non-sense to sensu-server.log
85
+ def receive_data(data)
86
+ end
87
+
88
+ # Reconnect normally attempts to connect at the end of the tick
89
+ # Delay the reconnect for some seconds.
90
+ def reconnect(time)
91
+ EM.add_timer(time) do
92
+ logger.info("Graphite: Attempting to reconnect relay channel: #{@name}.")
93
+ super(@host, @port)
94
+ end
95
+ end
96
+
97
+ def get_reconnect_time
98
+ @reconnect_timer.get_reconnect_time(
99
+ @max_reconnect_time,
100
+ @connection_attempt_count
101
+ )
102
+ end
103
+
104
+ def schedule_reconnect
105
+ unless @connected
106
+ @connection_attempt_count += 1
107
+ reconnect_time = get_reconnect_time
108
+ logger.info("Graphite: Scheduling reconnect in #{@reconnect_time} seconds for relay channel: #{@name}.")
109
+ reconnect(reconnect_time)
110
+ end
111
+ reconnect_time
112
+ end
113
+
114
+ def logger
115
+ Sensu::Logger.get
116
+ end
117
+
118
+ end # ConnectionHandler
119
+
120
+ ##########################################
121
+ # EndPoint
122
+ # An endpoint is a backend metric store. This is a compositional object
123
+ # to help keep the rest of the code sane.
124
+ ##########################################
125
+ class Endpoint
126
+
127
+ # EM::Connection.send_data batches network connection writes in 16KB
128
+ # We should start out by having all data in the queue flush in the
129
+ # space of a single loop tick.
130
+ MAX_QUEUE_SIZE = 2048
131
+
132
+ attr_accessor :connection, :queue
133
+
134
+ def initialize(name, host, port)
135
+ @queue = []
136
+ @connection = EM.connect(host, port, ConnectionHandler)
137
+ @connection.name = name
138
+ @connection.host = host
139
+ @connection.port = port
140
+ @connection.message_queue = @queue
141
+ EventMachine::PeriodicTimer.new(60) do
142
+ Sensu::Logger.get.info("Graphite: queue size for #{name}: #{queue_length}")
8
143
  end
144
+ end
145
+
146
+ def queue_length
147
+ @queue
148
+ .map(&:bytesize)
149
+ .reduce(:+) || 0
150
+ end
151
+
152
+ def flush_to_net
153
+ sent = @connection.send_data(@queue.join)
154
+ @queue = [] if sent > 0
155
+ end
156
+
157
+ def relay_event(data)
158
+ if @connection.connected
159
+ @queue << data
160
+ if queue_length >= MAX_QUEUE_SIZE
161
+ flush_to_net
162
+ Sensu::Logger.get.debug('Graphite: successfully flushed to network')
163
+ end
164
+ end
165
+ end
166
+
167
+ def stop
168
+ if @connection.connected
169
+ flush_to_net
170
+ #@connection.close_connection_after_writing
171
+ @connection.close_connection # Force connection closing, do not wait.
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+
178
+ #################################
179
+ # Graphite Handler
180
+ #################################
181
+ class Graphite < Handler
182
+
183
+ def initialize
184
+ super
185
+ @initialized = false
186
+ @counter = 0
187
+ end
188
+
189
+ def name
190
+ "graphite"
191
+ end
192
+
193
+ def description
194
+ "Extension to get metrics into Graphite"
195
+ end
9
196
 
10
- def description
11
- "extension graphite"
197
+ def post_init
198
+ @endpoint = Endpoint.new(
199
+ @settings[:graphite][:name],
200
+ @settings[:graphite][:host],
201
+ @settings[:graphite][:port]
202
+ )
203
+ @counter = 0
204
+ end
205
+
206
+ def run(event)
207
+ begin
208
+ event = Oj.load(event)
209
+ metrics = event["check"]["output"]
210
+ rescue => e
211
+ logger.error("Graphite: Error setting up event object - #{e.backtrace.to_s}")
12
212
  end
13
213
 
14
- def run(event)
15
- logger.info("Hello Graphite")
16
- yield "template", 0
214
+ begin
215
+ if @counter > 2048
216
+ logger.debug("Graphite: recycling connection")
217
+ stop
218
+ post_init
219
+ end
220
+
221
+ logger.debug("Metrics: #{metrics}")
222
+ @endpoint.relay_event(metrics)
223
+ @counter += 1
224
+ rescue => e
225
+ logger.error("Graphite: Error posting metrics - #{e.backtrace.to_s}")
17
226
  end
227
+
228
+ yield "", 0
18
229
  end
230
+
231
+ def stop
232
+ @endpoint.stop
233
+ end
234
+
235
+ end # Graphite
236
+ #################################
237
+
19
238
  end
20
- end
239
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu-extensions-graphite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sensu-Extensions and contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-01 00:00:00.000000000 Z
11
+ date: 2017-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sensu-extension
@@ -94,9 +94,9 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: EXTENSION_TYPE extension to do X
97
+ description: Extension to get metrics into Graphite
98
98
  email:
99
- - "<sensu-users@googlegroups.com>"
99
+ - "<amine.benseddik@gmail.com>"
100
100
  executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
@@ -105,7 +105,7 @@ files:
105
105
  - LICENSE
106
106
  - README.md
107
107
  - lib/sensu/extensions/graphite.rb
108
- homepage: https://github.com/sensu-extensions/sensu-extensions-graphite
108
+ homepage: https://github.com/amine7536/sensu-extensions-graphite
109
109
  licenses: []
110
110
  metadata: {}
111
111
  post_install_message:
@@ -127,5 +127,5 @@ rubyforge_project:
127
127
  rubygems_version: 2.5.1
128
128
  signing_key:
129
129
  specification_version: 4
130
- summary: EXTENSION_TYPE extension to do X
130
+ summary: Extension to get metrics into Graphite
131
131
  test_files: []