instrumental_agent 0.12.7 → 0.13.0

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