instrumental_agent 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require 'bundler/gem_tasks'
2
+ require "rspec/core/rake_task"
3
+
4
+ task :default => 'spec'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = 'spec/*_spec.rb'
8
+ spec.rspec_opts = ['--backtrace']
9
+ end
@@ -14,8 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
16
  s.require_paths = ["lib"]
17
-
18
- s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
17
+ s.add_development_dependency(%q<rake>, [">= 0"])
19
18
  s.add_development_dependency(%q<rspec>, ["~> 2.0"])
20
19
  s.add_development_dependency(%q<guard>, [">= 0"])
21
20
  s.add_development_dependency(%q<guard-rspec>, [">= 0"])
@@ -1,23 +1,21 @@
1
1
  require 'instrumental/rack/middleware'
2
2
  require 'instrumental/version'
3
- require 'eventmachine'
4
3
  require 'logger'
4
+ require 'thread'
5
+ require 'socket'
5
6
 
6
7
  # Sets up a connection to the collector.
7
8
  #
8
9
  # Instrumental::Agent.new(API_KEY)
9
10
  module Instrumental
10
11
  class Agent
12
+ BACKOFF = 2.0
13
+ MAX_RECONNECT_DELAY = 15
14
+ MAX_BUFFER = 100
15
+
11
16
  attr_accessor :host, :port
12
17
  attr_reader :connection, :enabled
13
18
 
14
- def self.start_reactor
15
- unless EM.reactor_running?
16
- logger.debug 'Starting EventMachine reactor'
17
- Thread.new { EM.run }
18
- end
19
- end
20
-
21
19
  def self.logger=(l)
22
20
  @logger = l
23
21
  end
@@ -36,69 +34,12 @@ module Instrumental
36
34
  inst
37
35
  end
38
36
 
39
- module ServerConnection
40
- BACKOFF = 2
41
- MAX_RECONNECT_DELAY = 5
42
- MAX_BUFFER = 10
43
-
44
- attr_accessor :agent
45
- attr_reader :connected, :failures, :buffer
46
-
47
- def initialize(agent, api_key)
48
- @agent = agent
49
- @buffer = []
50
- @api_key = api_key
51
- end
52
-
53
- def logger
54
- agent.logger
55
- end
56
-
57
- def connection_completed
58
- logger.info "connected to collector"
59
- @connected = true
60
- @failures = 0
61
- send_data("hello version #{Instrumental::VERSION}\n")
62
- send_data("authenticate #{@api_key}\n") if @api_key
63
- dropped = @buffer.dup
64
- @buffer = []
65
- dropped.each do |msg|
66
- send_data(msg)
67
- end
68
- end
69
-
70
- def receive_data(data)
71
- logger.debug "Received: #{data.chomp}"
72
- end
73
-
74
- def send_data(data)
75
- if @connected
76
- super
77
- else
78
- if @buffer.size < MAX_BUFFER
79
- @buffer << data
80
- end
81
- end
82
- end
83
-
84
- def unbind
85
- @connected = false
86
- @failures = @failures.to_i + 1
87
- delay = [@failures ** BACKOFF / 10.to_f, MAX_RECONNECT_DELAY].min
88
- logger.info "disconnected, reconnect in #{delay}..."
89
- EM::Timer.new(delay) do
90
- reconnect(agent.host, agent.port)
91
- end
92
- end
93
-
94
- end
95
-
96
37
  # Sets up a connection to the collector.
97
38
  #
98
39
  # Instrumental::Agent.new(API_KEY)
99
40
  # Instrumental::Agent.new(API_KEY, :collector => 'hostname:port')
100
41
  def initialize(api_key, options = {})
101
- default_options = { :start_reactor => true, :enabled => true }
42
+ default_options = { :enabled => true }
102
43
  options = default_options.merge(options)
103
44
  @api_key = api_key
104
45
  if options[:collector]
@@ -110,15 +51,10 @@ module Instrumental
110
51
  end
111
52
 
112
53
  @enabled = options[:enabled]
113
-
114
54
  if @enabled
115
- if options[:start_reactor]
116
- self.class.start_reactor
117
- end
118
-
119
- EM.next_tick do
120
- @connection = EM.connect host, port, ServerConnection, self, api_key
121
- end
55
+ @failures = 0
56
+ @queue = Queue.new
57
+ start_connection_thread
122
58
  end
123
59
  end
124
60
 
@@ -170,13 +106,71 @@ module Instrumental
170
106
  def send_command(cmd, *args)
171
107
  if enabled?
172
108
  cmd = "%s %s\n" % [cmd, args.collect(&:to_s).join(" ")]
173
- logger.debug "Sending: #{cmd.chomp}"
174
- EM.next_tick do
175
- connection.send_data(cmd)
109
+ if @queue.size < MAX_BUFFER
110
+ logger.debug "Queueing: #{cmd.chomp}"
111
+ @queue << cmd
112
+ else
113
+ logger.warn "Dropping command, queue full(#{@queue.size}): #{cmd.chomp}"
176
114
  end
177
115
  end
178
116
  end
179
117
 
118
+ def test_server_connection
119
+ # FIXME: Test connection state hack
120
+ begin
121
+ @socket.read_nonblock(1) # TODO: put data back?
122
+ rescue Errno::EAGAIN
123
+ # nop
124
+ end
125
+ end
180
126
 
127
+ def start_connection_thread
128
+ @thread = Thread.new do
129
+ begin
130
+ @socket = TCPSocket.new(host, port)
131
+ @failures = 0
132
+ logger.info "connected to collector"
133
+ @socket.puts "hello version 0.0"
134
+ @socket.puts "authenticate #{@api_key}"
135
+ loop do
136
+ command_and_args = @queue.pop
137
+ begin
138
+ test_server_connection
139
+ rescue Exception => err
140
+ @queue << command_and_args # connection dead, requeue
141
+ raise err
142
+ end
143
+
144
+ if command_and_args == 'exit'
145
+ logger.info "exiting, #{@queue.size} commands remain"
146
+ Thread.exit
147
+ else
148
+ logger.debug "Sending: #{command_and_args.chomp}"
149
+ @socket.puts command_and_args
150
+ end
151
+ end
152
+ rescue Exception => err
153
+ logger.error err.to_s
154
+ # FIXME: not always a disconnect
155
+ @failures += 1
156
+ delay = [(@failures - 1) ** BACKOFF, MAX_RECONNECT_DELAY].min
157
+ logger.info "disconnected, reconnect in #{delay}..."
158
+ sleep delay
159
+ retry
160
+ end
161
+ end
162
+ at_exit do
163
+ if !@queue.empty? && @thread.alive?
164
+ if @failures > 0
165
+ logger.info "exit received but disconnected, dropping #{@queue.size} commands"
166
+ @thread.kill
167
+ else
168
+ logger.info "exit received, #{@queue.size} commands to be sent"
169
+ @queue << 'exit'
170
+ @thread.join
171
+ end
172
+ end
173
+ end
174
+ end
181
175
  end
182
176
  end
@@ -1,3 +1,3 @@
1
1
  module Instrumental
2
- VERSION = "0.1.6"
2
+ VERSION = "0.2.0"
3
3
  end
data/spec/agent_spec.rb CHANGED
@@ -1,84 +1,97 @@
1
1
  require 'spec_helper'
2
2
 
3
+ def wait
4
+ sleep 0.2 # FIXME: hack
5
+ end
6
+
3
7
  describe Instrumental::Agent, "disabled" do
4
8
  before do
5
- random_port = Time.now.to_i % rand(2000)
6
- base_port = 4000
7
- @port = base_port + random_port
8
- TestServer.start(@port)
9
+ @server = TestServer.new
10
+ @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :enabled => false)
9
11
  end
10
12
 
11
13
  after do
12
- TestServer.stop
14
+ @server.stop
13
15
  end
14
16
 
15
- subject { Instrumental::Agent.new('test_token', :collector => "127.0.0.1:#{@port}", :enabled => false) }
17
+ it "should not connect to the server" do
18
+ wait
19
+ @server.connect_count.should == 0
20
+ end
16
21
 
17
- it 'should not connect to the server' do
18
- subject.gauge('gauge_test', 123)
19
- EM.next do
20
- TestServer.last.should be_nil
21
- end
22
+ it "should not connect to the server" do
23
+ wait
24
+ @agent.gauge('disabled_test', 1)
25
+ wait
26
+ @server.connect_count.should == 0
22
27
  end
23
28
 
24
29
  end
25
30
 
26
- describe Instrumental::Agent do
31
+ describe Instrumental::Agent, "enabled" do
27
32
  before do
28
- random_port = Time.now.to_i % rand(2000)
29
- base_port = 4000
30
- @port = base_port + random_port
31
- TestServer.start(@port)
33
+ @server = TestServer.new
34
+ @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port)
32
35
  end
33
36
 
34
37
  after do
35
- TestServer.stop
38
+ @server.stop
36
39
  end
37
40
 
38
- subject { Instrumental::Agent.new('test_token', :collector => "127.0.0.1:#{@port}") }
41
+ it "should connect to the server" do
42
+ wait
43
+ @server.connect_count.should == 1
44
+ end
39
45
 
40
- it 'should announce itself including version' do
41
- subject.gauge('gauge_test', 123)
42
- EM.next do
43
- TestServer.last.buffer.first.should match(/hello.*version/)
44
- end
46
+ it "should announce itself, and include version" do
47
+ wait
48
+ @server.commands[0].should =~ /hello .*version /
45
49
  end
46
50
 
47
- it 'should authenticate using the token' do
48
- subject.gauge('gauge_test', 123)
49
- EM.next do
50
- TestServer.last.buffer[1].should == "authenticate test_token"
51
- end
51
+ it "should authenticate using the token" do
52
+ wait
53
+ @server.commands[1].should == "authenticate test_token"
52
54
  end
53
55
 
54
- it 'should report a gauge to the collector' do
56
+ it "should report a gauge" do
55
57
  now = Time.now
56
- subject.gauge('gauge_test', 123)
57
- EM.next do
58
- TestServer.last.buffer.last.should == "gauge gauge_test 123 #{now.to_i}"
59
- end
58
+ @agent.gauge('gauge_test', 123)
59
+ wait
60
+ @server.commands.last.should == "gauge gauge_test 123 #{now.to_i}"
60
61
  end
61
62
 
62
- it 'should report a gauge to the collector with a set time' do
63
- subject.gauge('gauge_test', 123, 555)
64
- EM.next do
65
- TestServer.last.buffer.last.should == 'gauge gauge_test 123 555'
66
- end
63
+ it "should report a gauge with a set time" do
64
+ @agent.gauge('gauge_test', 123, 555)
65
+ wait
66
+ @server.commands.last.should == "gauge gauge_test 123 555"
67
67
  end
68
68
 
69
- it "should automatically reconnect" do
70
- EM.next do
71
- subject.gauge('gauge_test', 123, 555)
72
- end
73
- EM.next do
74
- subject.connection.close_connection(false)
75
- end
76
- EM.next do
77
- subject.gauge('gauge_test', 444, 555)
78
- end
79
- EM.next do
80
- TestServer.last.buffer.last.should == 'gauge gauge_test 444 555'
81
- end
69
+ it "should report an increment" do
70
+ now = Time.now
71
+ @agent.increment("increment_test")
72
+ wait
73
+ @server.commands.last.should == "increment increment_test 1 #{now.to_i}"
82
74
  end
83
75
 
76
+ it "should report an increment a value" do
77
+ now = Time.now
78
+ @agent.increment("increment_test", 2)
79
+ wait
80
+ @server.commands.last.should == "increment increment_test 2 #{now.to_i}"
81
+ end
82
+
83
+ it "should report an increment with a set time" do
84
+ @agent.increment('increment_test', 1, 555)
85
+ wait
86
+ @server.commands.last.should == "increment increment_test 1 555"
87
+ end
88
+
89
+ it "should automatically reconnect" do
90
+ wait
91
+ @server.disconnect_all
92
+ @agent.increment('reconnect_test', 1, 1234) # triggers reconnect
93
+ wait
94
+ @server.connect_count.should == 2
95
+ @server.commands.last.should == "increment reconnect_test 1 1234"
96
+ end
84
97
  end
data/spec/spec_helper.rb CHANGED
@@ -6,57 +6,9 @@ require 'test_server'
6
6
  RSpec.configure do |config|
7
7
 
8
8
  config.before(:all) do
9
- unless EM.reactor_running?
10
- EM.error_handler { |*args|
11
- puts "\n"
12
- puts "*" * 80
13
- puts "EVENTMACHINE ERROR: #{args.inspect}\n"
14
- puts args.first.backtrace.join("\n")
15
- puts "*" * 80
16
- puts "\n"
17
- }
18
- Thread.new { EM.run }
19
- sleep(0.001) while !EM.reactor_running?
20
- end
21
9
  end
22
10
 
23
11
  config.after(:all) do
24
12
  end
25
13
 
26
14
  end
27
-
28
-
29
- module EM
30
-
31
- def self.next(&block)
32
- EM.wait_for_events
33
- mtx = Mutex.new
34
- exc = nil
35
- EM.next_tick do
36
- mtx.synchronize {
37
- begin
38
- yield
39
- rescue Exception => e
40
- exc = e
41
- end
42
- }
43
- end
44
- EM.wait_for_events
45
- mtx.lock
46
- raise exc if exc
47
- true
48
- end
49
-
50
- def self.wait_for_events
51
- raise "Reactor is not running" unless EM.reactor_running?
52
- while EM.reactor_running? && !(@next_tick_queue && @next_tick_queue.empty? && @timers && @timers.empty?)
53
- sleep(0.01) # This value is REALLY important
54
- # Too low and it doesn't allow
55
- # local socket events to finish
56
- # processing
57
- # Too high and it makes the tests
58
- # slow.
59
- end
60
- raise @wrapped_exception if @wrapped_exception
61
- end
62
- end
data/spec/test_server.rb CHANGED
@@ -1,85 +1,54 @@
1
- module TestServer
2
- CMUTEX = Mutex.new
3
-
4
- def self.start_reactor
5
- Thread.new { EM.run } unless EM.reactor_running?
6
- end
7
-
8
- def self.start(port)
9
- start_reactor
10
- unless @sig
11
- EM.next_tick {
12
- @sig = EventMachine.start_server "127.0.0.1", port, TestServer
13
- }
14
- end
15
- end
16
-
17
- def self.stop
18
- if (sig=@sig)
19
- EM.next_tick {
20
- EventMachine.stop_server sig
21
- }
22
- @sig = nil
23
- end
24
- end
25
-
26
- def self.connections
27
- CMUTEX.synchronize do
28
- @connections ||= []
29
- @connections.dup
30
- end
31
- end
32
-
33
- def self.add_connection(conn)
34
- CMUTEX.synchronize do
35
- @connections ||= []
36
- @connections << conn
37
- end
38
- end
39
-
40
- def self.remove_connection(conn)
41
- CMUTEX.synchronize do
42
- @connections ||= []
43
- @connections.delete(conn)
1
+ class TestServer
2
+ attr_accessor :host, :port, :connect_count, :commands
3
+
4
+ def initialize
5
+ @connect_count = 0
6
+ @connections = []
7
+ @commands = []
8
+ listen
9
+ end
10
+
11
+ def listen
12
+ @port ||= 10001
13
+ @server = TCPServer.new(port)
14
+ Thread.new do
15
+ begin
16
+ # puts "listening"
17
+ socket = @server.accept
18
+ @connect_count += 1
19
+ @connections << socket
20
+ # puts "connection received"
21
+ loop do
22
+ command = socket.gets.strip
23
+ # puts "got: #{command}"
24
+ commands << command
25
+ end
26
+ rescue Exception => err
27
+ unless @stopping
28
+ # puts "EXCEPTION:", err unless @stopping
29
+ retry
30
+ end
31
+ end
44
32
  end
33
+ # puts "server up"
34
+ rescue Exception => err
35
+ # FIXME: doesn't seem to be detecting failures of listen
36
+ puts "failed to get port"
37
+ @port += 1
38
+ retry
45
39
  end
46
40
 
47
- def self.last
48
- connections.last
49
- end
50
-
51
- def post_init
52
- TestServer.add_connection(self)
53
- end
54
-
55
- def receive_data data
56
- buffer_response(data)
57
- end
58
-
59
- def unbind
60
- TestServer.remove_connection(self)
41
+ def host_and_port
42
+ "#{host}:#{port}"
61
43
  end
62
44
 
63
- def last_message
64
- buffer.last
45
+ def stop
46
+ @stopping = true
47
+ disconnect_all
48
+ @server.close # FIXME: necessary?
65
49
  end
66
50
 
67
- def buffer
68
- @buffer ||= []
69
- @buffer.dup
70
- end
71
-
72
- def clear_buffer!
73
- @buffer = []
74
- end
75
-
76
- def buffer_response(dt)
77
- @buffer ||= []
78
- dt.split(/\n/).each do |measurement|
79
- @buffer << measurement
80
- end
81
- dt
51
+ def disconnect_all
52
+ @connections.each { |c| c.close rescue false }
82
53
  end
83
54
  end
84
-
85
-
metadata CHANGED
@@ -1,92 +1,120 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: instrumental_agent
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.6
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Elijah Miller
9
14
  - Christopher Zelenak
10
15
  - Kristopher Chambers
11
16
  autorequire:
12
17
  bindir: bin
13
18
  cert_chain: []
14
- date: 2011-11-14 00:00:00.000000000Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: eventmachine
18
- requirement: &70095834702400 !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ! '>='
22
- - !ruby/object:Gem::Version
23
- version: '0'
24
- type: :runtime
19
+
20
+ date: 2011-11-15 00:00:00 -05:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: rake
25
25
  prerelease: false
26
- version_requirements: *70095834702400
27
- - !ruby/object:Gem::Dependency
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
28
38
  name: rspec
29
- requirement: &70095834701400 !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
30
41
  none: false
31
- requirements:
42
+ requirements:
32
43
  - - ~>
33
- - !ruby/object:Gem::Version
34
- version: '2.0'
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 2
48
+ - 0
49
+ version: "2.0"
35
50
  type: :development
36
- prerelease: false
37
- version_requirements: *70095834701400
38
- - !ruby/object:Gem::Dependency
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
39
53
  name: guard
40
- requirement: &70095834700420 !ruby/object:Gem::Requirement
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
41
56
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
46
64
  type: :development
47
- prerelease: false
48
- version_requirements: *70095834700420
49
- - !ruby/object:Gem::Dependency
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
50
67
  name: guard-rspec
51
- requirement: &70095834699460 !ruby/object:Gem::Requirement
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
52
70
  none: false
53
- requirements:
54
- - - ! '>='
55
- - !ruby/object:Gem::Version
56
- version: '0'
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
57
78
  type: :development
58
- prerelease: false
59
- version_requirements: *70095834699460
60
- - !ruby/object:Gem::Dependency
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
61
81
  name: growl_notify
62
- requirement: &70095834698100 !ruby/object:Gem::Requirement
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
63
84
  none: false
64
- requirements:
65
- - - ! '>='
66
- - !ruby/object:Gem::Version
67
- version: '0'
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
68
92
  type: :development
69
- prerelease: false
70
- version_requirements: *70095834698100
71
- - !ruby/object:Gem::Dependency
93
+ version_requirements: *id005
94
+ - !ruby/object:Gem::Dependency
72
95
  name: rb-fsevent
73
- requirement: &70095834697380 !ruby/object:Gem::Requirement
96
+ prerelease: false
97
+ requirement: &id006 !ruby/object:Gem::Requirement
74
98
  none: false
75
- requirements:
76
- - - ! '>='
77
- - !ruby/object:Gem::Version
78
- version: '0'
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
79
106
  type: :development
80
- prerelease: false
81
- version_requirements: *70095834697380
107
+ version_requirements: *id006
82
108
  description: Keep track of anything.
83
- email:
109
+ email:
84
110
  - support@instrumentalapp.com
85
- executables:
111
+ executables:
86
112
  - instrument_server
87
113
  extensions: []
114
+
88
115
  extra_rdoc_files: []
89
- files:
116
+
117
+ files:
90
118
  - .gitignore
91
119
  - Gemfile
92
120
  - Guardfile
@@ -104,31 +132,41 @@ files:
104
132
  - spec/agent_spec.rb
105
133
  - spec/spec_helper.rb
106
134
  - spec/test_server.rb
135
+ has_rdoc: true
107
136
  homepage: http://github.com/fastestforward/instrumental_agent
108
137
  licenses: []
138
+
109
139
  post_install_message:
110
140
  rdoc_options: []
111
- require_paths:
141
+
142
+ require_paths:
112
143
  - lib
113
- required_ruby_version: !ruby/object:Gem::Requirement
144
+ required_ruby_version: !ruby/object:Gem::Requirement
114
145
  none: false
115
- requirements:
116
- - - ! '>='
117
- - !ruby/object:Gem::Version
118
- version: '0'
119
- required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ hash: 3
150
+ segments:
151
+ - 0
152
+ version: "0"
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
154
  none: false
121
- requirements:
122
- - - ! '>='
123
- - !ruby/object:Gem::Version
124
- version: '0'
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ hash: 3
159
+ segments:
160
+ - 0
161
+ version: "0"
125
162
  requirements: []
163
+
126
164
  rubyforge_project:
127
- rubygems_version: 1.8.10
165
+ rubygems_version: 1.6.1
128
166
  signing_key:
129
167
  specification_version: 3
130
168
  summary: Agent for reporting data to instrumentalapp.com
131
- test_files:
169
+ test_files:
132
170
  - spec/agent_spec.rb
133
171
  - spec/spec_helper.rb
134
172
  - spec/test_server.rb