sensu 0.13.1-java → 0.14.0.beta-java
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 +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/sensu/api.rb +35 -5
- data/lib/sensu/client.rb +13 -6
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +1 -1
- data/lib/sensu/server.rb +28 -14
- data/lib/sensu/socket.rb +197 -30
- data/sensu.gemspec +4 -4
- metadata +18 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4579594b99d018ca7ec1fe9c2d82d8c3a1796dc6
|
4
|
+
data.tar.gz: 95def4eb9ebce9a3851c3571dfb06a23a126a639
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b185dc5176bb716b33537424da4cbfd81155dcee418911bc6beb980238781fd6b15e1080530294ade66d4666d368f3cd31d43dac7bc85c32178a28c8dabeb642
|
7
|
+
data.tar.gz: 594bddf91fb61f1e97a4ebf4867b967e0457c8eed61a5d24887a3ac2083d2fd9ddc6b03c1a180fbb69aed970546d370dcd51f6eb00587431afe31f73531aa5b5
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
## 0.14.0 - TBD
|
2
|
+
|
3
|
+
### Features
|
4
|
+
|
5
|
+
Client socket now supports sending a result via a TCP stream. This feature
|
6
|
+
allows check results to have larger output (metrics, backtraces, etc).
|
7
|
+
|
8
|
+
API now supports CORS (configurable).
|
9
|
+
|
10
|
+
### Other
|
11
|
+
|
12
|
+
Child process manager now supports check output larger than the max OS
|
13
|
+
buffer size. The parent process was waiting on the child to exit before
|
14
|
+
closing its write end of the pipe.
|
15
|
+
|
16
|
+
Client & server are now guarding against invalid JSON transport payloads.
|
17
|
+
|
1
18
|
## 0.13.1 - 2014-07-28
|
2
19
|
|
3
20
|
### Other
|
data/lib/sensu/api.rb
CHANGED
@@ -39,13 +39,15 @@ module Sensu
|
|
39
39
|
setup_logger(options)
|
40
40
|
set :logger, @logger
|
41
41
|
load_settings(options)
|
42
|
+
set :api, @settings[:api]
|
42
43
|
set :checks, @settings[:checks]
|
43
44
|
set :all_checks, @settings.checks
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
set :cors, @settings[:cors] || {
|
46
|
+
'Origin' => '*',
|
47
|
+
'Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
|
48
|
+
'Credentials' => 'true',
|
49
|
+
'Headers' => 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
|
50
|
+
}
|
49
51
|
on_reactor_run
|
50
52
|
self
|
51
53
|
end
|
@@ -112,10 +114,30 @@ module Sensu
|
|
112
114
|
env['rack.input'].rewind
|
113
115
|
end
|
114
116
|
|
117
|
+
def protected!
|
118
|
+
if settings.api[:user] && settings.api[:password]
|
119
|
+
return if !(settings.api[:user] && settings.api[:password]) || authorized?
|
120
|
+
headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
|
121
|
+
unauthorized!
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def authorized?
|
126
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
127
|
+
@auth.provided? &&
|
128
|
+
@auth.basic? &&
|
129
|
+
@auth.credentials &&
|
130
|
+
@auth.credentials == [settings.api[:user], settings.api[:password]]
|
131
|
+
end
|
132
|
+
|
115
133
|
def bad_request!
|
116
134
|
ahalt 400
|
117
135
|
end
|
118
136
|
|
137
|
+
def unauthorized!
|
138
|
+
ahalt 401
|
139
|
+
end
|
140
|
+
|
119
141
|
def not_found!
|
120
142
|
ahalt 404
|
121
143
|
end
|
@@ -235,6 +257,14 @@ module Sensu
|
|
235
257
|
before do
|
236
258
|
request_log_line
|
237
259
|
content_type 'application/json'
|
260
|
+
settings.cors.each do |header, value|
|
261
|
+
headers['Access-Control-Allow-' + header] = value
|
262
|
+
end
|
263
|
+
protected! unless env['REQUEST_METHOD'] == 'OPTIONS'
|
264
|
+
end
|
265
|
+
|
266
|
+
aoptions '/*' do
|
267
|
+
body ''
|
238
268
|
end
|
239
269
|
|
240
270
|
aget '/info/?' do
|
data/lib/sensu/client.rb
CHANGED
@@ -170,11 +170,18 @@ module Sensu
|
|
170
170
|
})
|
171
171
|
funnel = [@settings[:client][:name], VERSION, Time.now.to_i].join('-')
|
172
172
|
@transport.subscribe(:fanout, subscription, funnel) do |message_info, message|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
173
|
+
begin
|
174
|
+
check = MultiJson.load(message)
|
175
|
+
@logger.info('received check request', {
|
176
|
+
:check => check
|
177
|
+
})
|
178
|
+
process_check(check)
|
179
|
+
rescue MultiJson::ParseError => error
|
180
|
+
@logger.error('failed to parse the check request payload', {
|
181
|
+
:message => message,
|
182
|
+
:error => error.to_s
|
183
|
+
})
|
184
|
+
end
|
178
185
|
end
|
179
186
|
end
|
180
187
|
end
|
@@ -224,7 +231,7 @@ module Sensu
|
|
224
231
|
socket.logger = @logger
|
225
232
|
socket.settings = @settings
|
226
233
|
socket.transport = @transport
|
227
|
-
socket.
|
234
|
+
socket.protocol = :udp
|
228
235
|
end
|
229
236
|
end
|
230
237
|
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/daemon.rb
CHANGED
data/lib/sensu/server.rb
CHANGED
@@ -26,14 +26,21 @@ module Sensu
|
|
26
26
|
def setup_keepalives
|
27
27
|
@logger.debug('subscribing to keepalives')
|
28
28
|
@transport.subscribe(:direct, 'keepalives', 'keepalives', :ack => true) do |message_info, message|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@redis.
|
35
|
-
@
|
29
|
+
begin
|
30
|
+
client = MultiJson.load(message)
|
31
|
+
@logger.debug('received keepalive', {
|
32
|
+
:client => client
|
33
|
+
})
|
34
|
+
@redis.set('client:' + client[:name], MultiJson.dump(client)) do
|
35
|
+
@redis.sadd('clients', client[:name]) do
|
36
|
+
@transport.ack(message_info)
|
37
|
+
end
|
36
38
|
end
|
39
|
+
rescue MultiJson::ParseError => error
|
40
|
+
@logger.error('failed to parse keepalive payload', {
|
41
|
+
:message => message,
|
42
|
+
:error => error.to_s
|
43
|
+
})
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
@@ -447,13 +454,20 @@ module Sensu
|
|
447
454
|
def setup_results
|
448
455
|
@logger.debug('subscribing to results')
|
449
456
|
@transport.subscribe(:direct, 'results', 'results', :ack => true) do |message_info, message|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
+
begin
|
458
|
+
result = MultiJson.load(message)
|
459
|
+
@logger.debug('received result', {
|
460
|
+
:result => result
|
461
|
+
})
|
462
|
+
process_result(result)
|
463
|
+
EM::next_tick do
|
464
|
+
@transport.ack(message_info)
|
465
|
+
end
|
466
|
+
rescue MultiJson::ParseError => error
|
467
|
+
@logger.error('failed to parse result payload', {
|
468
|
+
:message => message,
|
469
|
+
:error => error.to_s
|
470
|
+
})
|
457
471
|
end
|
458
472
|
end
|
459
473
|
end
|
data/lib/sensu/socket.rb
CHANGED
@@ -1,15 +1,184 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
1
3
|
module Sensu
|
4
|
+
# EventMachine connection handler for the Sensu client's socket.
|
5
|
+
#
|
6
|
+
# The Sensu client listens on localhost, port 3030 (by default), for
|
7
|
+
# UDP and TCP traffic. This allows software running on the host to
|
8
|
+
# push check results (that may contain metrics) into Sensu, without
|
9
|
+
# needing to know anything about Sensu's internal implementation.
|
10
|
+
#
|
11
|
+
# The socket only accepts 7-bit ASCII-encoded data.
|
12
|
+
#
|
13
|
+
# Although the Sensu client accepts UDP and TCP traffic, you must be
|
14
|
+
# aware of the UDP protocol limitations. Any data you send over UDP
|
15
|
+
# must fit in a single datagram and you will not receive a response
|
16
|
+
# (no confirmation).
|
17
|
+
#
|
18
|
+
# == UDP Protocol ==
|
19
|
+
#
|
20
|
+
# If the socket receives a message containing whitespace and the
|
21
|
+
# string +'ping'+, it will ignore it.
|
22
|
+
#
|
23
|
+
# The socket assumes all other messages will contain a single,
|
24
|
+
# complete, JSON hash. The hash must be a valid JSON check result.
|
25
|
+
# Deserialization failures will be logged at the ERROR level by the
|
26
|
+
# Sensu client, but the sender of the invalid data will not be
|
27
|
+
# notified.
|
28
|
+
#
|
29
|
+
# == TCP Protocol ==
|
30
|
+
#
|
31
|
+
# If the socket receives a message containing whitespace and the
|
32
|
+
# string +'ping'+, it will respond with the message +'pong'+.
|
33
|
+
#
|
34
|
+
# The socket assumes any other stream will be a single, complete,
|
35
|
+
# JSON hash. A deserialization failure will be logged at the WARN
|
36
|
+
# level by the Sensu client and respond with the message
|
37
|
+
# +'invalid'+. An +'ok'+ response indicates the Sensu client
|
38
|
+
# successfully received the JSON hash and will publish the check
|
39
|
+
# result.
|
40
|
+
#
|
41
|
+
# Streams can be of any length. The socket protocol does not require
|
42
|
+
# any headers, instead the socket tries to parse everything it has
|
43
|
+
# been sent each time a chunk of data arrives. Once the JSON parses
|
44
|
+
# successfully, the Sensu client publishes the result. After
|
45
|
+
# +WATCHDOG_DELAY+ (default is 500 msec) since the most recent chunk
|
46
|
+
# of data was received, the agent will give up on the sender, and
|
47
|
+
# instead respond +'invalid'+ and close the connection.
|
2
48
|
class Socket < EM::Connection
|
3
|
-
|
49
|
+
class DataError < StandardError; end
|
50
|
+
|
51
|
+
attr_accessor :logger, :settings, :transport, :protocol
|
52
|
+
|
53
|
+
# The number of seconds that may elapse between chunks of data
|
54
|
+
# from a sender before it is considered dead, and the connection
|
55
|
+
# is close.
|
56
|
+
WATCHDOG_DELAY = 0.5
|
57
|
+
|
58
|
+
#
|
59
|
+
# Sensu::Socket operating mode enum.
|
60
|
+
#
|
61
|
+
|
62
|
+
# ACCEPT mode. Append chunks of data to a buffer and test to see
|
63
|
+
# whether the buffer contents are valid JSON.
|
64
|
+
MODE_ACCEPT = :ACCEPT
|
4
65
|
|
66
|
+
# REJECT mode. No longer receiving data from sender. Discard
|
67
|
+
# chunks of data in this mode, the connection is being closed.
|
68
|
+
MODE_REJECT = :REJECT
|
69
|
+
|
70
|
+
# Initialize instance variables that will be used throughout the
|
71
|
+
# lifetime of the connection. This method is called when the
|
72
|
+
# network connection has been established, and immediately after
|
73
|
+
# responding to a sender.
|
74
|
+
def post_init
|
75
|
+
@protocol ||= :tcp
|
76
|
+
@data_buffer = ''
|
77
|
+
@parse_error = nil
|
78
|
+
@watchdog = nil
|
79
|
+
@mode = MODE_ACCEPT
|
80
|
+
end
|
81
|
+
|
82
|
+
# Send a response to the sender, close the
|
83
|
+
# connection, and call post_init().
|
84
|
+
#
|
85
|
+
# @param [String] data to send as a response.
|
5
86
|
def respond(data)
|
6
|
-
|
87
|
+
if @protocol == :tcp
|
7
88
|
send_data(data)
|
89
|
+
close_connection_after_writing
|
8
90
|
end
|
91
|
+
post_init
|
9
92
|
end
|
10
93
|
|
11
|
-
|
12
|
-
|
94
|
+
# Cancel the current connection watchdog.
|
95
|
+
def cancel_watchdog
|
96
|
+
if @watchdog
|
97
|
+
@watchdog.cancel
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Reset (or start) the connection watchdog.
|
102
|
+
def reset_watchdog
|
103
|
+
cancel_watchdog
|
104
|
+
@watchdog = EM::Timer.new(WATCHDOG_DELAY) do
|
105
|
+
@mode = MODE_REJECT
|
106
|
+
@logger.warn('discarding data buffer for sender and closing connection', {
|
107
|
+
:data => @data_buffer,
|
108
|
+
:parse_error => @parse_error
|
109
|
+
})
|
110
|
+
respond('invalid')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Validate check result attributes.
|
115
|
+
#
|
116
|
+
# @param [Hash] check result to validate.
|
117
|
+
def validate_check_result(check)
|
118
|
+
unless check[:name] =~ /^[\w\.-]+$/
|
119
|
+
raise DataError, 'check name must be a string and cannot contain spaces or special characters'
|
120
|
+
end
|
121
|
+
unless check[:output].is_a?(String)
|
122
|
+
raise DataError, 'check output must be a string'
|
123
|
+
end
|
124
|
+
unless check[:status].is_a?(Integer)
|
125
|
+
raise DataError, 'check status must be an integer'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Publish a check result to the Sensu transport.
|
130
|
+
#
|
131
|
+
# @param [Hash] check result.
|
132
|
+
def publish_check_result(check)
|
133
|
+
payload = {
|
134
|
+
:client => @settings[:client][:name],
|
135
|
+
:check => check.merge(:issued => Time.now.to_i)
|
136
|
+
}
|
137
|
+
@logger.info('publishing check result', {
|
138
|
+
:payload => payload
|
139
|
+
})
|
140
|
+
@transport.publish(:direct, 'results', MultiJson.dump(payload))
|
141
|
+
end
|
142
|
+
|
143
|
+
# Process a check result. Set check result attribute defaults,
|
144
|
+
# validate the attributes, publish the check result to the Sensu
|
145
|
+
# transport, and respond to the sender with the message +'ok'+.
|
146
|
+
#
|
147
|
+
# @param [Hash] check result to be validated and published.
|
148
|
+
# @raise [DataError] if +check+ is invalid.
|
149
|
+
def process_check_result(check)
|
150
|
+
check[:status] ||= 0
|
151
|
+
validate_check_result(check)
|
152
|
+
publish_check_result(check)
|
153
|
+
respond('ok')
|
154
|
+
end
|
155
|
+
|
156
|
+
# Parse a JSON check result. For UDP, immediately raise a parser
|
157
|
+
# error. For TCP, record parser errors, so the connection
|
158
|
+
# +watchdog+ can report them.
|
159
|
+
#
|
160
|
+
# @param [String] data to parse for a check result.
|
161
|
+
def parse_check_result(data)
|
162
|
+
begin
|
163
|
+
check = MultiJson.load(data)
|
164
|
+
cancel_watchdog
|
165
|
+
process_check_result(check)
|
166
|
+
rescue MultiJson::ParseError, ArgumentError => error
|
167
|
+
if @protocol == :tcp
|
168
|
+
@parse_error = error.to_s
|
169
|
+
else
|
170
|
+
raise error
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Process the data received. This method validates the data
|
176
|
+
# encoding, provides ping/pong functionality, and passes potential
|
177
|
+
# check results on for further processing.
|
178
|
+
#
|
179
|
+
# @param [String] data to be processed.
|
180
|
+
def process_data(data)
|
181
|
+
if data.bytes.find { |char| char > 0x80 }
|
13
182
|
@logger.warn('socket received non-ascii characters')
|
14
183
|
respond('invalid')
|
15
184
|
elsif data.strip == 'ping'
|
@@ -20,32 +189,9 @@ module Sensu
|
|
20
189
|
:data => data
|
21
190
|
})
|
22
191
|
begin
|
23
|
-
|
24
|
-
|
25
|
-
check
|
26
|
-
validates = [
|
27
|
-
check[:name] =~ /^[\w\.-]+$/,
|
28
|
-
check[:output].is_a?(String),
|
29
|
-
check[:status].is_a?(Integer)
|
30
|
-
].all?
|
31
|
-
if validates
|
32
|
-
payload = {
|
33
|
-
:client => @settings[:client][:name],
|
34
|
-
:check => check
|
35
|
-
}
|
36
|
-
@logger.info('publishing check result', {
|
37
|
-
:payload => payload
|
38
|
-
})
|
39
|
-
@transport.publish(:direct, 'results', MultiJson.dump(payload))
|
40
|
-
respond('ok')
|
41
|
-
else
|
42
|
-
@logger.warn('invalid check result', {
|
43
|
-
:check => check
|
44
|
-
})
|
45
|
-
respond('invalid')
|
46
|
-
end
|
47
|
-
rescue MultiJson::ParseError => error
|
48
|
-
@logger.warn('check result must be valid json', {
|
192
|
+
parse_check_result(data)
|
193
|
+
rescue => error
|
194
|
+
@logger.error('failed to process check result from socket', {
|
49
195
|
:data => data,
|
50
196
|
:error => error.to_s
|
51
197
|
})
|
@@ -53,6 +199,27 @@ module Sensu
|
|
53
199
|
end
|
54
200
|
end
|
55
201
|
end
|
202
|
+
|
203
|
+
# This method is called whenever data is received. For UDP, it
|
204
|
+
# will only be called once, the original data length can be
|
205
|
+
# expected. For TCP, this method may be called several times, data
|
206
|
+
# received is buffered. TCP connections require a +watchdog+.
|
207
|
+
#
|
208
|
+
# @param [String] data received from the sender.
|
209
|
+
def receive_data(data)
|
210
|
+
unless @mode == MODE_REJECT
|
211
|
+
case @protocol
|
212
|
+
when :udp
|
213
|
+
process_data(data)
|
214
|
+
when :tcp
|
215
|
+
if EM.reactor_running?
|
216
|
+
reset_watchdog
|
217
|
+
end
|
218
|
+
@data_buffer << data
|
219
|
+
process_data(@data_buffer)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
56
223
|
end
|
57
224
|
|
58
225
|
class SocketHandler < EM::Connection
|
data/sensu.gemspec
CHANGED
@@ -22,15 +22,15 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_dependency('sensu-extension', '1.0.0')
|
23
23
|
s.add_dependency('sensu-extensions', '1.0.0')
|
24
24
|
s.add_dependency('sensu-transport', '1.0.0')
|
25
|
-
s.add_dependency('sensu-spawn', '1.
|
25
|
+
s.add_dependency('sensu-spawn', '1.1.0')
|
26
26
|
s.add_dependency('em-redis-unified', '0.5.0')
|
27
27
|
s.add_dependency('sinatra', '1.3.5')
|
28
28
|
s.add_dependency('async_sinatra', '1.0.0')
|
29
29
|
s.add_dependency('thin', '1.5.0') unless RUBY_PLATFORM =~ /java/
|
30
30
|
|
31
|
-
s.add_development_dependency('rake')
|
32
|
-
s.add_development_dependency('rspec')
|
33
|
-
s.add_development_dependency('em-http-request')
|
31
|
+
s.add_development_dependency('rake', '~> 10.3')
|
32
|
+
s.add_development_dependency('rspec', '~> 3.0.0')
|
33
|
+
s.add_development_dependency('em-http-request', '~> 1.1')
|
34
34
|
|
35
35
|
s.files = Dir.glob('{bin,lib}/**/*') + %w[sensu.gemspec README.md CHANGELOG.md MIT-LICENSE.txt]
|
36
36
|
s.executables = Dir.glob('bin/**/*').map { |file| File.basename(file) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0.beta
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Sean Porter
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-09-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -129,12 +129,12 @@ dependencies:
|
|
129
129
|
requirements:
|
130
130
|
- - '='
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: 1.
|
132
|
+
version: 1.1.0
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
135
|
- - '='
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: 1.
|
137
|
+
version: 1.1.0
|
138
138
|
prerelease: false
|
139
139
|
type: :runtime
|
140
140
|
- !ruby/object:Gem::Dependency
|
@@ -183,42 +183,42 @@ dependencies:
|
|
183
183
|
name: rake
|
184
184
|
version_requirements: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
|
-
- -
|
186
|
+
- - ~>
|
187
187
|
- !ruby/object:Gem::Version
|
188
|
-
version: '
|
188
|
+
version: '10.3'
|
189
189
|
requirement: !ruby/object:Gem::Requirement
|
190
190
|
requirements:
|
191
|
-
- -
|
191
|
+
- - ~>
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version: '
|
193
|
+
version: '10.3'
|
194
194
|
prerelease: false
|
195
195
|
type: :development
|
196
196
|
- !ruby/object:Gem::Dependency
|
197
197
|
name: rspec
|
198
198
|
version_requirements: !ruby/object:Gem::Requirement
|
199
199
|
requirements:
|
200
|
-
- -
|
200
|
+
- - ~>
|
201
201
|
- !ruby/object:Gem::Version
|
202
|
-
version:
|
202
|
+
version: 3.0.0
|
203
203
|
requirement: !ruby/object:Gem::Requirement
|
204
204
|
requirements:
|
205
|
-
- -
|
205
|
+
- - ~>
|
206
206
|
- !ruby/object:Gem::Version
|
207
|
-
version:
|
207
|
+
version: 3.0.0
|
208
208
|
prerelease: false
|
209
209
|
type: :development
|
210
210
|
- !ruby/object:Gem::Dependency
|
211
211
|
name: em-http-request
|
212
212
|
version_requirements: !ruby/object:Gem::Requirement
|
213
213
|
requirements:
|
214
|
-
- -
|
214
|
+
- - ~>
|
215
215
|
- !ruby/object:Gem::Version
|
216
|
-
version: '
|
216
|
+
version: '1.1'
|
217
217
|
requirement: !ruby/object:Gem::Requirement
|
218
218
|
requirements:
|
219
|
-
- -
|
219
|
+
- - ~>
|
220
220
|
- !ruby/object:Gem::Version
|
221
|
-
version: '
|
221
|
+
version: '1.1'
|
222
222
|
prerelease: false
|
223
223
|
type: :development
|
224
224
|
description: A monitoring framework that aims to be simple, malleable, and scalable.
|
@@ -265,9 +265,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
265
265
|
version: '0'
|
266
266
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
267
|
requirements:
|
268
|
-
- - '
|
268
|
+
- - '>'
|
269
269
|
- !ruby/object:Gem::Version
|
270
|
-
version:
|
270
|
+
version: 1.3.1
|
271
271
|
requirements: []
|
272
272
|
rubyforge_project:
|
273
273
|
rubygems_version: 2.1.9
|