instrumental_agent 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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