appsignal 0.11.18 → 0.12.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGELOG.md +4 -38
  3. data/Rakefile +14 -6
  4. data/appsignal.gemspec +3 -1
  5. data/benchmark.rake +12 -16
  6. data/ext/appsignal_extension.c +183 -0
  7. data/ext/extconf.rb +39 -0
  8. data/gemfiles/capistrano2.gemfile +0 -1
  9. data/gemfiles/capistrano3.gemfile +0 -1
  10. data/gemfiles/rails-4.2.gemfile +1 -1
  11. data/lib/appsignal.rb +23 -61
  12. data/lib/appsignal/capistrano.rb +1 -2
  13. data/lib/appsignal/config.rb +13 -1
  14. data/lib/appsignal/event_formatter.rb +67 -0
  15. data/lib/appsignal/event_formatter/action_view/render_formatter.rb +23 -0
  16. data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +74 -0
  17. data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
  18. data/lib/appsignal/event_formatter/net_http/request_formatter.rb +13 -0
  19. data/lib/appsignal/instrumentations/net_http.rb +6 -4
  20. data/lib/appsignal/integrations/resque.rb +2 -10
  21. data/lib/appsignal/integrations/sidekiq.rb +2 -2
  22. data/lib/appsignal/integrations/sinatra.rb +1 -0
  23. data/lib/appsignal/js_exception_transaction.rb +44 -28
  24. data/lib/appsignal/marker.rb +11 -13
  25. data/lib/appsignal/params_sanitizer.rb +5 -8
  26. data/lib/appsignal/rack/instrumentation.rb +2 -0
  27. data/lib/appsignal/rack/js_exception_catcher.rb +1 -0
  28. data/lib/appsignal/rack/listener.rb +1 -1
  29. data/lib/appsignal/rack/sinatra_instrumentation.rb +2 -12
  30. data/lib/appsignal/subscriber.rb +59 -0
  31. data/lib/appsignal/transaction.rb +117 -174
  32. data/lib/appsignal/transmitter.rb +8 -37
  33. data/lib/appsignal/version.rb +2 -1
  34. data/spec/lib/appsignal/config_spec.rb +25 -4
  35. data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +42 -0
  36. data/spec/lib/appsignal/{aggregator/middleware/active_record_sanitizer_spec.rb → event_formatter/active_record/sql_formatter_spec.rb} +61 -61
  37. data/spec/lib/appsignal/{event/moped_event_spec.rb → event_formatter/moped/query_formatter_spec.rb} +32 -78
  38. data/spec/lib/appsignal/event_formatter/net_http/request_formatter_spec.rb +26 -0
  39. data/spec/lib/appsignal/event_formatter_spec.rb +102 -0
  40. data/spec/lib/appsignal/extension_spec.rb +75 -0
  41. data/spec/lib/appsignal/instrumentations/net_http_spec.rb +20 -4
  42. data/spec/lib/appsignal/integrations/delayed_job_spec.rb +3 -2
  43. data/spec/lib/appsignal/integrations/rails_spec.rb +0 -7
  44. data/spec/lib/appsignal/integrations/resque_spec.rb +51 -55
  45. data/spec/lib/appsignal/integrations/sequel_spec.rb +8 -3
  46. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -21
  47. data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -6
  48. data/spec/lib/appsignal/js_exception_transaction_spec.rb +57 -60
  49. data/spec/lib/appsignal/params_sanitizer_spec.rb +11 -27
  50. data/spec/lib/appsignal/rack/listener_spec.rb +6 -6
  51. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +2 -43
  52. data/spec/lib/appsignal/subscriber_spec.rb +162 -0
  53. data/spec/lib/appsignal/transaction_spec.rb +283 -615
  54. data/spec/lib/appsignal/transmitter_spec.rb +3 -32
  55. data/spec/lib/appsignal_spec.rb +41 -90
  56. data/spec/lib/generators/appsignal/appsignal_generator_spec.rb +0 -17
  57. data/spec/spec_helper.rb +18 -22
  58. data/spec/support/helpers/notification_helpers.rb +1 -1
  59. data/spec/support/helpers/time_helpers.rb +11 -0
  60. data/spec/support/helpers/transaction_helpers.rb +6 -18
  61. data/spec/support/project_fixture/config/appsignal.yml +1 -2
  62. metadata +68 -78
  63. checksums.yaml +0 -7
  64. data/gemfiles/padrino-0.13.gemfile +0 -7
  65. data/gemfiles/resque.gemfile +0 -5
  66. data/lib/appsignal/agent.rb +0 -217
  67. data/lib/appsignal/aggregator.rb +0 -67
  68. data/lib/appsignal/aggregator/middleware.rb +0 -4
  69. data/lib/appsignal/aggregator/middleware/action_view_sanitizer.rb +0 -23
  70. data/lib/appsignal/aggregator/middleware/active_record_sanitizer.rb +0 -65
  71. data/lib/appsignal/aggregator/middleware/chain.rb +0 -101
  72. data/lib/appsignal/aggregator/middleware/delete_blanks.rb +0 -16
  73. data/lib/appsignal/aggregator/post_processor.rb +0 -32
  74. data/lib/appsignal/event.rb +0 -20
  75. data/lib/appsignal/event/moped_event.rb +0 -90
  76. data/lib/appsignal/integrations/padrino.rb +0 -64
  77. data/lib/appsignal/integrations/passenger.rb +0 -13
  78. data/lib/appsignal/integrations/rake.rb +0 -29
  79. data/lib/appsignal/integrations/unicorn.rb +0 -25
  80. data/lib/appsignal/ipc.rb +0 -68
  81. data/lib/appsignal/transaction/formatter.rb +0 -85
  82. data/lib/appsignal/transaction/params_sanitizer.rb +0 -4
  83. data/lib/appsignal/zipped_payload.rb +0 -37
  84. data/spec/lib/appsignal/agent_spec.rb +0 -592
  85. data/spec/lib/appsignal/aggregator/middleware/action_view_sanitizer_spec.rb +0 -44
  86. data/spec/lib/appsignal/aggregator/middleware/chain_spec.rb +0 -168
  87. data/spec/lib/appsignal/aggregator/middleware/delete_blanks_spec.rb +0 -37
  88. data/spec/lib/appsignal/aggregator/post_processor_spec.rb +0 -99
  89. data/spec/lib/appsignal/aggregator_spec.rb +0 -186
  90. data/spec/lib/appsignal/event_spec.rb +0 -48
  91. data/spec/lib/appsignal/integrations/padrino_spec.rb +0 -171
  92. data/spec/lib/appsignal/integrations/passenger_spec.rb +0 -22
  93. data/spec/lib/appsignal/integrations/rake_spec.rb +0 -92
  94. data/spec/lib/appsignal/integrations/unicorn_spec.rb +0 -48
  95. data/spec/lib/appsignal/ipc_spec.rb +0 -128
  96. data/spec/lib/appsignal/transaction/formatter_spec.rb +0 -247
  97. data/spec/lib/appsignal/zipped_payload_spec.rb +0 -42
@@ -1,48 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Appsignal::Event do
4
-
5
- describe "#sanitize!" do
6
- let(:payload) { {:foo => 'bar'} }
7
- let(:event) { Appsignal::Event.new('event.test', 1, 2, 3, payload) }
8
-
9
- it "should call the sanitizer" do
10
- expect( Appsignal::ParamsSanitizer ).to receive(:sanitize).with(payload)
11
- event.sanitize!
12
- end
13
-
14
- it "should store the result on the payload" do
15
- Appsignal::ParamsSanitizer.stub(:sanitize => {:foo => 'sanitized'})
16
- expect {
17
- event.sanitize!
18
- }.to change(event, :payload).from(:foo => 'bar').to(:foo => 'sanitized')
19
- end
20
- end
21
-
22
- describe "#truncate!" do
23
- let(:payload) { {:foo => 'bar'} }
24
- let(:event) { Appsignal::Event.new('event.test', 1, 2, 3, payload) }
25
-
26
- it "should remove the payload" do
27
- expect {
28
- event.truncate!
29
- }.to change(event, :payload).from(:foo => 'bar').to({})
30
- end
31
- end
32
-
33
- describe ".event_for_instrumentation" do
34
- context "with non-moped event" do
35
- it "should instantiate a new Appsignal::Event" do
36
- expect( Appsignal::Event ).to receive(:new)
37
- Appsignal::Event.event_for_instrumentation('query.active_record')
38
- end
39
- end
40
-
41
- context "with moped event" do
42
- it "should instantiate a moped event" do
43
- expect( Appsignal::Event::MopedEvent ).to receive(:new)
44
- Appsignal::Event.event_for_instrumentation('query.moped')
45
- end
46
- end
47
- end
48
- end
@@ -1,171 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if padrino_present?
4
- describe "Padrino integration" do
5
- require File.expand_path('lib/appsignal/integrations/padrino.rb')
6
-
7
- class ClassWithRouter
8
- include Padrino::Routing
9
- end
10
-
11
- before do
12
- @events = []
13
- @subscriber = ActiveSupport::Notifications.subscribe do |*args|
14
- @events << ActiveSupport::Notifications::Event.new(*args)
15
- end
16
- end
17
- after do
18
- ActiveSupport::Notifications.unsubscribe(@subscriber)
19
- end
20
-
21
- describe "Appsignal::Integrations::PadrinoPlugin" do
22
- before do
23
- Appsignal.stub(
24
- :active? => true,
25
- :start => true,
26
- :start_logger => true
27
- )
28
- end
29
-
30
- it "should start the logger on init" do
31
- expect( Appsignal ).to receive(:start_logger)
32
- end
33
-
34
- it "should start appsignal on init" do
35
- expect( Appsignal ).to receive(:start)
36
- end
37
-
38
- it "should add the Listener middleware to the stack" do
39
- expect( Padrino ).to receive(:use).with(Appsignal::Rack::Listener)
40
- end
41
-
42
- context "when not active" do
43
- before { Appsignal.stub(:active? => false) }
44
-
45
- it "should not add the Listener middleware to the stack" do
46
- expect( Padrino ).to_not receive(:use)
47
- end
48
- end
49
-
50
- after { Appsignal::Integrations::PadrinoPlugin.init }
51
- end
52
-
53
- describe "Padrino::Routing::InstanceMethods" do
54
- let(:base) { double }
55
- let(:router) { ClassWithRouter.new }
56
- let(:env) { {} }
57
- let(:settings) { double(:name => 'TestApp') }
58
-
59
- describe "#route!" do
60
- let(:request) do
61
- double(
62
- :params => {'id' => 1},
63
- :session => {'user_id' => 123},
64
- :request_method => 'GET',
65
- :path => '/users/1',
66
- :controller => 'users',
67
- :action => 'show'
68
- )
69
- end
70
-
71
- before do
72
- router.stub(
73
- :route_without_appsignal => true,
74
- :request => request,
75
- :env => env,
76
- :settings => settings,
77
- :get_payload_action => 'controller#action'
78
- )
79
- end
80
-
81
- context "when Sinatra tells us it's a static file" do
82
- let(:env) { {'sinatra.static_file' => true} }
83
-
84
- it "should call the original method" do
85
- expect( router ).to receive(:route_without_appsignal)
86
- end
87
-
88
- it "should not instrument the request" do
89
- expect( ActiveSupport::Notifications ).to_not receive(:instrument)
90
- end
91
-
92
- after { router.route!(base) }
93
- end
94
-
95
- context "with a dynamic request" do
96
-
97
- it "should call the original method" do
98
- expect( router ).to receive(:route_without_appsignal)
99
- end
100
-
101
- it "should instrument the action" do
102
- expect( ActiveSupport::Notifications ).to receive(:instrument).with(
103
- 'process_action.padrino',
104
- {
105
- :params => {'id' => 1},
106
- :session => {'user_id' => 123},
107
- :method => 'GET',
108
- :path => '/users/1'
109
- }
110
- )
111
- end
112
-
113
- after { router.route!(base) }
114
- end
115
-
116
- it "should add the action to the payload" do
117
- router.route!(base)
118
-
119
- expect( @events.first.payload[:action] ).to eql('controller#action')
120
- end
121
-
122
- context "with an exception" do
123
- before { router.stub(:route_without_appsignal).and_raise(VerySpecificError) }
124
-
125
- it "should add the exception to the current transaction" do
126
- expect( Appsignal ).to receive(:add_exception)
127
-
128
- router.route!(base) rescue VerySpecificError
129
- end
130
- end
131
- end
132
-
133
- describe "#get_payload_action" do
134
- before { router.stub(:settings => settings) }
135
-
136
- context "when request is nil" do
137
- it "should return the site" do
138
- expect( router.get_payload_action(nil) ).to eql('TestApp')
139
- end
140
- end
141
-
142
- context "when there's no route object" do
143
- let(:request) { double(:controller => 'Controller', :action => 'action') }
144
-
145
- it "should return the site name, controller and action" do
146
- expect( router.get_payload_action(request) ).to eql('TestApp:Controller#action')
147
- end
148
-
149
- context "when there's no action" do
150
- let(:request) { double(:controller => 'Controller', :fullpath => '/action') }
151
-
152
- it "should return the site name, controller and fullpath" do
153
- expect( router.get_payload_action(request) ).to eql('TestApp:Controller#/action')
154
- end
155
- end
156
- end
157
-
158
- context "when request has a route object" do
159
- let(:request) { double }
160
- let(:route_object) { double(:original_path => '/accounts/edit/:id') }
161
- before { request.stub(:route_obj => route_object) }
162
-
163
- it "should return the original path" do
164
- expect( router.get_payload_action(request) ).to eql('TestApp:/accounts/edit/:id')
165
- end
166
- end
167
- end
168
-
169
- end
170
- end
171
- end
@@ -1,22 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Passenger integration" do
4
- let(:file) { File.expand_path('lib/appsignal/integrations/passenger.rb') }
5
- before(:all) do
6
- module PhusionPassenger
7
- end
8
- end
9
-
10
- it "adds behavior to stopping_worker_process and starting_worker_process" do
11
- PhusionPassenger.should_receive(:on_event).with(:starting_worker_process)
12
- PhusionPassenger.should_receive(:on_event).with(:stopping_worker_process)
13
- load file
14
- end
15
-
16
- context "without passenger" do
17
- before(:all) { Object.send(:remove_const, :PhusionPassenger) }
18
-
19
- specify { expect { PhusionPassenger }.to raise_error(NameError) }
20
- specify { expect { load file }.to_not raise_error }
21
- end
22
- end
@@ -1,92 +0,0 @@
1
- require 'spec_helper'
2
- require 'rake'
3
- describe "Rack integration" do
4
- let(:file) { File.expand_path('lib/appsignal/integrations/rake.rb') }
5
- let(:app) { double(:current_scope => nil) }
6
- let(:task) { Rake::Task.new('task', app) }
7
- before do
8
- load file
9
- task.stub(
10
- :name => 'task:name',
11
- :invoke_without_appsignal => true
12
- )
13
- end
14
-
15
- describe "#invoke" do
16
-
17
- it "should call with appsignal monitoring" do
18
- expect( task ).to receive(:invoke_with_appsignal).with(['foo'])
19
- end
20
-
21
- it "should call the original task" do
22
- expect( task ).to receive(:invoke_without_appsignal).with(['foo'])
23
- end
24
-
25
- after { task.invoke(['foo']) }
26
- end
27
-
28
- describe "#invoke_with_appsignal" do
29
- context "with transaction" do
30
- let!(:transaction) { Appsignal::Transaction.new('123', {}) }
31
- let!(:agent) { double('Agent', :send_queue => true) }
32
- before do
33
- SecureRandom.stub(:uuid => '123')
34
- Appsignal::Transaction.stub(:create => transaction)
35
- Appsignal.stub(:agent => agent, :active? => true)
36
- end
37
-
38
- it "should create a transaction" do
39
- expect( Appsignal::Transaction ).to receive(:create).with(
40
- '123',
41
- ENV,
42
- :kind => 'background_job',
43
- :action => 'task:name',
44
- :params => ['foo']
45
- )
46
- end
47
-
48
- it "should call the original task" do
49
- expect( task ).to receive(:invoke_without_appsignal).with('foo')
50
- end
51
-
52
- it "should complete the transaction" do
53
- expect( transaction ).to receive(:complete!)
54
- end
55
-
56
- it "should send the queue" do
57
- expect( Appsignal.agent ).to receive(:send_queue)
58
- end
59
-
60
- context "when Appsignal is not active" do
61
- before { Appsignal.stub(:active? => false) }
62
-
63
- it "should not send the queue" do
64
- expect( Appsignal.agent ).to_not receive(:send_queue)
65
- end
66
- end
67
-
68
- context "with an exception" do
69
- let(:exception) { VerySpecificError.new }
70
-
71
- before do
72
- task.stub(:invoke_without_appsignal).and_raise(exception)
73
- Appsignal.stub(:is_ignored_exception? => false )
74
- end
75
-
76
- it "should add the exception to the transaction" do
77
- expect( transaction ).to receive(:add_exception).with(exception)
78
- end
79
-
80
- context "when ignored" do
81
- before { Appsignal.stub(:is_ignored_exception? => true ) }
82
-
83
- it "should NOT add the exception to the transaction" do
84
- expect( transaction ).to_not receive(:add_exception)
85
- end
86
- end
87
- end
88
- end
89
-
90
- after { task.invoke_with_appsignal('foo') rescue VerySpecificError }
91
- end
92
- end
@@ -1,48 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Unicorn integration" do
4
- let(:file) { File.expand_path('lib/appsignal/integrations/unicorn.rb') }
5
- before(:all) do
6
- module Unicorn
7
- class HttpServer
8
- def worker_loop(worker)
9
- end
10
- end
11
-
12
- class Worker
13
- def close
14
- end
15
- end
16
- end
17
- end
18
- before do
19
- load file
20
- start_agent
21
- end
22
-
23
- it "adds behavior to Unicorn::HttpServer#worker_loop" do
24
- server = Unicorn::HttpServer.new
25
- worker = double
26
-
27
- Appsignal.agent.should_receive(:forked!)
28
- server.should_receive(:original_worker_loop).with(worker)
29
-
30
- server.worker_loop(worker)
31
- end
32
-
33
- it "should add behavior to Unicorn::Worker#close" do
34
- worker = Unicorn::Worker.new
35
-
36
- Appsignal.agent.should_receive(:shutdown).with(true, 'stopping Unicorn worker process')
37
- worker.should_receive(:original_close)
38
-
39
- worker.close
40
- end
41
-
42
- context "without unicorn" do
43
- before(:all) { Object.send(:remove_const, :Unicorn) }
44
-
45
- specify { expect { Unicorn }.to raise_error(NameError) }
46
- specify { expect { load file }.to_not raise_error }
47
- end
48
- end
@@ -1,128 +0,0 @@
1
- require 'spec_helper'
2
- require 'fileutils'
3
-
4
- unless running_jruby?
5
- describe Appsignal::IPC do
6
- before :all do
7
- start_agent
8
- end
9
- after :all do
10
- Appsignal::IPC::Client.stop
11
- Appsignal::IPC::Server.stop
12
- end
13
-
14
- subject { Appsignal::IPC }
15
-
16
- describe ".forked!" do
17
- it "should stop the server, start the client and stop the appsignal thread" do
18
- Appsignal::IPC::Server.should_receive(:stop)
19
- Appsignal::IPC::Client.should_receive(:start)
20
- Appsignal.agent.should_receive(:stop_thread)
21
-
22
- subject.forked!
23
- end
24
- end
25
-
26
- describe Appsignal::IPC::Server do
27
- subject { Appsignal::IPC::Server }
28
-
29
- describe ".start" do
30
- before do
31
- FileUtils.rm_rf(File.join(project_fixture_path, 'tmp'))
32
- Process.stub(:pid => 100)
33
- end
34
-
35
- it "should start a DRb server" do
36
- DRb.should_receive(:start_service).with(
37
- instance_of(String),
38
- Appsignal::IPC::Server
39
- )
40
- subject.start
41
- subject.uri.should == 'drbunix:/tmp/appsignal-100'
42
- end
43
-
44
- context "when a tmp path exists in the project path" do
45
- before do
46
- FileUtils.mkdir_p(File.join(project_fixture_path, 'tmp'))
47
- end
48
-
49
- it "should use a uri in the project path" do
50
- subject.start
51
- subject.uri.should == "drbunix:#{project_fixture_path}/tmp/appsignal-100"
52
- end
53
- end
54
- end
55
-
56
- describe ".stop" do
57
- it "should stop the DRb server" do
58
- DRb.should_receive(:stop_service)
59
- subject.stop
60
- end
61
- end
62
-
63
- describe ".enqueue" do
64
- let(:transaction) { regular_transaction }
65
-
66
- it "should enqueue" do
67
- Appsignal.agent.aggregator.has_transactions?.should be_false
68
- subject.enqueue(transaction)
69
- Appsignal.agent.aggregator.has_transactions?.should be_true
70
- end
71
- end
72
- end
73
-
74
- describe Appsignal::IPC::Client do
75
- before do
76
- Appsignal::IPC::Client.stop
77
- end
78
-
79
- subject { Appsignal::IPC::Client }
80
-
81
- describe ".start" do
82
- it "should start the client" do
83
- subject.active?.should be_false
84
-
85
- subject.start
86
-
87
- subject.server.should be_instance_of(DRbObject)
88
- subject.active?.should be_true
89
- end
90
- end
91
-
92
- describe ".stop" do
93
- it "should stop the client" do
94
- subject.start
95
- subject.stop
96
-
97
- subject.server.should be_nil
98
- subject.active?.should be_false
99
- end
100
- end
101
-
102
- describe ".enqueue" do
103
- let(:transaction) { regular_transaction }
104
-
105
- it "should send the transaction to the server" do
106
- subject.start
107
- subject.server.should_receive(:enqueue).with(transaction)
108
- subject.enqueue(transaction)
109
- end
110
- end
111
- end
112
-
113
- describe "integration between client and server" do
114
- it "should enqueue a transaction on the master" do
115
- Appsignal::IPC::Server.start
116
-
117
- fork do
118
- Appsignal::IPC.forked!
119
- Appsignal::IPC::Client.enqueue(regular_transaction)
120
- end
121
-
122
- Appsignal.agent.should_receive(:enqueue).with(instance_of(Appsignal::Transaction))
123
-
124
- sleep 1 # Wait for the forked process to do it's work
125
- end
126
- end
127
- end
128
- end