stethoscope 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.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in stethoscope.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stethoscope (0.0.1)
5
+ dictionary (>= 1.0)
6
+ rack (> 1.0)
7
+ tilt (>= 1.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ dictionary (1.0.0)
13
+ nanotest (0.9.4.1)
14
+ nanotest_extensions (0.6.3)
15
+ rack (1.2.1)
16
+ rack-test (0.5.4)
17
+ rack (>= 1.0)
18
+ rake (0.8.7)
19
+ rspec-core (2.0.0.beta.20)
20
+ tilt (1.0.1)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ bundler (>= 1.0.0)
27
+ dictionary (>= 1.0)
28
+ nanotest
29
+ nanotest_extensions
30
+ rack (> 1.0)
31
+ rack-test
32
+ rake
33
+ rspec-core (>= 2.0.0.beta.20)
34
+ stethoscope!
35
+ tilt (>= 1.0)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 NZX
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Stethoscope
2
+
3
+ Stethoscope is Rack Middelware that provides heartbeats for your application. Heartbeats are used to check that your application is functioning correctly.
4
+
5
+ Typically, a tool like Nagios will monitor a heartbeat URL which will return a 200 OK status if everything is ok, or a 500 response for any issues.
6
+
7
+ ## Usage
8
+
9
+ ### Rack
10
+
11
+ use Stethoscope
12
+ run MyApp
13
+
14
+ ### Rails 2
15
+
16
+ # config/environment.rb
17
+ config.middleware.use Stethoscope
18
+
19
+ ### Rails 3
20
+
21
+ Just require Stethoscope in your application. Stethoscope has a Railtie that will configure Stethoscope to work
22
+
23
+ ## Customizing Stethoscope
24
+
25
+ ### Heartbeat URL
26
+
27
+ Default: `/heartbeat`
28
+
29
+ Stethoscope.url = "/some/custom/path"
30
+
31
+ ### Checks
32
+
33
+ Stethoscope uses _checks_ to check some component of the application. A check is simply a block that is executed when the heartbeat url is hit.
34
+
35
+ A response hash is made available to store any information which is then made available to the heartbeat template.
36
+
37
+ Returning a response _:status_ outside 200..299 will trigger Stethoscope to return a 500 status code to the client.
38
+
39
+ #### Example
40
+
41
+ Stethoscope.check :database do |response|
42
+ ActiveRecord::Base.connection.execute('select 1')
43
+ end
44
+
45
+ Stethoscope.check :some_service do |response|
46
+ start = Time.now
47
+ response['result'] = SomeSerivce.check_availability!
48
+ response['Ping Time'] = Time.now - start
49
+ response[:status] = 245 # Any status outside 200..299 will result in a 500 status being returned from the heartbeat
50
+ end
51
+
52
+ Any exceptions are caught and added to the response with the _:error_ key. The template can then handle them appropriately
53
+
54
+ #### Defaults
55
+
56
+ * ActiveRecord
57
+ * Check name - :database
58
+ * require 'stethoscope/checks/active\_record'
59
+ * Included if the ActiveRecord constant is present in Rails 3
60
+ * DataMapper
61
+ * Check name - :database
62
+ * require 'stethoscope/checks/data\_mapper'
63
+ * Included if the DataMapper constant is present in Rails 3
64
+
65
+ ### Template
66
+
67
+ Stethoscope uses [Tilt](http://github.com/rtomayko/tilt) to render a template for the heartbeat response
68
+
69
+ By default, Stethoscope provides a simple template to render the responses of the checks in the _lib/stethoscope/template.erb_ file.
70
+
71
+ You can overwrite the template used:
72
+
73
+ Stethoscope.template = Tilt.new("my_new_tempalte_file.haml")
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc 'Run all tests'
5
+ task :test do
6
+ test_path = File.join(File.expand_path(File.dirname(__FILE__)), "test")
7
+ $:.unshift test_path
8
+ require 'test_helper'
9
+
10
+ require 'test_stethoscope'
11
+ end
@@ -0,0 +1,7 @@
1
+ require 'stethoscope'
2
+
3
+ # Provides a check for active record databases
4
+ Stethoscope.check :database do |response|
5
+ ActiveRecord::Base.connection.execute("SELECT 1")
6
+ response["ActiveRecord"] = "OK"
7
+ end
@@ -0,0 +1,8 @@
1
+ require 'stethoscope'
2
+
3
+ # Provides a check for datamapper databases
4
+ Stethoscope.check :database do |response|
5
+ DataMapper.repository.adapter.execute("select 1")
6
+ response['Datamapper'] = "OK"
7
+ end
8
+
@@ -0,0 +1,13 @@
1
+ if defined?(Rails::Railtie)
2
+ # Adds the heartbeat to the stack
3
+ class Stethoscope
4
+ class Railtie < Rails::Railtie
5
+ initializer 'stethoscope.middleare' do |app|
6
+ app.middleware.use Stethoscope
7
+
8
+ require 'stethoscope/checks/active_record' if defined? ( ActiveRecord )
9
+ require 'stethoscope/checks/data_mapper' if defined? ( DataMapper )
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ <!Doctype html>
2
+ <html>
3
+ <head>
4
+ <title>Heartbeat</title>
5
+ </head>
6
+ <body>
7
+ <h1>Heartbeat (Ba-Boomp)</h1>
8
+ <div class='results'>
9
+ <% if checks.empty? %>
10
+ <p class='error'>No Checks Enabled</p>
11
+ <% else %>
12
+ <ul class='checks'>
13
+ <% checks.each do |name, hash| %>
14
+ <li>
15
+ <strong><%= name %>:<strong>
16
+ <ul>
17
+ <% hash.each do |item, value| %>
18
+ <li>
19
+ <% if item.to_s == 'error' %>
20
+ <h4><%= item.class %></h4>
21
+ <p class='error-message'><%= value.message %></p>
22
+ <ul class='stack-trace'>
23
+ <% value.backtrace.each do |line| %>
24
+ <li><%= line %></li>
25
+ <% end %>
26
+ <% else %>
27
+ <strong><%= item %>:</strong> <%= value %>
28
+ <% end %>
29
+ </li>
30
+ <% end %>
31
+ </ul>
32
+ </li>
33
+ <% end %>
34
+ <% end %>
35
+ </div>
36
+ </body>
37
+ </html>
38
+
39
+
@@ -0,0 +1,3 @@
1
+ class Stethoscope
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,137 @@
1
+ require 'dictionary'
2
+ require 'tilt'
3
+ require 'stethoscope/rails'
4
+
5
+ # Stethoscope is Rack middleware that provides a heartbeat function to an application.
6
+ #
7
+ # Stethoscope provides a mechanism to add checks to the application, and will render a template
8
+ # in response to a request
9
+ #
10
+ # @example
11
+ # Rack::Builder.new do
12
+ # use Stethoscope
13
+ # run MyApp.new
14
+ # end
15
+ #
16
+ # @see Rack
17
+ class Stethoscope
18
+ # Set the url to check for the heartbeat in this application
19
+ #
20
+ # @example
21
+ # Stethoscope.url = "/my/heartbeat/location"
22
+ #
23
+ # GET "/my/heartbeat/location" <-- intercepted by stethoscope
24
+ #
25
+ # @see Stethoscope.url
26
+ # @api public
27
+ def self.url=(url)
28
+ @url = url
29
+ end
30
+
31
+ # The current url that Stethoscope is setup to listen for
32
+ # @see Stethoscope.url=
33
+ # @api public
34
+ def self.url
35
+ @url ||= "/heartbeat"
36
+ end
37
+
38
+ # The collection of checks currently in place in Stethoscope
39
+ # @see Stethoscope.check
40
+ # @api public
41
+ def self.checks
42
+ @checks ||= Dictionary.new
43
+ end
44
+
45
+ # Add a check to Stethoscope
46
+ #
47
+ # A check is a block that checks the health of some aspect of your application
48
+ # You add information to the response of the check, including a status (if not successful)
49
+ #
50
+ # Any resonse that has a status outside 200..299 will cause the heartbeat to fail
51
+ #
52
+ # @example
53
+ # Stethoscope.check("My Database") do |response|
54
+ # if my_db_check
55
+ # response[:result] = "Success"
56
+ # else
57
+ # response[:result] = "Bad Bad Bad"
58
+ # response[:arbitrary] = "something else"
59
+ # response[:status] = 500 # <---- VERY IMPORTANT
60
+ # end
61
+ # end
62
+ #
63
+ # @see Stethoscope.check
64
+ # @api public
65
+ def self.check(name, &blk)
66
+ checks[name] = blk
67
+ end
68
+
69
+ # Removes a give check
70
+ # @example
71
+ # Stethoscope.remove_check("my check to remove")
72
+ #
73
+ # @see Stethoscope.check
74
+ # @api public
75
+ def self.remove_check(name)
76
+ checks.delete(name)
77
+ end
78
+
79
+ # Clears all defined checks
80
+ # @see Stethoscope.check
81
+ # @api public
82
+ def self.clear_checks
83
+ checks.clear
84
+ end
85
+
86
+ # Sets the Tilt template that will be used for heartbeat rendering
87
+ #
88
+ # @param template - A Tilt template object
89
+ #
90
+ # @see Stethoscope.template
91
+ # @see Tilt
92
+ # @api public
93
+ def self.template=(template)
94
+ @template = template
95
+ end
96
+
97
+ # Getter for the Tilt template for heartbeat rendering
98
+ # By default, the Stethoscope default template is used. Overwrite this to use a custom template
99
+ #
100
+ # @see Stethoscope.template=
101
+ # @see Tilt
102
+ #
103
+ # @api public
104
+ def self.template
105
+ @template ||= Tilt.new(File.join(File.dirname(__FILE__), "stethoscope", "template.erb"))
106
+ end
107
+ def initialize(app)
108
+ @app = app
109
+ end
110
+
111
+ def call(env)
112
+ request = Rack::Request.new(env)
113
+ if request.path == Stethoscope.url
114
+ responses = Dictionary.new do |d,k|
115
+ dict = Dictionary.new
116
+ dict[:status] = 200
117
+ d[k] = dict
118
+ end
119
+
120
+ Stethoscope.checks.each do |name, check|
121
+ begin
122
+ check.call(responses[name])
123
+ rescue => e
124
+ responses[name][:error] = e
125
+ responses[name][:status] = 500
126
+ end
127
+ end
128
+
129
+ status = responses.any?{ |k,v| v[:status] && !((200..299).include?(v[:status])) } ? 500 : 200
130
+ result = Stethoscope.template.render(Object.new, :checks => responses)
131
+
132
+ Rack::Response.new(result, status).finish
133
+ else
134
+ @app.call(env)
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/stethoscope/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "stethoscope"
6
+ s.version = Stethoscope::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Daniel Neighman']
9
+ s.email = ['has.sox@gmail.com']
10
+ s.homepage = "http://rubygems.org/gems/stethoscope"
11
+ s.summary = "Heartbeat middleware for responding to heartbeat pings"
12
+ s.description = "Heartbeat middleware for responding to heartbeat pings"
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "stethoscope"
16
+
17
+ s.add_dependency "rack", "> 1.0"
18
+ s.add_dependency "dictionary", ">= 1.0"
19
+ s.add_dependency "tilt", ">= 1.0"
20
+
21
+ s.add_development_dependency "bundler", ">= 1.0.0"
22
+ s.add_development_dependency "rspec-core", ">= 2.0.0.beta.20"
23
+ s.add_development_dependency "nanotest"
24
+ s.add_development_dependency "nanotest_extensions"
25
+ s.add_development_dependency "rake"
26
+ s.add_development_dependency "rack-test"
27
+
28
+
29
+ s.files = `git ls-files`.split("\n")
30
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
31
+ s.require_path = 'lib'
32
+ end
@@ -0,0 +1,28 @@
1
+ require 'nanotest'
2
+ require 'nanotest/contexts'
3
+ require 'nanotest/stats'
4
+ require 'rack/test'
5
+
6
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
7
+ require 'stethoscope'
8
+
9
+ APP = lambda{ |e| Rack::Response.new("default").finish }
10
+
11
+ module StethoscopeTestHelpers
12
+ def setup_app(&blk)
13
+ @app = begin
14
+ Rack::Builder.new do
15
+ if blk
16
+ instance_eval &blk
17
+ else
18
+ use Stethoscope
19
+ end
20
+ run APP
21
+ end
22
+ end
23
+ end
24
+
25
+ def app
26
+ @app
27
+ end
28
+ end
@@ -0,0 +1,93 @@
1
+ require 'test_helper'
2
+
3
+ class TestStethoscope
4
+ extend Nanotest
5
+ extend Nanotest::Contexts
6
+ extend StethoscopeTestHelpers
7
+ extend Rack::Test::Methods
8
+
9
+ context do
10
+ setup { setup_app }
11
+ teardown do
12
+ Stethoscope.url = "/heartbeat"
13
+ Stethoscope.clear_checks
14
+ end
15
+
16
+
17
+ # When accessing normal url's should not intercept anything
18
+ test do
19
+ response = get "/"
20
+ assert { response.status == 200 }
21
+ assert { response.body.to_s == "default" }
22
+ end
23
+
24
+ # When accessing the Stethoscope.url should intercept the call
25
+ test do
26
+ response = get "/heartbeat"
27
+ assert { response.status == 200 }
28
+ assert { response.body.to_s =~ /Ba-Boomp/ }
29
+ end
30
+
31
+ # With a different url
32
+ test do
33
+ Stethoscope.url = "/something_else"
34
+ response = get "/heartbeat"
35
+ assert {response.body.to_s =~ /default/ }
36
+ response = get "/something_else"
37
+ assert {response.body.to_s =~ /Ba-Boomp/ }
38
+ end
39
+
40
+ # Check checks
41
+ context do
42
+ setup { $captures = [] }
43
+ teardown { $captures.clear }
44
+ # Check that checks run
45
+ test do
46
+ Stethoscope.check(:foo){ |response| response[:status] = 200;$captures << :foo; }
47
+ Stethoscope.check(:bar){ |response| response[:status] = 200;$captures << :bar; }
48
+
49
+ response = get "/heartbeat"
50
+ assert { response.status == 200 }
51
+ assert { $captures == [:foo, :bar] }
52
+ end
53
+
54
+ # Check, and fail the run
55
+ test do
56
+ Stethoscope.check(:foo){ |response| $captures << :foo; }
57
+ Stethoscope.check(:bar){ |response| response[:status] = 500;$captures << :bar; }
58
+
59
+ response = get "/heartbeat"
60
+ assert { response.status == 500 }
61
+ end
62
+
63
+ # should render the reason
64
+ test do
65
+ Stethoscope.check(:something) do |resp|
66
+ resp[:status] = 423
67
+ resp[:reason] = "Something went wrong capt'n"
68
+ end
69
+
70
+ response = get "/heartbeat"
71
+ assert { response.status == 500 }
72
+ assert { response.body.to_s =~ /Something went wrong capt'n/m }
73
+ end
74
+
75
+ # should handle tests being nilled
76
+ test do
77
+ Stethoscope.check('foo'){}
78
+ assert { Proc === Stethoscope.checks['foo'] }
79
+ Stethoscope.remove_check('foo')
80
+ assert { !Stethoscope.checks.key?('foo') }
81
+ end
82
+
83
+ # should give a 500 status if there is an exception
84
+ test do
85
+ Stethoscope.check('foo'){ |resp| raise "Oh Noes" }
86
+
87
+ response = get "/heartbeat"
88
+ assert { response.status == 500 }
89
+ end
90
+ end
91
+ end
92
+ end
93
+
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stethoscope
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Daniel Neighman
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-07 00:00:00 +10:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">"
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 0
33
+ version: "1.0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: dictionary
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 15
45
+ segments:
46
+ - 1
47
+ - 0
48
+ version: "1.0"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: tilt
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 15
60
+ segments:
61
+ - 1
62
+ - 0
63
+ version: "1.0"
64
+ type: :runtime
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: bundler
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 23
75
+ segments:
76
+ - 1
77
+ - 0
78
+ - 0
79
+ version: 1.0.0
80
+ type: :development
81
+ version_requirements: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec-core
84
+ prerelease: false
85
+ requirement: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 62196427
91
+ segments:
92
+ - 2
93
+ - 0
94
+ - 0
95
+ - beta
96
+ - 20
97
+ version: 2.0.0.beta.20
98
+ type: :development
99
+ version_requirements: *id005
100
+ - !ruby/object:Gem::Dependency
101
+ name: nanotest
102
+ prerelease: false
103
+ requirement: &id006 !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ type: :development
113
+ version_requirements: *id006
114
+ - !ruby/object:Gem::Dependency
115
+ name: nanotest_extensions
116
+ prerelease: false
117
+ requirement: &id007 !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ type: :development
127
+ version_requirements: *id007
128
+ - !ruby/object:Gem::Dependency
129
+ name: rake
130
+ prerelease: false
131
+ requirement: &id008 !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ hash: 3
137
+ segments:
138
+ - 0
139
+ version: "0"
140
+ type: :development
141
+ version_requirements: *id008
142
+ - !ruby/object:Gem::Dependency
143
+ name: rack-test
144
+ prerelease: false
145
+ requirement: &id009 !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ hash: 3
151
+ segments:
152
+ - 0
153
+ version: "0"
154
+ type: :development
155
+ version_requirements: *id009
156
+ description: Heartbeat middleware for responding to heartbeat pings
157
+ email:
158
+ - has.sox@gmail.com
159
+ executables: []
160
+
161
+ extensions: []
162
+
163
+ extra_rdoc_files: []
164
+
165
+ files:
166
+ - .gitignore
167
+ - Gemfile
168
+ - Gemfile.lock
169
+ - LICENSE
170
+ - README.md
171
+ - Rakefile
172
+ - lib/stethoscope.rb
173
+ - lib/stethoscope/checks/active_record.rb
174
+ - lib/stethoscope/checks/data_mapper.rb
175
+ - lib/stethoscope/rails.rb
176
+ - lib/stethoscope/template.erb
177
+ - lib/stethoscope/version.rb
178
+ - stethoscope.gemspec
179
+ - test/test_helper.rb
180
+ - test/test_stethoscope.rb
181
+ has_rdoc: true
182
+ homepage: http://rubygems.org/gems/stethoscope
183
+ licenses: []
184
+
185
+ post_install_message:
186
+ rdoc_options: []
187
+
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ none: false
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ hash: 3
196
+ segments:
197
+ - 0
198
+ version: "0"
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ hash: 23
205
+ segments:
206
+ - 1
207
+ - 3
208
+ - 6
209
+ version: 1.3.6
210
+ requirements: []
211
+
212
+ rubyforge_project: stethoscope
213
+ rubygems_version: 1.3.7
214
+ signing_key:
215
+ specification_version: 3
216
+ summary: Heartbeat middleware for responding to heartbeat pings
217
+ test_files: []
218
+