instrumental_agent 0.11.1 → 0.12.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.
@@ -1,3 +1,10 @@
1
+ ### 0.12.0 [July 30th, 2012]
2
+ * Add timeout to socket flush, fixes rare issue on REE/Linux
3
+ * Send only one buffer full warning
4
+ * Agent instances use global logger more consistently
5
+ * Minor code cleanups
6
+ * Remove rack-middleware
7
+
1
8
  ### 0.11.1 [July 19th, 2012]
2
9
  * Make error messages easily locatable in logs
3
10
 
@@ -1,45 +1,10 @@
1
- require 'instrumental/rack/middleware'
2
1
  require 'instrumental/version'
2
+ require 'instrumental/system_timer'
3
3
  require 'logger'
4
4
  require 'thread'
5
5
  require 'socket'
6
6
 
7
- if RUBY_VERSION < "1.9" && RUBY_PLATFORM != "java"
8
- timeout_lib = nil
9
- ["SystemTimer", "system_timer"].each do |lib|
10
- begin
11
- unless timeout_lib
12
- gem lib
13
- require "system_timer"
14
- timeout_lib = SystemTimer
15
- end
16
- rescue Exception => e
17
- end
18
- end
19
- if !timeout_lib
20
- puts <<-EOMSG
21
- WARNING:: You do not currently have system_timer installed.
22
- It is strongly advised that you install this gem when using
23
- instrumental_agent with Ruby 1.8.x. You can install it in
24
- your Gemfile via:
25
- gem 'system_timer'
26
- or manually via:
27
- gem install system_timer
28
- EOMSG
29
- require 'timeout'
30
- InstrumentalTimeout = Timeout
31
- else
32
- InstrumentalTimeout = timeout_lib
33
- end
34
- else
35
- require 'timeout'
36
- InstrumentalTimeout = Timeout
37
- end
38
-
39
7
 
40
- # Sets up a connection to the collector.
41
- #
42
- # Instrumental::Agent.new(API_KEY)
43
8
  module Instrumental
44
9
  class Agent
45
10
  BACKOFF = 2.0
@@ -64,16 +29,6 @@ module Instrumental
64
29
  @logger
65
30
  end
66
31
 
67
- def self.all
68
- @agents ||= []
69
- end
70
-
71
- def self.new(*args)
72
- inst = super
73
- all << inst
74
- inst
75
- end
76
-
77
32
  # Sets up a connection to the collector.
78
33
  #
79
34
  # Instrumental::Agent.new(API_KEY)
@@ -205,7 +160,7 @@ module Instrumental
205
160
  end
206
161
 
207
162
  def logger
208
- @logger ||= self.class.logger
163
+ @logger || self.class.logger
209
164
  end
210
165
 
211
166
  # Stopping the agent will immediately stop all communication
@@ -290,10 +245,15 @@ module Instrumental
290
245
 
291
246
  cmd = "%s %s\n" % [cmd, args.collect { |a| a.to_s }.join(" ")]
292
247
  if @queue.size < MAX_BUFFER
248
+ @queue_full_warning = false
293
249
  logger.debug "Queueing: #{cmd.chomp}"
294
250
  queue_message(cmd, { :synchronous => @synchronous })
295
251
  else
296
- logger.warn "Dropping command, queue full(#{@queue.size}): #{cmd.chomp}"
252
+ if !@queue_full_warning
253
+ @queue_full_warning = true
254
+ logger.warn "Queue full(#{@queue.size}), dropping commands..."
255
+ end
256
+ logger.debug "Dropping command, queue full(#{@queue.size}): #{cmd.chomp}"
297
257
  nil
298
258
  end
299
259
  end
@@ -320,9 +280,8 @@ module Instrumental
320
280
  end
321
281
 
322
282
  def test_connection
323
- # FIXME: Test connection state hack
324
283
  begin
325
- @socket.read_nonblock(1) # TODO: put data back?
284
+ @socket.read_nonblock(1)
326
285
  rescue Errno::EAGAIN
327
286
  # noop
328
287
  end
@@ -358,7 +317,7 @@ module Instrumental
358
317
  logger.info "connecting to collector"
359
318
  @socket = with_timeout(CONNECT_TIMEOUT) { TCPSocket.new(host, port) }
360
319
  logger.info "connected to collector at #{host}:#{port}"
361
- send_with_reply_timeout "hello version #{Instrumental::VERSION} hostname #{Socket.gethostname}"
320
+ send_with_reply_timeout "hello version #{Instrumental::VERSION} hostname #{Socket.gethostname} pid #{Process.pid}"
362
321
  send_with_reply_timeout "authenticate #{@api_key}"
363
322
  @failures = 0
364
323
  loop do
@@ -418,7 +377,11 @@ module Instrumental
418
377
  def disconnect
419
378
  if connected?
420
379
  logger.info "Disconnecting..."
421
- @socket.flush
380
+ begin
381
+ with_timeout(EXIT_FLUSH_TIMEOUT) { @socket.flush }
382
+ rescue Timeout::Error
383
+ logger.info "Timed out flushing socket..."
384
+ end
422
385
  @socket.close
423
386
  end
424
387
  @socket = nil
@@ -0,0 +1,31 @@
1
+ if RUBY_VERSION < "1.9" && RUBY_PLATFORM != "java"
2
+ timeout_lib = nil
3
+ ["SystemTimer", "system_timer"].each do |lib|
4
+ begin
5
+ unless timeout_lib
6
+ gem lib
7
+ require "system_timer"
8
+ timeout_lib = SystemTimer
9
+ end
10
+ rescue Exception => e
11
+ end
12
+ end
13
+ if !timeout_lib
14
+ puts <<-EOMSG
15
+ WARNING:: You do not currently have system_timer installed.
16
+ It is strongly advised that you install this gem when using
17
+ instrumental_agent with Ruby 1.8.x. You can install it in
18
+ your Gemfile via:
19
+ gem 'system_timer'
20
+ or manually via:
21
+ gem install system_timer
22
+ EOMSG
23
+ require 'timeout'
24
+ InstrumentalTimeout = Timeout
25
+ else
26
+ InstrumentalTimeout = timeout_lib
27
+ end
28
+ else
29
+ require 'timeout'
30
+ InstrumentalTimeout = Timeout
31
+ end
@@ -1,3 +1,3 @@
1
1
  module Instrumental
2
- VERSION = '0.11.1'
2
+ VERSION = '0.12.0'
3
3
  end
@@ -76,7 +76,7 @@ describe Instrumental::Agent, "enabled" do
76
76
  it "should announce itself, and include version" do
77
77
  @agent.increment("test.foo")
78
78
  wait
79
- @server.commands[0].should =~ /hello .*version .* hostname .*/
79
+ @server.commands[0].should =~ /hello .*version .* hostname .* pid .*/
80
80
  end
81
81
 
82
82
  it "should authenticate using the token" do
@@ -307,6 +307,7 @@ describe Instrumental::Agent, "connection problems" do
307
307
  @agent.increment("reconnect_test", 1, 1234)
308
308
  wait
309
309
  @server.disconnect_all
310
+ wait
310
311
  @agent.increment('reconnect_test', 1, 5678) # triggers reconnect
311
312
  wait
312
313
  @server.connect_count.should == 2
@@ -340,6 +341,21 @@ describe Instrumental::Agent, "connection problems" do
340
341
  @agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
341
342
  end
342
343
 
344
+ it "should warn once when buffer is full" do
345
+ with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
346
+ @server = TestServer.new(:listen => false)
347
+ @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
348
+ wait
349
+ @agent.logger.should_receive(:warn).with(/Queue full/).once
350
+
351
+ @agent.increment('buffer_full_warn_test', 1, 1234)
352
+ @agent.increment('buffer_full_warn_test', 1, 1234)
353
+ @agent.increment('buffer_full_warn_test', 1, 1234)
354
+ @agent.increment('buffer_full_warn_test', 1, 1234)
355
+ @agent.increment('buffer_full_warn_test', 1, 1234)
356
+ end
357
+ end
358
+
343
359
  it "should send commands in a short-lived process" do
344
360
  @server = TestServer.new
345
361
  @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
@@ -386,6 +402,23 @@ describe Instrumental::Agent, "connection problems" do
386
402
  end
387
403
  end
388
404
  end
405
+
406
+ it "should not wait longer than EXIT_FLUSH_TIMEOUT to attempt flushing the socket when disconnecting" do
407
+ @server = TestServer.new
408
+ @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
409
+ @agent.increment('foo', 1)
410
+ wait
411
+ @agent.instance_variable_get(:@socket).should_receive(:flush).and_return {
412
+ r, w = IO.pipe
413
+ IO.select([r]) # mimic an endless blocking select poll
414
+ }
415
+ with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
416
+ tm = Time.now.to_f
417
+ @agent.cleanup
418
+ diff = Time.now.to_f - tm
419
+ diff.should <= 3
420
+ end
421
+ end
389
422
  end
390
423
 
391
424
  describe Instrumental::Agent, "enabled with sync option" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instrumental_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-07-19 00:00:00.000000000 Z
15
+ date: 2012-07-30 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rake
@@ -143,7 +143,7 @@ files:
143
143
  - instrumental_agent.gemspec
144
144
  - lib/instrumental/agent.rb
145
145
  - lib/instrumental/capistrano.rb
146
- - lib/instrumental/rack/middleware.rb
146
+ - lib/instrumental/system_timer.rb
147
147
  - lib/instrumental/version.rb
148
148
  - lib/instrumental_agent.rb
149
149
  - spec/agent_spec.rb
@@ -163,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
163
  version: '0'
164
164
  segments:
165
165
  - 0
166
- hash: 891178819189974589
166
+ hash: -1710263125539985150
167
167
  required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  none: false
169
169
  requirements:
@@ -172,10 +172,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
172
  version: '0'
173
173
  segments:
174
174
  - 0
175
- hash: 891178819189974589
175
+ hash: -1710263125539985150
176
176
  requirements: []
177
177
  rubyforge_project:
178
- rubygems_version: 1.8.24
178
+ rubygems_version: 1.8.21
179
179
  signing_key:
180
180
  specification_version: 3
181
181
  summary: Agent for reporting data to instrumentalapp.com
@@ -1,7 +0,0 @@
1
- module Instrumental
2
- class Middleware
3
- def self.boot
4
- Instrumental::Agent.logger.warn "The Instrumental Rails middlware has been removed - contact support@instrumentalapp.com for more information"
5
- end
6
- end
7
- end