instrumental_agent 0.12.7 → 0.13.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,3 @@
1
1
  module Instrumental
2
- VERSION = "0.12.7"
2
+ VERSION = "0.13.0"
3
3
  end
data/spec/agent_spec.rb CHANGED
@@ -1,460 +1,485 @@
1
1
  require 'spec_helper'
2
2
 
3
- def wait
4
- sleep 0.2 # FIXME: hack
3
+ def wait(n=0.2)
4
+ sleep n # FIXME: hack
5
5
  end
6
6
 
7
- describe Instrumental::Agent, "disabled" do
8
- before do
9
- Instrumental::Agent.logger.level = Logger::UNKNOWN
10
- @server = TestServer.new
11
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :enabled => false)
12
- end
7
+ FORK_SUPPORTED = begin
8
+ Process.wait(fork { true })
9
+ true
10
+ rescue Exception => e
11
+ false
12
+ end
13
13
 
14
- after do
15
- @agent.stop
16
- @agent = nil
17
- @server.stop
18
- end
19
14
 
20
- it "should not connect to the server" do
21
- wait
22
- @server.connect_count.should == 0
23
- end
24
15
 
25
- it "should not connect to the server after receiving a metric" do
26
- wait
27
- @agent.gauge('disabled_test', 1)
28
- wait
29
- @server.connect_count.should == 0
30
- end
16
+ shared_examples "Instrumental Agent" do
17
+ context do
31
18
 
32
- it "should no op on flush without reconnect" do
33
- 1.upto(100) { @agent.gauge('disabled_test', 1) }
34
- @agent.flush(false)
35
- wait
36
- @server.commands.should be_empty
37
- end
19
+ # Inferred:
20
+ # secure? and verify_cert? are set
38
21
 
39
- it "should no op on flush with reconnect" do
40
- 1.upto(100) { @agent.gauge('disabled_test', 1) }
41
- @agent.flush(true)
42
- wait
43
- @server.commands.should be_empty
44
- end
22
+ # Agent options
23
+ let(:enabled) { true }
24
+ let(:synchronous) { false }
25
+ let(:token) { 'test_token' }
26
+ let(:agent) { Instrumental::Agent.new(token, :collector => server.host_and_port, :synchronous => synchronous, :enabled => enabled, :secure => secure?, :verify_cert => verify_cert?) }
45
27
 
46
- it "should no op on an empty flush" do
47
- @agent.flush(true)
48
- wait
49
- @server.commands.should be_empty
50
- end
28
+ # Server options
29
+ let(:listen) { true }
30
+ let(:response) { true }
31
+ let(:authenticate) { true }
32
+ let(:server) { TestServer.new(:listen => listen, :authenticate => authenticate, :response => response, :secure => secure?) }
51
33
 
52
- it "should send metrics to logger" do
53
- now = Time.now
54
- @agent.logger.should_receive(:debug).with("gauge metric 1 #{now.to_i} 1")
55
- @agent.gauge("metric", 1)
56
- end
57
- end
34
+ before do
35
+ Instrumental::Agent.logger.level = Logger::UNKNOWN
36
+ @server = server
37
+ wait
38
+ end
58
39
 
59
- describe Instrumental::Agent, "enabled" do
60
- before do
61
- @server = TestServer.new
62
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
63
- end
40
+ after do
41
+ agent.stop
42
+ server.stop
43
+ end
64
44
 
65
- after do
66
- @agent.stop
67
- @agent = nil
68
- @server.stop
69
- end
45
+ describe Instrumental::Agent, "disabled" do
46
+ let(:enabled) { false }
70
47
 
71
- it "should not connect to the server" do
72
- wait
73
- @server.connect_count.should == 0
74
- end
48
+ it "should not connect to the server" do
49
+ server.connect_count.should == 0
50
+ end
75
51
 
76
- it "should connect to the server after sending a metric" do
77
- @agent.increment("test.foo")
78
- wait
79
- @server.connect_count.should == 1
80
- end
52
+ it "should not connect to the server after receiving a metric" do
53
+ agent.gauge('disabled_test', 1)
54
+ wait
55
+ server.connect_count.should == 0
56
+ end
81
57
 
82
- it "should announce itself, and include version" do
83
- @agent.increment("test.foo")
84
- wait
85
- @server.commands[0].should =~ /hello .*/
86
- @server.commands[0].should =~ / version /
87
- @server.commands[0].should =~ / hostname /
88
- @server.commands[0].should =~ / pid /
89
- @server.commands[0].should =~ / runtime /
90
- @server.commands[0].should =~ / platform /
91
- end
58
+ it "should no op on flush without reconnect" do
59
+ 1.upto(100) { agent.gauge('disabled_test', 1) }
60
+ agent.flush(false)
61
+ wait
62
+ server.commands.should be_empty
63
+ end
92
64
 
93
- it "should authenticate using the token" do
94
- @agent.increment("test.foo")
95
- wait
96
- @server.commands[1].should == "authenticate test_token"
97
- end
65
+ it "should no op on flush with reconnect" do
66
+ 1.upto(100) { agent.gauge('disabled_test', 1) }
67
+ agent.flush(true)
68
+ wait
69
+ server.commands.should be_empty
70
+ end
98
71
 
99
- it "should report a gauge" do
100
- now = Time.now
101
- @agent.gauge('gauge_test', 123)
102
- wait
103
- @server.commands.last.should == "gauge gauge_test 123 #{now.to_i} 1"
104
- end
72
+ it "should no op on an empty flush" do
73
+ agent.flush(true)
74
+ wait
75
+ server.commands.should be_empty
76
+ end
105
77
 
106
- it "should report a time as gauge and return the block result" do
107
- now = Time.now
108
- @agent.time("time_value_test") do
109
- 1 + 1
110
- end.should == 2
111
- wait
112
- @server.commands.last.should =~ /gauge time_value_test .* #{now.to_i}/
113
- end
78
+ it "should send metrics to logger" do
79
+ now = Time.now
80
+ agent.logger.should_receive(:debug).with("gauge metric 1 #{now.to_i} 1")
81
+ agent.gauge("metric", 1)
82
+ end
83
+ end
114
84
 
115
- it "should return the value gauged" do
116
- now = Time.now
117
- @agent.gauge('gauge_test', 123).should == 123
118
- @agent.gauge('gauge_test', 989).should == 989
119
- wait
120
- end
85
+ describe Instrumental::Agent, "enabled" do
121
86
 
122
- it "should report a gauge with a set time" do
123
- @agent.gauge('gauge_test', 123, 555)
124
- wait
125
- @server.commands.last.should == "gauge gauge_test 123 555 1"
126
- end
87
+ it "should not connect to the server" do
88
+ server.connect_count.should == 0
89
+ end
127
90
 
128
- it "should report a gauge with a set time and count" do
129
- @agent.gauge('gauge_test', 123, 555, 111)
130
- wait
131
- @server.commands.last.should == "gauge gauge_test 123 555 111"
132
- end
91
+ it "should connect to the server after sending a metric" do
92
+ agent.increment("test.foo")
93
+ wait
94
+ server.connect_count.should == 1
95
+ end
133
96
 
134
- it "should report an increment" do
135
- now = Time.now
136
- @agent.increment("increment_test")
137
- wait
138
- @server.commands.last.should == "increment increment_test 1 #{now.to_i} 1"
139
- end
97
+ it "should announce itself, and include version" do
98
+ agent.increment("test.foo")
99
+ wait
100
+ server.commands[0].should =~ /hello .*/
101
+ server.commands[0].should =~ / version /
102
+ server.commands[0].should =~ / hostname /
103
+ server.commands[0].should =~ / pid /
104
+ server.commands[0].should =~ / runtime /
105
+ server.commands[0].should =~ / platform /
106
+ end
140
107
 
141
- it "should return the value incremented by" do
142
- now = Time.now
143
- @agent.increment("increment_test").should == 1
144
- @agent.increment("increment_test", 5).should == 5
145
- wait
146
- end
108
+ it "should authenticate using the token" do
109
+ agent.increment("test.foo")
110
+ wait
111
+ server.commands[1].should == "authenticate test_token"
112
+ end
147
113
 
148
- it "should report an increment a value" do
149
- now = Time.now
150
- @agent.increment("increment_test", 2)
151
- wait
152
- @server.commands.last.should == "increment increment_test 2 #{now.to_i} 1"
153
- end
114
+ it "should report a gauge" do
115
+ now = Time.now
116
+ agent.gauge('gauge_test', 123)
117
+ wait
118
+ server.commands.last.should == "gauge gauge_test 123 #{now.to_i} 1"
119
+ end
154
120
 
155
- it "should report an increment with a set time" do
156
- @agent.increment('increment_test', 1, 555)
157
- wait
158
- @server.commands.last.should == "increment increment_test 1 555 1"
159
- end
121
+ it "should report a time as gauge and return the block result" do
122
+ now = Time.now
123
+ agent.time("time_value_test") do
124
+ 1 + 1
125
+ end.should == 2
126
+ wait
127
+ server.commands.last.should =~ /gauge time_value_test .* #{now.to_i}/
128
+ end
160
129
 
161
- it "should report an increment with a set time and count" do
162
- @agent.increment('increment_test', 1, 555, 111)
163
- wait
164
- @server.commands.last.should == "increment increment_test 1 555 111"
165
- end
130
+ it "should return the value gauged" do
131
+ now = Time.now
132
+ agent.gauge('gauge_test', 123).should == 123
133
+ agent.gauge('gauge_test', 989).should == 989
134
+ wait
135
+ end
166
136
 
167
- it "should discard data that overflows the buffer" do
168
- with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
169
- 5.times do |i|
170
- @agent.increment('overflow_test', i + 1, 300)
137
+ it "should report a gauge with a set time" do
138
+ agent.gauge('gauge_test', 123, 555)
139
+ wait
140
+ server.commands.last.should == "gauge gauge_test 123 555 1"
171
141
  end
172
- wait
173
- @server.commands.should include("increment overflow_test 1 300 1")
174
- @server.commands.should include("increment overflow_test 2 300 1")
175
- @server.commands.should include("increment overflow_test 3 300 1")
176
- @server.commands.should_not include("increment overflow_test 4 300 1")
177
- @server.commands.should_not include("increment overflow_test 5 300 1")
178
- end
179
- end
180
142
 
181
- it "should send all data in synchronous mode" do
182
- with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
183
- @agent.synchronous = true
184
- 5.times do |i|
185
- @agent.increment('overflow_test', i + 1, 300)
186
- end
187
- @agent.instance_variable_get(:@queue).size.should == 0
188
- wait # let the server receive the commands
189
- @server.commands.should include("increment overflow_test 1 300 1")
190
- @server.commands.should include("increment overflow_test 2 300 1")
191
- @server.commands.should include("increment overflow_test 3 300 1")
192
- @server.commands.should include("increment overflow_test 4 300 1")
193
- @server.commands.should include("increment overflow_test 5 300 1")
194
- end
195
- end
143
+ it "should report a gauge with a set time and count" do
144
+ agent.gauge('gauge_test', 123, 555, 111)
145
+ wait
146
+ server.commands.last.should == "gauge gauge_test 123 555 111"
147
+ end
196
148
 
197
- it "should automatically reconnect when forked" do
198
- wait
199
- @agent.increment('fork_reconnect_test', 1, 2)
200
- fork do
201
- @agent.increment('fork_reconnect_test', 1, 3) # triggers reconnect
202
- end
203
- wait
204
- @agent.increment('fork_reconnect_test', 1, 4) # triggers reconnect
205
- wait
206
- @server.connect_count.should == 2
207
- @server.commands.should include("increment fork_reconnect_test 1 2 1")
208
- @server.commands.should include("increment fork_reconnect_test 1 3 1")
209
- @server.commands.should include("increment fork_reconnect_test 1 4 1")
210
- end
149
+ it "should report an increment" do
150
+ now = Time.now
151
+ agent.increment("increment_test")
152
+ wait
153
+ server.commands.last.should == "increment increment_test 1 #{now.to_i} 1"
154
+ end
211
155
 
212
- it "should never let an exception reach the user" do
213
- @agent.stub!(:send_command).and_raise(Exception.new("Test Exception"))
214
- @agent.increment('throws_exception', 2).should be_nil
215
- wait
216
- @agent.gauge('throws_exception', 234).should be_nil
217
- wait
218
- end
156
+ it "should return the value incremented by" do
157
+ now = Time.now
158
+ agent.increment("increment_test").should == 1
159
+ agent.increment("increment_test", 5).should == 5
160
+ wait
161
+ end
219
162
 
220
- it "should let exceptions in time bubble up" do
221
- expect { @agent.time('za') { raise "fail" } }.to raise_error
222
- end
163
+ it "should report an increment a value" do
164
+ now = Time.now
165
+ agent.increment("increment_test", 2)
166
+ wait
167
+ server.commands.last.should == "increment increment_test 2 #{now.to_i} 1"
168
+ end
223
169
 
224
- it "should return nil if the user overflows the MAX_BUFFER" do
225
- 1.upto(Instrumental::Agent::MAX_BUFFER) do
226
- @agent.increment("test").should == 1
227
- thread = @agent.instance_variable_get(:@thread)
228
- thread.kill
229
- end
230
- @agent.increment("test").should be_nil
231
- end
170
+ it "should report an increment with a set time" do
171
+ agent.increment('increment_test', 1, 555)
172
+ wait
173
+ server.commands.last.should == "increment increment_test 1 555 1"
174
+ end
232
175
 
233
- it "should track invalid metrics" do
234
- @agent.logger.should_receive(:warn).with(/%%/)
235
- @agent.increment(' %% .!#@$%^&*', 1, 1)
236
- wait
237
- @server.commands.join("\n").should include("increment agent.invalid_metric")
238
- end
176
+ it "should report an increment with a set time and count" do
177
+ agent.increment('increment_test', 1, 555, 111)
178
+ wait
179
+ server.commands.last.should == "increment increment_test 1 555 111"
180
+ end
239
181
 
240
- it "should allow reasonable metric names" do
241
- @agent.increment('a')
242
- @agent.increment('a.b')
243
- @agent.increment('hello.world')
244
- @agent.increment('ThisIsATest.Of.The.Emergency.Broadcast.System.12345')
245
- wait
246
- @server.commands.join("\n").should_not include("increment agent.invalid_metric")
247
- end
182
+ it "should discard data that overflows the buffer" do
183
+ with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
184
+ 5.times do |i|
185
+ agent.increment('overflow_test', i + 1, 300)
186
+ end
187
+ wait
188
+ server.commands.should include("increment overflow_test 1 300 1")
189
+ server.commands.should include("increment overflow_test 2 300 1")
190
+ server.commands.should include("increment overflow_test 3 300 1")
191
+ server.commands.should_not include("increment overflow_test 4 300 1")
192
+ server.commands.should_not include("increment overflow_test 5 300 1")
193
+ end
194
+ end
248
195
 
249
- it "should track invalid values" do
250
- @agent.logger.should_receive(:warn).with(/hello.*testington/)
251
- @agent.increment('testington', 'hello')
252
- wait
253
- @server.commands.join("\n").should include("increment agent.invalid_value")
254
- end
196
+ it "should send all data in synchronous mode" do
197
+ with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
198
+ agent.synchronous = true
199
+ 5.times do |i|
200
+ agent.increment('overflow_test', i + 1, 300)
201
+ end
202
+ agent.instance_variable_get(:@queue).size.should == 0
203
+ wait # let the server receive the commands
204
+ server.commands.should include("increment overflow_test 1 300 1")
205
+ server.commands.should include("increment overflow_test 2 300 1")
206
+ server.commands.should include("increment overflow_test 3 300 1")
207
+ server.commands.should include("increment overflow_test 4 300 1")
208
+ server.commands.should include("increment overflow_test 5 300 1")
209
+ end
210
+ end
255
211
 
256
- it "should allow reasonable values" do
257
- @agent.increment('a', -333.333)
258
- @agent.increment('a', -2.2)
259
- @agent.increment('a', -1)
260
- @agent.increment('a', 0)
261
- @agent.increment('a', 1)
262
- @agent.increment('a', 2.2)
263
- @agent.increment('a', 333.333)
264
- @agent.increment('a', Float::EPSILON)
265
- wait
266
- @server.commands.join("\n").should_not include("increment agent.invalid_value")
267
- end
212
+ if FORK_SUPPORTED
213
+ it "should automatically reconnect when forked" do
214
+ agent.increment('fork_reconnect_test', 1, 2)
215
+ fork do
216
+ agent.increment('fork_reconnect_test', 1, 3) # triggers reconnect
217
+ end
218
+ wait(1)
219
+ agent.increment('fork_reconnect_test', 1, 4) # triggers reconnect
220
+ wait(1)
221
+ server.connect_count.should == 2
222
+ server.commands.should include("increment fork_reconnect_test 1 2 1")
223
+ server.commands.should include("increment fork_reconnect_test 1 3 1")
224
+ server.commands.should include("increment fork_reconnect_test 1 4 1")
225
+ end
226
+ end
268
227
 
269
- it "should send notices to the server" do
270
- tm = Time.now
271
- @agent.notice("Test note", tm)
272
- wait
273
- @server.commands.join("\n").should include("notice #{tm.to_i} 0 Test note")
274
- end
228
+ it "should never let an exception reach the user" do
229
+ agent.stub(:send_command).and_raise(Exception.new("Test Exception"))
230
+ agent.increment('throws_exception', 2).should be_nil
231
+ wait
232
+ agent.gauge('throws_exception', 234).should be_nil
233
+ wait
234
+ end
275
235
 
276
- it "should prevent a note w/ newline characters from being sent to the server" do
277
- @agent.notice("Test note\n").should be_nil
278
- wait
279
- @server.commands.join("\n").should_not include("notice Test note")
280
- end
236
+ it "should let exceptions in time bubble up" do
237
+ expect { agent.time('za') { raise "fail" } }.to raise_error
238
+ end
281
239
 
282
- it "should allow outgoing metrics to be stopped" do
283
- tm = Time.now
284
- @agent.increment("foo.bar", 1, tm)
285
- @agent.stop
286
- wait
287
- @agent.increment("foo.baz", 1, tm)
288
- wait
289
- @server.commands.join("\n").should include("increment foo.baz 1 #{tm.to_i}")
290
- @server.commands.join("\n").should_not include("increment foo.bar 1 #{tm.to_i}")
291
- end
240
+ it "should return nil if the user overflows the MAX_BUFFER" do
241
+ 1.upto(Instrumental::Agent::MAX_BUFFER) do
242
+ agent.increment("test").should == 1
243
+ thread = agent.instance_variable_get(:@thread)
244
+ thread.kill
245
+ end
246
+ agent.increment("test").should be_nil
247
+ end
292
248
 
293
- it "should allow flushing pending values to the server" do
294
- 1.upto(100) { @agent.gauge('a', rand(50)) }
295
- @agent.instance_variable_get(:@queue).size.should >= 100
296
- @agent.flush
297
- @agent.instance_variable_get(:@queue).size.should == 0
298
- wait
299
- @server.commands.grep(/^gauge a /).size.should == 100
300
- end
249
+ it "should track invalid metrics" do
250
+ agent.logger.should_receive(:warn).with(/%%/)
251
+ agent.increment(' %% .!#@$%^&*', 1, 1)
252
+ wait
253
+ server.commands.join("\n").should include("increment agent.invalid_metric")
254
+ end
301
255
 
302
- it "should no op on an empty flush" do
303
- @agent.flush(true)
304
- wait
305
- @server.commands.should be_empty
306
- end
307
- end
256
+ it "should allow reasonable metric names" do
257
+ agent.increment('a')
258
+ agent.increment('a.b')
259
+ agent.increment('hello.world')
260
+ agent.increment('ThisIsATest.Of.The.Emergency.Broadcast.System.12345')
261
+ wait
262
+ server.commands.join("\n").should_not include("increment agent.invalid_metric")
263
+ end
308
264
 
309
- describe Instrumental::Agent, "connection problems" do
310
- after do
311
- @agent.stop
312
- @server.stop
313
- end
265
+ it "should track invalid values" do
266
+ agent.logger.should_receive(:warn).with(/hello.*testington/)
267
+ agent.increment('testington', 'hello')
268
+ wait
269
+ server.commands.join("\n").should include("increment agent.invalid_value")
270
+ end
314
271
 
315
- it "should automatically reconnect on disconnect" do
316
- @server = TestServer.new
317
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
318
- @agent.increment("reconnect_test", 1, 1234)
319
- wait
320
- @server.disconnect_all
321
- wait
322
- @agent.increment('reconnect_test', 1, 5678) # triggers reconnect
323
- wait
324
- @server.connect_count.should == 2
325
- @server.commands.last.should == "increment reconnect_test 1 5678 1"
326
- end
272
+ it "should allow reasonable values" do
273
+ agent.increment('a', -333.333)
274
+ agent.increment('a', -2.2)
275
+ agent.increment('a', -1)
276
+ agent.increment('a', 0)
277
+ agent.increment('a', 1)
278
+ agent.increment('a', 2.2)
279
+ agent.increment('a', 333.333)
280
+ agent.increment('a', Float::EPSILON)
281
+ wait
282
+ server.commands.join("\n").should_not include("increment agent.invalid_value")
283
+ end
327
284
 
328
- it "should buffer commands when server is down" do
329
- @server = TestServer.new(:listen => false)
330
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
331
- wait
332
- @agent.increment('reconnect_test', 1, 1234)
333
- wait
334
- @agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
335
- end
285
+ it "should send notices to the server" do
286
+ tm = Time.now
287
+ agent.notice("Test note", tm)
288
+ wait
289
+ server.commands.join("\n").should include("notice #{tm.to_i} 0 Test note")
290
+ end
336
291
 
337
- it "should buffer commands when server is not responsive" do
338
- @server = TestServer.new(:response => false)
339
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
340
- wait
341
- @agent.increment('reconnect_test', 1, 1234)
342
- wait
343
- @agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
344
- end
292
+ it "should prevent a note w/ newline characters from being sent to the server" do
293
+ agent.notice("Test note\n").should be_nil
294
+ wait
295
+ server.commands.join("\n").should_not include("notice Test note")
296
+ end
345
297
 
346
- it "should buffer commands when authentication fails" do
347
- @server = TestServer.new(:authenticate => false)
348
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
349
- wait
350
- @agent.increment('reconnect_test', 1, 1234)
351
- wait
352
- @agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
353
- end
298
+ it "should allow outgoing metrics to be stopped" do
299
+ tm = Time.now
300
+ agent.increment("foo.bar", 1, tm)
301
+ agent.stop
302
+ wait
303
+ agent.increment("foo.baz", 1, tm)
304
+ wait
305
+ server.commands.join("\n").should include("increment foo.baz 1 #{tm.to_i}")
306
+ server.commands.join("\n").should_not include("increment foo.bar 1 #{tm.to_i}")
307
+ end
354
308
 
355
- it "should warn once when buffer is full" do
356
- with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
357
- @server = TestServer.new(:listen => false)
358
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
359
- wait
360
- @agent.logger.should_receive(:warn).with(/Queue full/).once
309
+ it "should allow flushing pending values to the server" do
310
+ 1.upto(100) { agent.gauge('a', rand(50)) }
311
+ agent.instance_variable_get(:@queue).size.should > 0
312
+ agent.flush
313
+ agent.instance_variable_get(:@queue).size.should == 0
314
+ wait
315
+ server.commands.grep(/^gauge a /).size.should == 100
316
+ end
361
317
 
362
- @agent.increment('buffer_full_warn_test', 1, 1234)
363
- @agent.increment('buffer_full_warn_test', 1, 1234)
364
- @agent.increment('buffer_full_warn_test', 1, 1234)
365
- @agent.increment('buffer_full_warn_test', 1, 1234)
366
- @agent.increment('buffer_full_warn_test', 1, 1234)
318
+ it "should no op on an empty flush" do
319
+ agent.flush(true)
320
+ wait
321
+ server.commands.should be_empty
322
+ end
367
323
  end
368
- end
369
324
 
370
- it "should send commands in a short-lived process" do
371
- @server = TestServer.new
372
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
373
- if pid = fork { @agent.increment('foo', 1, 1234) }
374
- Process.wait(pid)
375
- @server.commands.last.should == "increment foo 1 1234 1"
376
- end
377
- end
325
+ describe Instrumental::Agent, "connection problems" do
326
+ it "should automatically reconnect on disconnect" do
327
+ agent.increment("reconnect_test", 1, 1234)
328
+ wait
329
+ server.disconnect_all
330
+ wait(1)
331
+ agent.increment('reconnect_test', 1, 5678) # triggers reconnect
332
+ wait(1)
333
+ server.connect_count.should == 2
334
+ server.commands.last.should == "increment reconnect_test 1 5678 1"
335
+ end
378
336
 
379
- it "should send commands in a process that bypasses at_exit when using #cleanup" do
380
- @server = TestServer.new
381
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
382
- if pid = fork { @agent.increment('foo', 1, 1234); @agent.cleanup; exit! }
383
- Process.wait(pid)
384
- @server.commands.last.should == "increment foo 1 1234 1"
385
- end
386
- end
337
+ context 'not listening' do
338
+ let(:listen) { false }
339
+
340
+ it "should buffer commands when server is down" do
341
+ agent.increment('reconnect_test', 1, 1234)
342
+ wait
343
+ agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
344
+ end
345
+
346
+ it "should warn once when buffer is full" do
347
+ with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
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
+ end
387
359
 
388
- it "should not wait longer than EXIT_FLUSH_TIMEOUT seconds to exit a process" do
389
- @server = TestServer.new
390
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
391
- Socket.stub!(:new) { |*args| sleep(5) && StringIO.new }
392
- with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
393
- if (pid = fork { @agent.increment('foo', 1) })
394
- tm = Time.now.to_f
395
- Process.wait(pid)
396
- diff = Time.now.to_f - tm
397
- diff.should >= 3
398
- diff.should < 5
360
+ context 'not responding' do
361
+ let(:response) { false }
362
+
363
+ it "should buffer commands when server is not responsive" do
364
+ agent.increment('reconnect_test', 1, 1234)
365
+ wait
366
+ agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
367
+ end
399
368
  end
400
- end
401
- end
402
369
 
403
- it "should not wait to exit a process if there are no commands queued" do
404
- @server = TestServer.new
405
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
406
- Socket.stub!(:new) { |*args| sleep(5) && StringIO.new }
407
- with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
408
- if (pid = fork { @agent.increment('foo', 1); @agent.queue.clear })
409
- tm = Time.now.to_f
410
- Process.wait(pid)
411
- diff = Time.now.to_f - tm
412
- diff.should < 1
370
+
371
+ context 'not authenticating' do
372
+ let(:authenticate) { false }
373
+
374
+ it "should buffer commands when authentication fails" do
375
+ agent.increment('reconnect_test', 1, 1234)
376
+ wait
377
+ agent.queue.pop(true).should include("increment reconnect_test 1 1234 1\n")
378
+ end
379
+ end
380
+
381
+ if FORK_SUPPORTED
382
+ it "should send commands in a short-lived process" do
383
+ if pid = fork { agent.increment('foo', 1, 1234) }
384
+ Process.wait(pid)
385
+ server.commands.last.should == "increment foo 1 1234 1"
386
+ end
387
+ end
388
+
389
+ it "should send commands in a process that bypasses at_exit when using #cleanup" do
390
+ if pid = fork { agent.increment('foo', 1, 1234); agent.cleanup; exit! }
391
+ Process.wait(pid)
392
+ server.commands.last.should == "increment foo 1 1234 1"
393
+ end
394
+ end
395
+
396
+ it "should not wait longer than EXIT_FLUSH_TIMEOUT seconds to exit a process" do
397
+ agent.stub(:open_socket) { |*args, &block| sleep(5) && block.call }
398
+ with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
399
+ if (pid = fork { agent.increment('foo', 1) })
400
+ tm = Time.now.to_f
401
+ Process.wait(pid)
402
+ diff = Time.now.to_f - tm
403
+ diff.abs.should >= 3
404
+ diff.abs.should < 5
405
+ end
406
+ end
407
+ end
408
+
409
+ it "should not wait to exit a process if there are no commands queued" do
410
+ agent.stub(:open_socket) { |*args, &block| sleep(5) && block.call }
411
+ with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
412
+ if (pid = fork { agent.increment('foo', 1); agent.queue.clear })
413
+ tm = Time.now.to_f
414
+ Process.wait(pid)
415
+ diff = Time.now.to_f - tm
416
+ diff.should < 1
417
+ end
418
+ end
419
+ end
420
+ end
421
+
422
+ it "should not wait longer than EXIT_FLUSH_TIMEOUT to attempt flushing the socket when disconnecting" do
423
+ agent.increment('foo', 1)
424
+ wait
425
+ agent.should_receive(:flush_socket) do
426
+ r, w = IO.pipe
427
+ Thread.new do
428
+ IO.select([r]) # mimic an endless blocking select poll
429
+ end.join
430
+ end
431
+ with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
432
+ tm = Time.now.to_f
433
+ agent.cleanup
434
+ diff = Time.now.to_f - tm
435
+ diff.should <= 3
436
+ end
413
437
  end
414
438
  end
415
- end
416
439
 
417
- it "should not wait longer than EXIT_FLUSH_TIMEOUT to attempt flushing the socket when disconnecting" do
418
- @server = TestServer.new
419
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => false)
420
- @agent.increment('foo', 1)
421
- wait
422
- @agent.instance_variable_get(:@socket).should_receive(:flush).and_return {
423
- r, w = IO.pipe
424
- IO.select([r]) # mimic an endless blocking select poll
425
- }
426
- with_constants('Instrumental::Agent::EXIT_FLUSH_TIMEOUT' => 3) do
427
- tm = Time.now.to_f
428
- @agent.cleanup
429
- diff = Time.now.to_f - tm
430
- diff.should <= 3
440
+ describe Instrumental::Agent, "enabled with sync option" do
441
+ let(:synchronous) { true }
442
+
443
+ it "should send all data in synchronous mode" do
444
+ with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
445
+ 5.times do |i|
446
+ agent.increment('overflow_test', i + 1, 300)
447
+ end
448
+ wait # let the server receive the commands
449
+ server.commands.should include("increment overflow_test 1 300 1")
450
+ server.commands.should include("increment overflow_test 2 300 1")
451
+ server.commands.should include("increment overflow_test 3 300 1")
452
+ server.commands.should include("increment overflow_test 4 300 1")
453
+ server.commands.should include("increment overflow_test 5 300 1")
454
+ end
455
+ end
456
+
431
457
  end
432
458
  end
433
459
  end
434
460
 
435
- describe Instrumental::Agent, "enabled with sync option" do
436
- before do
437
- @server = TestServer.new
438
- @agent = Instrumental::Agent.new('test_token', :collector => @server.host_and_port, :synchronous => true)
439
- end
461
+ describe "Insecure" do
462
+ let(:secure?) { false }
463
+ let(:verify_cert?) { false }
464
+ it_behaves_like "Instrumental Agent"
465
+ end
440
466
 
441
- after do
442
- @agent.stop
443
- @server.stop
444
- end
467
+ describe "Secure without cert verify" do
468
+ let(:secure?) { true }
469
+ let(:verify_cert?) { false }
470
+ it_behaves_like "Instrumental Agent"
445
471
 
446
- it "should send all data in synchronous mode" do
447
- with_constants('Instrumental::Agent::MAX_BUFFER' => 3) do
448
- 5.times do |i|
449
- @agent.increment('overflow_test', i + 1, 300)
450
- end
451
- wait # let the server receive the commands
452
- @server.commands.should include("increment overflow_test 1 300 1")
453
- @server.commands.should include("increment overflow_test 2 300 1")
454
- @server.commands.should include("increment overflow_test 3 300 1")
455
- @server.commands.should include("increment overflow_test 4 300 1")
456
- @server.commands.should include("increment overflow_test 5 300 1")
457
- end
472
+ it "should be disabled if the system does not allow secure connections but the user specifically requested secure" do
473
+ Instrumental::Agent.any_instance.stub(:allows_secure?) { false }
474
+ agent = Instrumental::Agent.new('test-token', :enabled => true, :secure => true)
475
+ agent.secure.should == false
476
+ agent.enabled.should == false
458
477
  end
459
478
 
479
+ it "should be fallback to insecure if the system does not allow secure connections but the user did not specifically request secure" do
480
+ Instrumental::Agent.any_instance.stub(:allows_secure?) { false }
481
+ agent = Instrumental::Agent.new('test-token', :enabled => true)
482
+ agent.secure.should == false
483
+ agent.enabled.should == true
484
+ end
460
485
  end