instrumental_agent 0.9.1 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ### 0.9.5 [March 23rd, 2012]
2
+ * Defer startup of agent thread until metrics are submitted - this update is strongly recommended for anyone using Ruby Enterprise Edition in concert w/ a preforking application server (like Phusion Passenger). See the [REE wiki page](https://github.com/fastestforward/instrumental_agent/wiki/Using-with-Ruby-Enterprise-Edition) for more information.
3
+ * Add .stop method for cancelling agent processing
4
+ * Changes to how defaults are processed at initialization
5
+ * Documentation for usage w/ Resque and Resque like scenarios
6
+
1
7
  ### 0.9.1 [March 6th, 2012]
2
8
  * No longer install system_timer on Ruby 1.8.x, but warn if it's not installed
3
9
 
data/README.md CHANGED
@@ -89,6 +89,22 @@ after "deploy:migrations", "instrumental:util:deploy_end"
89
89
  after "instrumental:util:deploy_end", "instrumental:record_deploy_notice"
90
90
  ```
91
91
 
92
+ ## Tracking metrics in Resque jobs (and Resque-like scenarios)
93
+
94
+ If you plan on tracking metrics in your Resque jobs, you will need to explicitly flush your metrics when the jobs are finished. You can accomplish this by adding the following code to your app initializers:
95
+
96
+ ```ruby
97
+ Resque.after_perform { I.flush }
98
+ Resque.on_failure { I.flush }
99
+ ```
100
+
101
+ You're required to do this because Resque calls `exit!` when a worker has finished processing, which bypasses Ruby's `at_exit` hooks. The Instrumental Agent installs an `at_exit` hook to flush any pending metrics to the servers, but this hook is bypassed by the `exit!` call; any other code you rely that uses `exit!` should call `I.flush` to ensure any pending metrics are correctly sent to the server before exiting the process.
102
+
103
+ ## Using with Ruby Enterprise Edition
104
+
105
+ Users of Ruby Enterprise Edition should plan on using version 0.9.5 of the Instrumental Agent or greater. Please see the [REE wiki page](https://github.com/fastestforward/instrumental_agent/wiki/Using-with-Ruby-Enterprise-Edition) for more information.
106
+
107
+
92
108
  ## Troubleshooting & Help
93
109
 
94
110
  We are here to help. Email us at [support@instrumentalapp.com](mailto:support@instrumentalapp.com), or visit the [Instrumental Support](https://fastestforward.campfirenow.com/6b934) Campfire room.
@@ -3,6 +3,7 @@ require 'instrumental/version'
3
3
  require 'logger'
4
4
  require 'thread'
5
5
  require 'socket'
6
+
6
7
  if RUBY_VERSION < "1.9" && RUBY_PLATFORM != "java"
7
8
  begin
8
9
  gem 'system_timer'
@@ -69,32 +70,28 @@ module Instrumental
69
70
  # Instrumental::Agent.new(API_KEY)
70
71
  # Instrumental::Agent.new(API_KEY, :collector => 'hostname:port')
71
72
  def initialize(api_key, options = {})
72
- default_options = {
73
- :collector => 'instrumentalapp.com:8000',
74
- :enabled => true,
75
- :test_mode => false,
76
- :synchronous => false
77
- }
78
- options = default_options.merge(options)
79
- collector = options[:collector].split(':')
80
-
81
- @api_key = api_key
82
- @host = collector[0]
83
- @port = (collector[1] || 8000).to_i
84
- @enabled = options[:enabled]
85
- @test_mode = options[:test_mode]
86
- @synchronous = options[:synchronous]
73
+ # symbolize options keys
74
+ options.replace(
75
+ options.inject({}) { |m, (k, v)| m[(k.to_sym rescue k) || k] = v; m }
76
+ )
77
+
78
+ # defaults
79
+ # host: instrumentalapp.com
80
+ # port: 8000
81
+ # enabled: true
82
+ # test_mode: false
83
+ # synchronous: false
84
+ @api_key = api_key
85
+ @host, @port = options[:collector].to_s.split(':')
86
+ @host ||= 'instrumentalapp.com'
87
+ @port = (@port || 8000).to_i
88
+ @enabled = options.has_key?(:enabled) ? !!options[:enabled] : true
89
+ @test_mode = !!options[:test_mode]
90
+ @synchronous = !!options[:synchronous]
91
+ @pid = Process.pid
87
92
  @allow_reconnect = true
88
- @pid = Process.pid
89
-
90
93
 
91
- if @enabled
92
- @failures = 0
93
- @queue = Queue.new
94
- @sync_mutex = Mutex.new
95
- start_connection_worker
96
- setup_cleanup_at_exit
97
- end
94
+ setup_cleanup_at_exit if @enabled
98
95
  end
99
96
 
100
97
  # Store a gauge for a metric, optionally at a specific time.
@@ -204,6 +201,23 @@ module Instrumental
204
201
  @logger ||= self.class.logger
205
202
  end
206
203
 
204
+ # Stopping the agent will immediately stop all communication
205
+ # to Instrumental. If you call this and submit another metric,
206
+ # the agent will start again.
207
+ #
208
+ # Calling stop will cause all metrics waiting to be sent to be
209
+ # discarded. Don't call it unless you are expecting this behavior.
210
+ #
211
+ # agent.stop
212
+ #
213
+ def stop
214
+ disconnect
215
+ if @thread
216
+ @thread.kill
217
+ @thread = nil
218
+ end
219
+ end
220
+
207
221
  private
208
222
 
209
223
  def with_timeout(time, &block)
@@ -242,13 +256,7 @@ module Instrumental
242
256
 
243
257
  def send_command(cmd, *args)
244
258
  if enabled?
245
- if @pid != Process.pid
246
- logger.info "Detected fork"
247
- @pid = Process.pid
248
- @socket = nil
249
- @queue = Queue.new
250
- start_connection_worker
251
- end
259
+ start_connection_worker if !running?
252
260
 
253
261
  cmd = "%s %s\n" % [cmd, args.collect { |a| a.to_s }.join(" ")]
254
262
  if @queue.size < MAX_BUFFER
@@ -293,6 +301,10 @@ module Instrumental
293
301
  def start_connection_worker
294
302
  if enabled?
295
303
  disconnect
304
+ @pid = Process.pid
305
+ @queue = Queue.new
306
+ @sync_mutex = Mutex.new
307
+ @failures = 0
296
308
  logger.info "Starting thread"
297
309
  @thread = Thread.new do
298
310
  run_worker_loop
@@ -364,23 +376,28 @@ module Instrumental
364
376
 
365
377
  def setup_cleanup_at_exit
366
378
  at_exit do
367
- logger.info "Cleaning up agent, queue empty: #{@queue.empty?}, thread running: #{@thread.alive?}"
368
- @allow_reconnect = false
369
- logger.info "exit received, currently #{@queue.size} commands to be sent"
370
- queue_message('exit')
371
- begin
372
- with_timeout(EXIT_FLUSH_TIMEOUT) { @thread.join }
373
- rescue Timeout::Error
374
- if @queue.size > 0
375
- logger.error "Timed out working agent thread on exit, dropping #{@queue.size} metrics"
376
- else
377
- logger.error "Timed out Instrumental Agent, exiting"
379
+ if running?
380
+ logger.info "Cleaning up agent, queue empty: #{@queue.empty?}, thread running: #{@thread.alive?}"
381
+ @allow_reconnect = false
382
+ logger.info "exit received, currently #{@queue.size} commands to be sent"
383
+ queue_message('exit')
384
+ begin
385
+ with_timeout(EXIT_FLUSH_TIMEOUT) { @thread.join }
386
+ rescue Timeout::Error
387
+ if @queue.size > 0
388
+ logger.error "Timed out working agent thread on exit, dropping #{@queue.size} metrics"
389
+ else
390
+ logger.error "Timed out Instrumental Agent, exiting"
391
+ end
378
392
  end
379
393
  end
380
-
381
394
  end
382
395
  end
383
396
 
397
+ def running?
398
+ !@thread.nil? && @pid == Process.pid
399
+ end
400
+
384
401
  def disconnect
385
402
  if connected?
386
403
  logger.info "Disconnecting..."
@@ -1,3 +1,3 @@
1
1
  module Instrumental
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.5'
3
3
  end
data/spec/agent_spec.rb CHANGED
@@ -12,6 +12,8 @@ describe Instrumental::Agent, "disabled" do
12
12
  end
13
13
 
14
14
  after do
15
+ @agent.stop
16
+ @agent = nil
15
17
  @server.stop
16
18
  end
17
19
 
@@ -43,26 +45,36 @@ describe Instrumental::Agent, "disabled" do
43
45
  end
44
46
 
45
47
  describe Instrumental::Agent, "enabled in test_mode" do
46
- before do
48
+ before(:each) do
47
49
  @server = TestServer.new
48
50
  @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :test_mode => true)
49
51
  end
50
52
 
51
- after do
53
+ after(:each) do
54
+ @agent.stop
55
+ @agent = nil
52
56
  @server.stop
53
57
  end
54
58
 
55
- it "should connect to the server" do
59
+ it "should not connect to the server" do
60
+ wait
61
+ @server.connect_count.should == 0
62
+ end
63
+
64
+ it "should connect to the server when the user sends a metric" do
65
+ @agent.increment("test.foo")
56
66
  wait
57
67
  @server.connect_count.should == 1
58
68
  end
59
69
 
60
70
  it "should announce itself, and include version and test_mode flag" do
71
+ @agent.increment("test.foo")
61
72
  wait
62
73
  @server.commands[0].should =~ /hello .*version .*test_mode true/
63
74
  end
64
75
 
65
76
  it "should authenticate using the token" do
77
+ @agent.increment("test.foo")
66
78
  wait
67
79
  @server.commands[1].should == "authenticate test_token"
68
80
  end
@@ -110,7 +122,7 @@ describe Instrumental::Agent, "enabled in test_mode" do
110
122
  wait
111
123
  @server.commands.last.should =~ /gauge time_ms_test .* #{now.to_i}/
112
124
  time = @server.commands.last.scan(/gauge time_ms_test (.*) #{now.to_i}/)[0][0].to_f
113
- time.should > 100
125
+ time.should > 100.0
114
126
  end
115
127
 
116
128
  it "should report an increment" do
@@ -126,6 +138,17 @@ describe Instrumental::Agent, "enabled in test_mode" do
126
138
  wait
127
139
  @server.commands.join("\n").should include("notice #{tm.to_i} 0 Test note")
128
140
  end
141
+
142
+ it "should allow outgoing metrics to be stopped" do
143
+ tm = Time.now
144
+ @agent.increment("foo.bar", 1, tm)
145
+ @agent.stop
146
+ wait
147
+ @agent.increment("foo.baz", 1, tm)
148
+ wait
149
+ @server.commands.join("\n").should include("increment foo.baz 1 #{tm.to_i}")
150
+ @server.commands.join("\n").should_not include("increment foo.bar 1 #{tm.to_i}")
151
+ end
129
152
  end
130
153
 
131
154
  describe Instrumental::Agent, "enabled" do
@@ -135,20 +158,30 @@ describe Instrumental::Agent, "enabled" do
135
158
  end
136
159
 
137
160
  after do
161
+ @agent.stop
162
+ @agent = nil
138
163
  @server.stop
139
164
  end
140
165
 
141
- it "should connect to the server" do
166
+ it "should not connect to the server" do
167
+ wait
168
+ @server.connect_count.should == 0
169
+ end
170
+
171
+ it "should connect to the server after sending a metric" do
172
+ @agent.increment("test.foo")
142
173
  wait
143
174
  @server.connect_count.should == 1
144
175
  end
145
176
 
146
177
  it "should announce itself, and include version" do
178
+ @agent.increment("test.foo")
147
179
  wait
148
180
  @server.commands[0].should =~ /hello .*version /
149
181
  end
150
182
 
151
183
  it "should authenticate using the token" do
184
+ @agent.increment("test.foo")
152
185
  wait
153
186
  @server.commands[1].should == "authenticate test_token"
154
187
  end
@@ -267,10 +300,10 @@ describe Instrumental::Agent, "enabled" do
267
300
  end
268
301
 
269
302
  it "should return nil if the user overflows the MAX_BUFFER" do
270
- thread = @agent.instance_variable_get(:@thread)
271
- thread.kill
272
303
  1.upto(Instrumental::Agent::MAX_BUFFER) do
273
304
  @agent.increment("test").should == 1
305
+ thread = @agent.instance_variable_get(:@thread)
306
+ thread.kill
274
307
  end
275
308
  @agent.increment("test").should be_nil
276
309
  end
@@ -324,6 +357,17 @@ describe Instrumental::Agent, "enabled" do
324
357
  @server.commands.join("\n").should_not include("notice Test note")
325
358
  end
326
359
 
360
+ it "should allow outgoing metrics to be stopped" do
361
+ tm = Time.now
362
+ @agent.increment("foo.bar", 1, tm)
363
+ @agent.stop
364
+ wait
365
+ @agent.increment("foo.baz", 1, tm)
366
+ wait
367
+ @server.commands.join("\n").should include("increment foo.baz 1 #{tm.to_i}")
368
+ @server.commands.join("\n").should_not include("increment foo.bar 1 #{tm.to_i}")
369
+ end
370
+
327
371
  it "should allow flushing pending values to the server" do
328
372
  1.upto(100) { @agent.gauge('a', rand(50)) }
329
373
  @agent.instance_variable_get(:@queue).size.should >= 100
@@ -336,18 +380,20 @@ end
336
380
 
337
381
  describe Instrumental::Agent, "connection problems" do
338
382
  after do
383
+ @agent.stop
339
384
  @server.stop
340
385
  end
341
386
 
342
387
  it "should automatically reconnect on disconnect" do
343
388
  @server = TestServer.new
344
389
  @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
390
+ @agent.increment("reconnect_test", 1, 1234)
345
391
  wait
346
392
  @server.disconnect_all
347
- @agent.increment('reconnect_test', 1, 1234) # triggers reconnect
393
+ @agent.increment('reconnect_test', 1, 5678) # triggers reconnect
348
394
  wait
349
395
  @server.connect_count.should == 2
350
- @server.commands.last.should == "increment reconnect_test 1 1234"
396
+ @server.commands.last.should == "increment reconnect_test 1 5678"
351
397
  end
352
398
 
353
399
  it "should buffer commands when server is down" do
@@ -408,6 +454,11 @@ describe Instrumental::Agent, "enabled with sync option" do
408
454
  @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => true)
409
455
  end
410
456
 
457
+ after do
458
+ @agent.stop
459
+ @server.stop
460
+ end
461
+
411
462
  it "should send all data in synchronous mode" do
412
463
  with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
413
464
  5.times do |i|
@@ -421,4 +472,5 @@ describe Instrumental::Agent, "enabled with sync option" do
421
472
  @server.commands.should include("increment overflow_test 5 300")
422
473
  end
423
474
  end
475
+
424
476
  end
data/spec/test_server.rb CHANGED
@@ -13,36 +13,50 @@ class TestServer
13
13
  @connections = []
14
14
  @commands = []
15
15
  @host = 'localhost'
16
+ @main_thread = nil
17
+ @client_threads = []
18
+ @fd_to_thread = {}
16
19
  listen if @options[:listen]
17
20
  end
18
21
 
22
+
19
23
  def listen
20
24
  @port ||= 10001
21
25
  @server = TCPServer.new(port)
22
- Thread.new do
26
+ @main_thread = Thread.new do
23
27
  begin
24
28
  # puts "listening"
25
29
  loop do
26
- socket = @server.accept
27
- Thread.new do
28
- @connect_count += 1
29
- @connections << socket
30
+ client = @server.accept
31
+ @connections << client
32
+ @connect_count += 1
33
+ @fd_to_thread[client.to_i] = Thread.new(client) do |socket|
30
34
  # puts "connection received"
31
35
  loop do
32
- command = socket.gets.strip
33
- # puts "got: #{command}"
34
- commands << command
35
- if %w[hello authenticate].include?(command.split(' ')[0])
36
- if @options[:response]
37
- if @options[:authenticate]
38
- socket.puts "ok"
39
- else
40
- socket.puts "gtfo"
36
+ begin
37
+ command = ""
38
+ while (c = socket.read(1)) != "\n"
39
+ command << c unless c.nil?
40
+ end
41
+ if !command.empty?
42
+ # puts "got: #{command}"
43
+ commands << command
44
+ if %w[hello authenticate].include?(command.split(' ')[0])
45
+ if @options[:response]
46
+ if @options[:authenticate]
47
+ socket.puts "ok"
48
+ else
49
+ socket.puts "gtfo"
50
+ end
51
+ end
41
52
  end
42
53
  end
54
+ rescue Exception => e
55
+ break
43
56
  end
44
57
  end
45
58
  end
59
+ @client_threads << @fd_to_thread[client.to_i]
46
60
  end
47
61
  rescue Exception => err
48
62
  unless @stopping
@@ -67,10 +81,24 @@ class TestServer
67
81
  def stop
68
82
  @stopping = true
69
83
  disconnect_all
70
- @server.close if @server
84
+ @main_thread.kill if @main_thread
85
+ @main_thread = nil
86
+ @client_threads.each { |thread| thread.kill }
87
+ @client_threads = []
88
+ begin
89
+ @server.close if @server
90
+ rescue Exception => e
91
+ end
71
92
  end
72
93
 
73
94
  def disconnect_all
74
- @connections.each { |c| c.close rescue false }
95
+ @connections.each { |c|
96
+ if (thr = @fd_to_thread[c.to_i])
97
+ thr.kill
98
+ end
99
+ @fd_to_thread.delete(c.to_i)
100
+ c.close rescue false
101
+ }
102
+ @connections = []
75
103
  end
76
104
  end
metadata CHANGED
@@ -1,10 +1,15 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: instrumental_agent
3
- version: !ruby/object:Gem::Version
4
- version: 0.9.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 49
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 5
10
+ version: 0.9.5
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Elijah Miller
9
14
  - Christopher Zelenak
10
15
  - Kristopher Chambers
@@ -12,92 +17,118 @@ authors:
12
17
  autorequire:
13
18
  bindir: bin
14
19
  cert_chain: []
15
- date: 2012-03-06 00:00:00.000000000 Z
16
- dependencies:
17
- - !ruby/object:Gem::Dependency
18
- name: rake
19
- requirement: &70101951414580 !ruby/object:Gem::Requirement
20
- none: false
21
- requirements:
22
- - - ! '>='
23
- - !ruby/object:Gem::Version
24
- version: '0'
20
+
21
+ date: 2012-03-23 00:00:00 Z
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
25
24
  type: :development
26
25
  prerelease: false
27
- version_requirements: *70101951414580
28
- - !ruby/object:Gem::Dependency
29
- name: rspec
30
- requirement: &70101951413720 !ruby/object:Gem::Requirement
26
+ version_requirements: &id001 !ruby/object:Gem::Requirement
31
27
  none: false
32
- requirements:
33
- - - ~>
34
- - !ruby/object:Gem::Version
35
- version: '2.0'
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
35
+ requirement: *id001
36
+ name: rake
37
+ - !ruby/object:Gem::Dependency
36
38
  type: :development
37
39
  prerelease: false
38
- version_requirements: *70101951413720
39
- - !ruby/object:Gem::Dependency
40
- name: fuubar
41
- requirement: &70101951429080 !ruby/object:Gem::Requirement
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
41
  none: false
43
- requirements:
44
- - - ! '>='
45
- - !ruby/object:Gem::Version
46
- version: '0'
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 2
48
+ - 0
49
+ version: "2.0"
50
+ requirement: *id002
51
+ name: rspec
52
+ - !ruby/object:Gem::Dependency
47
53
  type: :development
48
54
  prerelease: false
49
- version_requirements: *70101951429080
50
- - !ruby/object:Gem::Dependency
51
- name: guard
52
- requirement: &70101951428440 !ruby/object:Gem::Requirement
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
53
56
  none: false
54
- requirements:
55
- - - ! '>='
56
- - !ruby/object:Gem::Version
57
- version: '0'
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirement: *id003
65
+ name: fuubar
66
+ - !ruby/object:Gem::Dependency
58
67
  type: :development
59
68
  prerelease: false
60
- version_requirements: *70101951428440
61
- - !ruby/object:Gem::Dependency
62
- name: guard-rspec
63
- requirement: &70101951427760 !ruby/object:Gem::Requirement
69
+ version_requirements: &id004 !ruby/object:Gem::Requirement
64
70
  none: false
65
- requirements:
66
- - - ! '>='
67
- - !ruby/object:Gem::Version
68
- version: '0'
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirement: *id004
79
+ name: guard
80
+ - !ruby/object:Gem::Dependency
69
81
  type: :development
70
82
  prerelease: false
71
- version_requirements: *70101951427760
72
- - !ruby/object:Gem::Dependency
73
- name: growl
74
- requirement: &70101951424880 !ruby/object:Gem::Requirement
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
75
84
  none: false
76
- requirements:
77
- - - ! '>='
78
- - !ruby/object:Gem::Version
79
- version: '0'
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirement: *id005
93
+ name: guard-rspec
94
+ - !ruby/object:Gem::Dependency
80
95
  type: :development
81
96
  prerelease: false
82
- version_requirements: *70101951424880
83
- - !ruby/object:Gem::Dependency
84
- name: rb-fsevent
85
- requirement: &70101951423500 !ruby/object:Gem::Requirement
97
+ version_requirements: &id006 !ruby/object:Gem::Requirement
86
98
  none: false
87
- requirements:
88
- - - ! '>='
89
- - !ruby/object:Gem::Version
90
- version: '0'
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirement: *id006
107
+ name: growl
108
+ - !ruby/object:Gem::Dependency
91
109
  type: :development
92
110
  prerelease: false
93
- version_requirements: *70101951423500
111
+ version_requirements: &id007 !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ hash: 3
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ requirement: *id007
121
+ name: rb-fsevent
94
122
  description: Track anything.
95
- email:
123
+ email:
96
124
  - support@instrumentalapp.com
97
125
  executables: []
126
+
98
127
  extensions: []
128
+
99
129
  extra_rdoc_files: []
100
- files:
130
+
131
+ files:
101
132
  - .gitignore
102
133
  - .rspec
103
134
  - CHANGELOG.md
@@ -116,35 +147,38 @@ files:
116
147
  - spec/test_server.rb
117
148
  homepage: http://github.com/fastestforward/instrumental_agent
118
149
  licenses: []
150
+
119
151
  post_install_message:
120
152
  rdoc_options: []
121
- require_paths:
153
+
154
+ require_paths:
122
155
  - lib
123
- required_ruby_version: !ruby/object:Gem::Requirement
156
+ required_ruby_version: !ruby/object:Gem::Requirement
124
157
  none: false
125
- requirements:
126
- - - ! '>='
127
- - !ruby/object:Gem::Version
128
- version: '0'
129
- segments:
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ hash: 3
162
+ segments:
130
163
  - 0
131
- hash: -1711513508284611167
132
- required_rubygems_version: !ruby/object:Gem::Requirement
164
+ version: "0"
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
166
  none: false
134
- requirements:
135
- - - ! '>='
136
- - !ruby/object:Gem::Version
137
- version: '0'
138
- segments:
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ hash: 3
171
+ segments:
139
172
  - 0
140
- hash: -1711513508284611167
173
+ version: "0"
141
174
  requirements: []
175
+
142
176
  rubyforge_project:
143
177
  rubygems_version: 1.8.10
144
178
  signing_key:
145
179
  specification_version: 3
146
180
  summary: Agent for reporting data to instrumentalapp.com
147
- test_files:
181
+ test_files:
148
182
  - spec/agent_spec.rb
149
183
  - spec/spec_helper.rb
150
184
  - spec/test_server.rb