appsignal 0.11.7 → 0.11.8.beta.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 667d1d2dfa406916da0c6249befc7528ff83c662
4
- data.tar.gz: 5853d8a6387eba48425f5206bd1d1352e827b0d7
3
+ metadata.gz: 69c0fe4aba981d664f4b5a320c2cf47816ae4598
4
+ data.tar.gz: 546e20aa73e171ca1183c4cba04beed672ced563
5
5
  SHA512:
6
- metadata.gz: 6185e5637b0724d92dcdaaf826474e110bc8959f24ad057a0ddc391c972b175ca8efa498ed9f953211864e726450b8e344983c558082162f6d93a5848c376f3b
7
- data.tar.gz: 91b6b5e685022c0493347161fb28f5c3b040f297231b2ae7e89b70fe43f5671a9b540edc0deaf674fb482ad5f01d97591aa075f22a9cecc75fdaed072f8b0f0a
6
+ metadata.gz: dba3ef8508c2b43ef0456f926397ae29cd34a0b454de79cf3cf10e853386a2bfb90fb2d1e60ef21f9ffcf8e56c9425f6ede6669436430b35e2fb95936851be8c
7
+ data.tar.gz: 26d06743732e417cd38ddf55372f25f80be96f38d55ed5719c3740b746a32cc0579e5f399e75b1b9d31a62564a31d643778ca8a0ff8ddc02ba7142c582762cb8
@@ -1,3 +1,6 @@
1
+ # 0.11.8
2
+ * Add frontend error catcher
3
+
1
4
  # 0.11.7
2
5
  * Add option to override Job name in Delayed Job
3
6
 
@@ -195,6 +195,7 @@ require 'appsignal/marker'
195
195
  require 'appsignal/rack/listener'
196
196
  require 'appsignal/rack/instrumentation'
197
197
  require 'appsignal/rack/sinatra_instrumentation'
198
+ require 'appsignal/rack/js_exception_catcher'
198
199
  require 'appsignal/params_sanitizer'
199
200
  require 'appsignal/transaction'
200
201
  require 'appsignal/transaction/formatter'
@@ -203,3 +204,4 @@ require 'appsignal/transmitter'
203
204
  require 'appsignal/ipc'
204
205
  require 'appsignal/version'
205
206
  require 'appsignal/integrations/rails'
207
+ require 'appsignal/js_exception_transaction'
@@ -7,22 +7,24 @@ module Appsignal
7
7
  include Appsignal::CarefulLogger
8
8
 
9
9
  DEFAULT_CONFIG = {
10
- :ignore_exceptions => [],
11
- :ignore_actions => [],
12
- :send_params => true,
13
- :endpoint => 'https://push.appsignal.com/1',
14
- :slow_request_threshold => 200,
15
- :instrument_net_http => true,
16
- :skip_session_data => false
10
+ :ignore_exceptions => [],
11
+ :ignore_actions => [],
12
+ :send_params => true,
13
+ :endpoint => 'https://push.appsignal.com/1',
14
+ :slow_request_threshold => 200,
15
+ :instrument_net_http => true,
16
+ :skip_session_data => false,
17
+ :enable_frontend_error_catching => false,
18
+ :frontend_error_catching_path => '/appsignal_error_catcher'
17
19
  }.freeze
18
20
 
19
21
  attr_reader :root_path, :env, :initial_config, :config_hash
20
22
 
21
23
  def initialize(root_path, env, initial_config={}, logger=Appsignal.logger)
22
- @root_path = root_path
23
- @env = env.to_s
24
+ @root_path = root_path
25
+ @env = env.to_s
24
26
  @initial_config = initial_config
25
- @logger = logger
27
+ @logger = logger
26
28
 
27
29
  if File.exists?(config_file)
28
30
  load_config_from_disk
@@ -7,6 +7,10 @@ if defined?(::Rails)
7
7
  initializer 'appsignal.configure_rails_initialization' do |app|
8
8
  app.middleware.insert_before(
9
9
  ActionDispatch::RemoteIp,
10
+ Appsignal::Rack::JSExceptionCatcher
11
+ )
12
+ app.middleware.insert_after(
13
+ Appsignal::Rack::JSExceptionCatcher,
10
14
  Appsignal::Rack::Listener
11
15
  )
12
16
  end
@@ -0,0 +1,46 @@
1
+ module Appsignal
2
+ class JSExceptionTransaction
3
+
4
+ def initialize(data)
5
+ @data = data
6
+ @time = Time.now.to_i
7
+ end
8
+
9
+ def type
10
+ :exception
11
+ end
12
+
13
+ def action
14
+ @data['action']
15
+ end
16
+
17
+ def clear_events!; end
18
+ def convert_values_to_primitives!; end
19
+ def events; []; end
20
+
21
+ def to_hash
22
+ {
23
+ :request_id => SecureRandom.uuid,
24
+ :log_entry => {
25
+ :action => action,
26
+ :path => @data['path'],
27
+ :kind => 'frontend',
28
+ :time => @time,
29
+ :environment => @data['environment'],
30
+ :revision => Appsignal.agent.revision
31
+ },
32
+ :exception => {
33
+ :exception => @data['name'],
34
+ :message => @data['message'],
35
+ :backtrace => @data['backtrace']
36
+ },
37
+ :failed => true
38
+ }
39
+ end
40
+
41
+ def complete!
42
+ Appsignal.enqueue(self)
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ module Appsignal
2
+ module Rack
3
+ class JSExceptionCatcher
4
+ def initialize(app, options = {})
5
+ Appsignal.logger.debug 'Initializing Appsignal::Rack::JSExceptionCatcher'
6
+ @app, @options = app, options
7
+ end
8
+
9
+ def call(env)
10
+ if env['PATH_INFO'] == Appsignal.config[:frontend_error_catching_path]
11
+ if Appsignal.config.active? &&
12
+ Appsignal.config[:enable_frontend_error_catching] == true
13
+
14
+ body = JSON.parse(env['rack.input'].read)
15
+ transaction = JSExceptionTransaction.new(body)
16
+ transaction.complete!
17
+ end
18
+ return [ 200, {}, []]
19
+ else
20
+ @app.call(env)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module Appsignal
2
- VERSION = '0.11.7'
2
+ VERSION = '0.11.8.beta.0'
3
3
  end
@@ -16,16 +16,18 @@ describe Appsignal::Config do
16
16
 
17
17
  it "should merge with the default config and fill the config hash" do
18
18
  subject.config_hash.should == {
19
- :ignore_exceptions => [],
20
- :ignore_actions => [],
21
- :instrument_net_http => true,
22
- :skip_session_data => false,
23
- :send_params => true,
24
- :endpoint => 'https://push.appsignal.com/1',
25
- :slow_request_threshold => 200,
26
- :push_api_key => 'abc',
27
- :name => 'TestApp',
28
- :active => true
19
+ :ignore_exceptions => [],
20
+ :ignore_actions => [],
21
+ :instrument_net_http => true,
22
+ :skip_session_data => false,
23
+ :send_params => true,
24
+ :endpoint => 'https://push.appsignal.com/1',
25
+ :slow_request_threshold => 200,
26
+ :push_api_key => 'abc',
27
+ :name => 'TestApp',
28
+ :active => true,
29
+ :enable_frontend_error_catching => false,
30
+ :frontend_error_catching_path => '/appsignal_error_catcher'
29
31
  }
30
32
  end
31
33
 
@@ -127,15 +129,17 @@ describe Appsignal::Config do
127
129
  )
128
130
 
129
131
  subject.config_hash.should == {
130
- :push_api_key => 'push_api_key',
131
- :ignore_exceptions => [],
132
- :ignore_actions => [],
133
- :send_params => true,
134
- :instrument_net_http => true,
135
- :skip_session_data => false,
136
- :endpoint => 'https://push.appsignal.com/1',
137
- :slow_request_threshold => 200,
138
- :active => true
132
+ :push_api_key => 'push_api_key',
133
+ :ignore_exceptions => [],
134
+ :ignore_actions => [],
135
+ :send_params => true,
136
+ :instrument_net_http => true,
137
+ :skip_session_data => false,
138
+ :endpoint => 'https://push.appsignal.com/1',
139
+ :slow_request_threshold => 200,
140
+ :active => true,
141
+ :enable_frontend_error_catching => false,
142
+ :frontend_error_catching_path => '/appsignal_error_catcher'
139
143
  }
140
144
  end
141
145
 
@@ -40,6 +40,10 @@ if rails_present?
40
40
  MyApp::Application.middleware.to_a.should include Appsignal::Rack::Listener
41
41
  end
42
42
 
43
+ it "should have added the js exception catcher middleware" do
44
+ MyApp::Application.middleware.to_a.should include Appsignal::Rack::JSExceptionCatcher
45
+ end
46
+
43
47
  it "should not have added the instrumentation middleware" do
44
48
  MyApp::Application.middleware.to_a.should_not include Appsignal::Rack::Instrumentation
45
49
  end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Appsignal::JSExceptionTransaction do
4
+ let(:transaction) { Appsignal::JSExceptionTransaction.new(data) }
5
+ let(:data) do
6
+ {
7
+ 'name' => 'TypeError',
8
+ 'message' => 'foo is not a valid method',
9
+ 'action' => 'ExceptionIncidentComponent',
10
+ 'path' => 'foo.bar/moo',
11
+ 'environment' => 'development',
12
+ 'backtrace' => [
13
+ 'foo.bar/js:11:1',
14
+ 'foo.bar/js:22:2',
15
+ ]
16
+ }
17
+ end
18
+
19
+ describe "#type" do
20
+ it "should return `:exception`" do
21
+ expect( transaction.type ).to eql :exception
22
+ end
23
+ end
24
+
25
+ describe "#action" do
26
+ it "should return the action" do
27
+ expect( transaction.action ).to eql 'ExceptionIncidentComponent'
28
+ end
29
+ end
30
+
31
+ describe "#clear_events" do
32
+ it "should respond to `clear_events!`" do
33
+ expect( transaction ).to respond_to :clear_events!
34
+ end
35
+ end
36
+
37
+ describe "#convert_values_to_primitives!" do
38
+ it "should respond to `convert_values_to_primitives!`" do
39
+ expect( transaction ).to respond_to :convert_values_to_primitives!
40
+ end
41
+ end
42
+
43
+ describe "#events" do
44
+ it "should respond to `events` with an empty array" do
45
+ expect( transaction.events ).to eql []
46
+ end
47
+ end
48
+
49
+ describe "#to_hash" do
50
+ around do |sample|
51
+ Timecop.freeze(Time.at(123)) { sample.run }
52
+ end
53
+
54
+ before do
55
+ SecureRandom.stub(:uuid => 'uuid')
56
+ Appsignal.stub(:agent => double(:revision => 'abcdef'))
57
+ end
58
+
59
+ it "should generate a hash based on the given data" do
60
+ expect( transaction.to_hash).to eql({
61
+ :request_id => 'uuid',
62
+ :log_entry => {
63
+ :action => 'ExceptionIncidentComponent',
64
+ :path => 'foo.bar/moo',
65
+ :kind => 'frontend',
66
+ :time => 123,
67
+ :environment => 'development',
68
+ :revision => 'abcdef'
69
+ },
70
+ :exception => {
71
+ :exception => 'TypeError',
72
+ :message => 'foo is not a valid method',
73
+ :backtrace => [
74
+ 'foo.bar/js:11:1',
75
+ 'foo.bar/js:22:2',
76
+ ]
77
+ },
78
+ :failed => true
79
+ })
80
+ end
81
+
82
+ describe "#complete!" do
83
+ it "should enqueue itself" do
84
+ expect( Appsignal ).to receive(:enqueue).with(transaction)
85
+
86
+ transaction.complete!
87
+ end
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe Appsignal::Rack::JSExceptionCatcher do
4
+ let(:app) { double(:call => true) }
5
+ let(:options) { double }
6
+ let(:active) { true }
7
+ let(:config_options) { {:enable_frontend_error_catching => true} }
8
+ let(:config) { project_fixture_config('production', config_options) }
9
+
10
+ before do
11
+ Appsignal.stub(:config => config)
12
+ config.stub(:active? => active)
13
+ end
14
+
15
+ describe "#initialize" do
16
+ it "should log to the logger" do
17
+ expect( Appsignal.logger ).to receive(:debug)
18
+ .with('Initializing Appsignal::Rack::JSExceptionCatcher')
19
+
20
+ Appsignal::Rack::JSExceptionCatcher.new(app, options)
21
+ end
22
+ end
23
+
24
+ describe "#call" do
25
+ let(:catcher) { Appsignal::Rack::JSExceptionCatcher.new(app, options) }
26
+
27
+ context "when path is not `/appsignal_error_catcher`" do
28
+ let(:env) { {'PATH_INFO' => '/foo'} }
29
+
30
+ it "should call the next middleware" do
31
+ expect( app ).to receive(:call).with(env)
32
+ end
33
+ end
34
+
35
+ context "when path is `/appsignal_error_catcher`" do
36
+ let(:transaction) { double(:complete! => true) }
37
+ let(:env) do
38
+ {
39
+ 'PATH_INFO' => '/appsignal_error_catcher',
40
+ 'rack.input' => double(:read => '{"foo": "bar"}')
41
+ }
42
+ end
43
+
44
+ it "should create a JSExceptionTransaction" do
45
+ expect( Appsignal::JSExceptionTransaction ).to receive(:new)
46
+ .with({'foo' => 'bar'})
47
+ .and_return(transaction)
48
+
49
+ expect( transaction ).to receive(:complete!)
50
+ end
51
+
52
+ context "when appsignal is not active" do
53
+ let(:active) { false }
54
+
55
+ it "should not create a transaction" do
56
+ expect( Appsignal::JSExceptionTransaction ).to_not receive(:new)
57
+ end
58
+ end
59
+
60
+ context "when `enable_frontend_error_catching` is disabled" do
61
+ let(:config_options) { {:enable_frontend_error_catching => false} }
62
+
63
+ it "should not create a transaction" do
64
+ expect( Appsignal::JSExceptionTransaction ).to_not receive(:new)
65
+ end
66
+ end
67
+
68
+ context "when `frontend_error_catching_path` is different" do
69
+ let(:config_options) do
70
+ {
71
+ :enable_frontend_error_catching => true,
72
+ :frontend_error_catching_path => '/foo'
73
+ }
74
+ end
75
+
76
+ it "should not create a transaction" do
77
+ expect( Appsignal::JSExceptionTransaction ).to_not receive(:new)
78
+ end
79
+
80
+ it "should call the next middleware" do
81
+ expect( app ).to receive(:call).with(env)
82
+ end
83
+ end
84
+ end
85
+
86
+ after { catcher.call(env) }
87
+ end
88
+
89
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.7
4
+ version: 0.11.8.beta.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Beekman
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-02-20 00:00:00.000000000 Z
15
+ date: 2015-03-03 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rack
@@ -170,9 +170,11 @@ files:
170
170
  - lib/appsignal/integrations/sinatra.rb
171
171
  - lib/appsignal/integrations/unicorn.rb
172
172
  - lib/appsignal/ipc.rb
173
+ - lib/appsignal/js_exception_transaction.rb
173
174
  - lib/appsignal/marker.rb
174
175
  - lib/appsignal/params_sanitizer.rb
175
176
  - lib/appsignal/rack/instrumentation.rb
177
+ - lib/appsignal/rack/js_exception_catcher.rb
176
178
  - lib/appsignal/rack/listener.rb
177
179
  - lib/appsignal/rack/sinatra_instrumentation.rb
178
180
  - lib/appsignal/transaction.rb
@@ -213,9 +215,11 @@ files:
213
215
  - spec/lib/appsignal/integrations/sinatra_spec.rb
214
216
  - spec/lib/appsignal/integrations/unicorn_spec.rb
215
217
  - spec/lib/appsignal/ipc_spec.rb
218
+ - spec/lib/appsignal/js_exception_transaction_spec.rb
216
219
  - spec/lib/appsignal/marker_spec.rb
217
220
  - spec/lib/appsignal/params_sanitizer_spec.rb
218
221
  - spec/lib/appsignal/rack/instrumentation_spec.rb
222
+ - spec/lib/appsignal/rack/js_exception_catcher_spec.rb
219
223
  - spec/lib/appsignal/rack/listener_spec.rb
220
224
  - spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb
221
225
  - spec/lib/appsignal/transaction/formatter_spec.rb
@@ -250,9 +254,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
250
254
  version: '1.9'
251
255
  required_rubygems_version: !ruby/object:Gem::Requirement
252
256
  requirements:
253
- - - ">="
257
+ - - ">"
254
258
  - !ruby/object:Gem::Version
255
- version: '0'
259
+ version: 1.3.1
256
260
  requirements: []
257
261
  rubyforge_project:
258
262
  rubygems_version: 2.2.2
@@ -284,9 +288,11 @@ test_files:
284
288
  - spec/lib/appsignal/integrations/sinatra_spec.rb
285
289
  - spec/lib/appsignal/integrations/unicorn_spec.rb
286
290
  - spec/lib/appsignal/ipc_spec.rb
291
+ - spec/lib/appsignal/js_exception_transaction_spec.rb
287
292
  - spec/lib/appsignal/marker_spec.rb
288
293
  - spec/lib/appsignal/params_sanitizer_spec.rb
289
294
  - spec/lib/appsignal/rack/instrumentation_spec.rb
295
+ - spec/lib/appsignal/rack/js_exception_catcher_spec.rb
290
296
  - spec/lib/appsignal/rack/listener_spec.rb
291
297
  - spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb
292
298
  - spec/lib/appsignal/transaction/formatter_spec.rb