instrumental_agent 0.1.6 → 0.2.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/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