appsignal 0.9.6 → 0.10.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,6 +10,12 @@ describe Appsignal::Agent do
10
10
 
11
11
  let(:transaction) { regular_transaction }
12
12
 
13
+ context "supporting objects" do
14
+ its(:mutex) { should be_a(Mutex) }
15
+ its(:aggregator) { should be_a(Appsignal::Aggregator) }
16
+ its(:transmitter) { should be_a(Appsignal::Transmitter) }
17
+ end
18
+
13
19
  context "pid" do
14
20
  its(:master_pid) { should == Process.pid }
15
21
  its(:pid) { should == Process.pid }
@@ -55,7 +61,7 @@ describe Appsignal::Agent do
55
61
  subject.should_receive(:send_queue).at_least(:twice)
56
62
 
57
63
  subject.start_thread
58
- sleep 2
64
+ sleep 1
59
65
  end
60
66
  end
61
67
 
@@ -218,11 +224,12 @@ describe Appsignal::Agent do
218
224
  end
219
225
 
220
226
  describe "#enqueue" do
227
+ let(:transaction) { double(:action => 'test#test', :request_id => 'id') }
221
228
  subject { Appsignal.agent }
222
229
 
223
230
  it "forwards to the aggregator" do
224
231
  subject.aggregator.should respond_to(:add)
225
- subject.aggregator.should_receive(:add).with(:foo)
232
+ subject.aggregator.should_receive(:add).with(transaction)
226
233
  subject.should_not_receive(:forked!)
227
234
  end
228
235
 
@@ -230,12 +237,20 @@ describe Appsignal::Agent do
230
237
  before { Process.stub(:pid => 9000000002) }
231
238
 
232
239
  it "should call forked!" do
233
- subject.aggregator.should_receive(:add).with(:foo)
240
+ subject.aggregator.should_receive(:add).with(transaction)
234
241
  subject.should_receive(:forked!)
235
242
  end
236
243
  end
237
244
 
238
- after { subject.enqueue(:foo) }
245
+ context "with ignored action" do
246
+ before { Appsignal.stub(:is_ignored_action? => true) }
247
+
248
+ it "should not add item to queue" do
249
+ subject.aggregator.should_not_receive(:add)
250
+ end
251
+ end
252
+
253
+ after { subject.enqueue(transaction) }
239
254
  end
240
255
 
241
256
  describe "#send_queue" do
@@ -17,6 +17,7 @@ describe Appsignal::Config do
17
17
  it "should merge with the default config and fill the config hash" do
18
18
  subject.config_hash.should == {
19
19
  :ignore_exceptions => [],
20
+ :ignore_actions => [],
20
21
  :instrument_net_http => true,
21
22
  :send_params => true,
22
23
  :endpoint => 'https://push.appsignal.com/1',
@@ -123,6 +124,7 @@ describe Appsignal::Config do
123
124
  subject.config_hash.should == {
124
125
  :push_api_key => 'push_api_key',
125
126
  :ignore_exceptions => [],
127
+ :ignore_actions => [],
126
128
  :send_params => true,
127
129
  :instrument_net_http => true,
128
130
  :endpoint => 'https://push.appsignal.com/1',
@@ -41,8 +41,8 @@ describe "Delayed Job integration" do
41
41
  let(:error) { StandardError.new }
42
42
 
43
43
  context "with a normal call" do
44
- it "should create an instrumentation with the correct params" do
45
- ActiveSupport::Notifications.should_receive(:instrument).with(
44
+ it "should wrap in a transaction with the correct params" do
45
+ Appsignal.should_receive(:monitor_transaction).with(
46
46
  'perform_job.delayed_job',
47
47
  :class => 'TestClass',
48
48
  :method => 'perform',
@@ -51,7 +51,6 @@ describe "Delayed Job integration" do
51
51
  :queue => 'default',
52
52
  :queue_start => time - 60_000
53
53
  )
54
- Appsignal::Transaction.any_instance.should_receive(:complete!)
55
54
 
56
55
  Timecop.freeze(time) do
57
56
  plugin.invoke_with_instrumentation(job, invoked_block)
@@ -38,8 +38,8 @@ describe "Resque integration" do
38
38
  Appsignal::Transaction.should_receive(:create).and_return(transaction)
39
39
  end
40
40
 
41
- it "should instrument with correct params" do
42
- ActiveSupport::Notifications.should_receive(:instrument).with(
41
+ it "should wrap in a transaction with the correct params" do
42
+ Appsignal.should_receive(:monitor_transaction).with(
43
43
  'perform_job.resque',
44
44
  :class => 'Resque::Job',
45
45
  :method => 'perform'
@@ -1,8 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- class VerySpecificError < RuntimeError
4
- end
5
-
6
3
  describe "Sidekiq integration" do
7
4
  let(:file) { File.expand_path('lib/appsignal/integrations/sidekiq.rb') }
8
5
  before :all do
@@ -32,8 +29,8 @@ describe "Sidekiq integration" do
32
29
  end
33
30
 
34
31
  context "with a performance call" do
35
- it "should create an instrumentation with the correct params" do
36
- ActiveSupport::Notifications.should_receive(:instrument).with(
32
+ it "should wrap in a transaction with the correct params" do
33
+ Appsignal.should_receive(:monitor_transaction).with(
37
34
  'perform_job.sidekiq',
38
35
  :class => 'TestClass',
39
36
  :method => 'perform',
@@ -54,7 +51,7 @@ describe "Sidekiq integration" do
54
51
 
55
52
  context "with an erroring call" do
56
53
  let(:error) { VerySpecificError.new('the roof') }
57
- it "should add exception to appsignal" do
54
+ it "should add the exception to appsignal" do
58
55
  current_transaction.should_receive(:add_exception).with(error)
59
56
  end
60
57
 
@@ -186,4 +186,22 @@ describe Appsignal::Transaction::Formatter do
186
186
  end
187
187
  end
188
188
  end
189
+
190
+ describe "#clean_backtrace" do
191
+ let(:transaction) { regular_transaction }
192
+
193
+ context "when backtrace is nil" do
194
+ let(:error) { double(:backtrace => nil) }
195
+
196
+ it "should not raise an error when backtrace is `nil`" do
197
+ expect {
198
+ formatter.send(:clean_backtrace, error)
199
+ }.to_not raise_error
200
+ end
201
+
202
+ it "should always return an array" do
203
+ expect( formatter.send(:clean_backtrace, error) ).to be_a(Array)
204
+ end
205
+ end
206
+ end
189
207
  end
@@ -234,15 +234,6 @@ describe Appsignal::Transaction do
234
234
  subject.process_action_event.payload.should be_empty
235
235
  subject.events.should be_empty
236
236
  subject.tags.should be_empty
237
- subject.truncated?.should be_true
238
- end
239
-
240
- it "should not truncate twice" do
241
- subject.process_action_event.payload.should_receive(:clear).once
242
- subject.events.should_receive(:clear).once
243
-
244
- subject.truncate!
245
- subject.truncate!
246
237
  end
247
238
  end
248
239
 
@@ -291,14 +282,6 @@ describe Appsignal::Transaction do
291
282
  subject
292
283
  event_payload.should == before
293
284
  end
294
-
295
- it "should not covert to primitives twice" do
296
- transaction.convert_values_to_primitives!
297
- transaction.have_values_been_converted_to_primitives?.should be_true
298
-
299
- Appsignal::Transaction::ParamsSanitizer.should_not_receive(:sanitize!)
300
- transaction.convert_values_to_primitives!
301
- end
302
285
  end
303
286
  end
304
287
 
@@ -372,20 +355,12 @@ describe Appsignal::Transaction do
372
355
 
373
356
  context 'when using pipes' do
374
357
  let(:pipe) { double }
375
- before do
376
- Appsignal::Pipe.stub(:current => pipe)
377
- pipe.stub(:write => true)
378
- transaction.stub(:convert_values_to_primitives! => true)
379
- end
358
+ before { Appsignal::Pipe.stub(:current => pipe) }
380
359
 
381
360
  it "should send itself trough the pipe" do
382
361
  pipe.should_receive(:write).with(transaction)
383
362
  end
384
363
 
385
- it "should convert itself to primitives" do
386
- transaction.should_receive(:convert_values_to_primitives!)
387
- end
388
-
389
364
  after { transaction.complete! }
390
365
  end
391
366
  end
@@ -40,18 +40,25 @@ describe Appsignal::Transmitter do
40
40
  end
41
41
 
42
42
  describe "#http_post" do
43
- before do
43
+ it "calls Net::HTTP.post_form with the correct params" do
44
+ post = double(:post)
45
+ post.should_receive(:[]=).with(
46
+ 'Content-Type',
47
+ 'application/json; charset=UTF-8'
48
+ )
49
+ post.should_receive(:[]=).with(
50
+ 'Content-Encoding',
51
+ 'gzip'
52
+ )
53
+ post.should_receive(:body=).with(
54
+ Zlib::Deflate.deflate("{\"the\":\"payload\"}", Zlib::BEST_SPEED)
55
+ )
44
56
  Socket.stub(:gethostname => 'app1.local')
45
- end
46
-
47
- subject { instance.send(:http_post, 'the' => 'payload') }
48
-
49
- its(:body) { should == Zlib::Deflate.deflate("{\"the\":\"payload\"}", Zlib::BEST_SPEED) }
50
- its(:path) { should == instance.uri.request_uri }
51
57
 
52
- it "should have the correct headers" do
53
- subject['Content-Type'].should == 'application/json; charset=UTF-8'
54
- subject['Content-Encoding'].should == 'gzip'
58
+ Net::HTTP::Post.should_receive(:new).with(
59
+ instance.uri.request_uri
60
+ ).and_return(post)
61
+ instance.send(:http_post, :the => :payload)
55
62
  end
56
63
  end
57
64
 
@@ -144,7 +144,7 @@ describe Appsignal do
144
144
  end
145
145
 
146
146
  context "not active" do
147
- describe "#enqueue" do
147
+ describe ".enqueue" do
148
148
  it "should do nothing" do
149
149
  lambda {
150
150
  Appsignal.enqueue(Appsignal::Transaction.create(SecureRandom.uuid, ENV))
@@ -152,7 +152,22 @@ describe Appsignal do
152
152
  end
153
153
  end
154
154
 
155
- describe "#listen_for_exception" do
155
+ describe ".monitor_transaction" do
156
+ it "should do nothing but still yield the block" do
157
+ Appsignal::Transaction.should_not_receive(:create)
158
+ ActiveSupport::Notifications.should_not_receive(:instrument)
159
+ object = double
160
+ object.should_receive(:some_method)
161
+
162
+ lambda {
163
+ Appsignal.monitor_transaction('perform_job.nothing') do
164
+ object.some_method
165
+ end
166
+ }.should_not raise_error
167
+ end
168
+ end
169
+
170
+ describe ".listen_for_exception" do
156
171
  it "should do nothing" do
157
172
  error = RuntimeError.new('specific error')
158
173
  lambda {
@@ -163,7 +178,7 @@ describe Appsignal do
163
178
  end
164
179
  end
165
180
 
166
- describe "#send_exception" do
181
+ describe ".send_exception" do
167
182
  it "should do nothing" do
168
183
  lambda {
169
184
  Appsignal.send_exception(RuntimeError.new)
@@ -171,7 +186,7 @@ describe Appsignal do
171
186
  end
172
187
  end
173
188
 
174
- describe "#add_exception" do
189
+ describe ".add_exception" do
175
190
  it "should do nothing" do
176
191
  lambda {
177
192
  Appsignal.add_exception(RuntimeError.new)
@@ -179,7 +194,7 @@ describe Appsignal do
179
194
  end
180
195
  end
181
196
 
182
- describe "#tag_request" do
197
+ describe ".tag_request" do
183
198
  it "should do nothing" do
184
199
  lambda {
185
200
  Appsignal.tag_request(:tag => 'tag')
@@ -188,7 +203,6 @@ describe Appsignal do
188
203
  end
189
204
  end
190
205
 
191
-
192
206
  context "with config and started" do
193
207
  before do
194
208
  Appsignal.config = project_fixture_config
@@ -205,6 +219,43 @@ describe Appsignal do
205
219
  end
206
220
  end
207
221
 
222
+ describe ".monitor_transaction" do
223
+ context "with a normall call" do
224
+ it "should instrument and complete" do
225
+ Appsignal::Transaction.stub(:current => transaction)
226
+ ActiveSupport::Notifications.should_receive(:instrument).with(
227
+ 'perform_job.something',
228
+ :class => 'Something'
229
+ ).and_yield
230
+ transaction.should_receive(:complete!)
231
+ object = double
232
+ object.should_receive(:some_method)
233
+
234
+ Appsignal.monitor_transaction(
235
+ 'perform_job.something',
236
+ :class => 'Something'
237
+ ) do
238
+ object.some_method
239
+ end
240
+ end
241
+ end
242
+
243
+ context "with an erroring call" do
244
+ let(:error) { VerySpecificError.new('the roof') }
245
+
246
+ it "should add the error to the current transaction and complete" do
247
+ Appsignal.should_receive(:add_exception).with(error)
248
+ Appsignal::Transaction.should_receive(:complete_current!)
249
+
250
+ lambda {
251
+ Appsignal.monitor_transaction('perform_job.something') do
252
+ raise error
253
+ end
254
+ }.should raise_error(error)
255
+ end
256
+ end
257
+ end
258
+
208
259
  describe ".tag_request" do
209
260
  before { Appsignal::Transaction.stub(:current => transaction) }
210
261
 
@@ -320,12 +371,6 @@ describe Appsignal do
320
371
  end
321
372
  end
322
373
 
323
- describe ".json" do
324
- subject { Appsignal.json }
325
-
326
- it { should == ActiveSupport::JSON }
327
- end
328
-
329
374
  describe ".post_processing_middleware" do
330
375
  before { Appsignal.instance_variable_set(:@post_processing_chain, nil) }
331
376
 
@@ -454,5 +499,51 @@ describe Appsignal do
454
499
  end
455
500
  end
456
501
  end
502
+
503
+ describe ".is_ignored_exception?" do
504
+ let(:exception) { StandardError.new }
505
+ before do
506
+ Appsignal.stub(
507
+ :config => {:ignore_exceptions => 'StandardError'}
508
+ )
509
+ end
510
+
511
+ subject { Appsignal.is_ignored_exception?(exception) }
512
+
513
+ it "should return true if it's in the ignored list" do
514
+ should be_true
515
+ end
516
+
517
+ context "when exception is not in the ingore list" do
518
+ let(:exception) { Object.new }
519
+
520
+ it "should return false" do
521
+ should be_false
522
+ end
523
+ end
524
+ end
525
+
526
+ describe ".is_ignored_action?" do
527
+ let(:action) { 'TestController#isup' }
528
+ before do
529
+ Appsignal.stub(
530
+ :config => {:ignore_actions => 'TestController#isup'}
531
+ )
532
+ end
533
+
534
+ subject { Appsignal.is_ignored_action?(action) }
535
+
536
+ it "should return true if it's in the ignored list" do
537
+ should be_true
538
+ end
539
+
540
+ context "when action is not in the ingore list" do
541
+ let(:action) { 'TestController#other_action' }
542
+
543
+ it "should return false" do
544
+ should be_false
545
+ end
546
+ end
547
+ end
457
548
  end
458
549
  end
data/spec/spec_helper.rb CHANGED
@@ -3,7 +3,6 @@ require 'rspec'
3
3
  require 'pry'
4
4
  require 'timecop'
5
5
  require 'webmock/rspec'
6
- require 'active_support/notifications'
7
6
 
8
7
  puts "Runnings specs in #{RUBY_VERSION} on #{RUBY_PLATFORM}"
9
8
 
@@ -64,3 +63,6 @@ RSpec.configure do |config|
64
63
  Appsignal.logger = nil
65
64
  end
66
65
  end
66
+
67
+ class VerySpecificError < RuntimeError
68
+ end
@@ -9,6 +9,10 @@ default: &defaults
9
9
  # The cuttoff point in ms above which a request is considered slow, default is 200
10
10
  # slow_request_threshold: 200
11
11
 
12
+ # Actions that should not be monitored by AppSignal
13
+ # ignore_actions:
14
+ # - ApplicationController#isup
15
+
12
16
  # Configuration per environment, leave out an environment or set active
13
17
  # to false to not push metrics for that environment.
14
18
  development: