opbeat 2.0.0 → 3.0.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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/.travis.yml +19 -28
  4. data/.yardopts +3 -0
  5. data/Gemfile +4 -2
  6. data/HISTORY.md +3 -0
  7. data/LICENSE +7 -196
  8. data/README.md +96 -177
  9. data/Rakefile +19 -13
  10. data/gemfiles/Gemfile.base +28 -0
  11. data/gemfiles/Gemfile.rails-3.2.x +3 -0
  12. data/gemfiles/Gemfile.rails-4.0.x +3 -0
  13. data/gemfiles/Gemfile.rails-4.1.x +3 -0
  14. data/gemfiles/Gemfile.rails-4.2.x +3 -0
  15. data/lib/opbeat.rb +113 -93
  16. data/lib/opbeat/capistrano.rb +3 -4
  17. data/lib/opbeat/client.rb +243 -82
  18. data/lib/opbeat/configuration.rb +51 -64
  19. data/lib/opbeat/data_builders.rb +16 -0
  20. data/lib/opbeat/data_builders/error.rb +27 -0
  21. data/lib/opbeat/data_builders/transactions.rb +85 -0
  22. data/lib/opbeat/error.rb +1 -2
  23. data/lib/opbeat/error_message.rb +71 -0
  24. data/lib/opbeat/error_message/exception.rb +12 -0
  25. data/lib/opbeat/error_message/http.rb +62 -0
  26. data/lib/opbeat/error_message/stacktrace.rb +75 -0
  27. data/lib/opbeat/error_message/user.rb +23 -0
  28. data/lib/opbeat/filter.rb +53 -43
  29. data/lib/opbeat/http_client.rb +141 -0
  30. data/lib/opbeat/injections.rb +83 -0
  31. data/lib/opbeat/injections/json.rb +19 -0
  32. data/lib/opbeat/injections/net_http.rb +43 -0
  33. data/lib/opbeat/injections/redis.rb +23 -0
  34. data/lib/opbeat/injections/sequel.rb +32 -0
  35. data/lib/opbeat/injections/sinatra.rb +56 -0
  36. data/lib/opbeat/{capistrano → integration}/capistrano2.rb +6 -6
  37. data/lib/opbeat/{capistrano → integration}/capistrano3.rb +3 -3
  38. data/lib/opbeat/{integrations → integration}/delayed_job.rb +6 -11
  39. data/lib/opbeat/integration/rails/inject_exceptions_catcher.rb +23 -0
  40. data/lib/opbeat/integration/railtie.rb +53 -0
  41. data/lib/opbeat/integration/resque.rb +16 -0
  42. data/lib/opbeat/integration/sidekiq.rb +38 -0
  43. data/lib/opbeat/line_cache.rb +21 -0
  44. data/lib/opbeat/logging.rb +37 -0
  45. data/lib/opbeat/middleware.rb +59 -0
  46. data/lib/opbeat/normalizers.rb +65 -0
  47. data/lib/opbeat/normalizers/action_controller.rb +21 -0
  48. data/lib/opbeat/normalizers/action_view.rb +71 -0
  49. data/lib/opbeat/normalizers/active_record.rb +41 -0
  50. data/lib/opbeat/sql_summarizer.rb +27 -0
  51. data/lib/opbeat/subscriber.rb +80 -0
  52. data/lib/opbeat/tasks.rb +20 -18
  53. data/lib/opbeat/trace.rb +47 -0
  54. data/lib/opbeat/trace_helpers.rb +29 -0
  55. data/lib/opbeat/transaction.rb +99 -0
  56. data/lib/opbeat/util.rb +26 -0
  57. data/lib/opbeat/util/constantize.rb +54 -0
  58. data/lib/opbeat/util/inspector.rb +75 -0
  59. data/lib/opbeat/version.rb +1 -1
  60. data/lib/opbeat/worker.rb +55 -0
  61. data/opbeat.gemspec +6 -14
  62. data/spec/opbeat/client_spec.rb +216 -29
  63. data/spec/opbeat/configuration_spec.rb +34 -38
  64. data/spec/opbeat/data_builders/error_spec.rb +43 -0
  65. data/spec/opbeat/data_builders/transactions_spec.rb +51 -0
  66. data/spec/opbeat/error_message/exception_spec.rb +22 -0
  67. data/spec/opbeat/error_message/http_spec.rb +65 -0
  68. data/spec/opbeat/error_message/stacktrace_spec.rb +56 -0
  69. data/spec/opbeat/error_message/user_spec.rb +28 -0
  70. data/spec/opbeat/error_message_spec.rb +78 -0
  71. data/spec/opbeat/filter_spec.rb +21 -99
  72. data/spec/opbeat/http_client_spec.rb +64 -0
  73. data/spec/opbeat/injections/net_http_spec.rb +37 -0
  74. data/spec/opbeat/injections/sequel_spec.rb +33 -0
  75. data/spec/opbeat/injections/sinatra_spec.rb +13 -0
  76. data/spec/opbeat/injections_spec.rb +49 -0
  77. data/spec/opbeat/integration/delayed_job_spec.rb +35 -0
  78. data/spec/opbeat/integration/json_spec.rb +41 -0
  79. data/spec/opbeat/integration/rails_spec.rb +88 -0
  80. data/spec/opbeat/integration/redis_spec.rb +20 -0
  81. data/spec/opbeat/integration/resque_spec.rb +42 -0
  82. data/spec/opbeat/integration/sidekiq_spec.rb +40 -0
  83. data/spec/opbeat/integration/sinatra_spec.rb +66 -0
  84. data/spec/opbeat/line_cache_spec.rb +38 -0
  85. data/spec/opbeat/logging_spec.rb +47 -0
  86. data/spec/opbeat/middleware_spec.rb +32 -0
  87. data/spec/opbeat/normalizers/action_controller_spec.rb +32 -0
  88. data/spec/opbeat/normalizers/action_view_spec.rb +77 -0
  89. data/spec/opbeat/normalizers/active_record_spec.rb +70 -0
  90. data/spec/opbeat/normalizers_spec.rb +16 -0
  91. data/spec/opbeat/sql_summarizer_spec.rb +6 -0
  92. data/spec/opbeat/subscriber_spec.rb +83 -0
  93. data/spec/opbeat/trace_spec.rb +43 -0
  94. data/spec/opbeat/transaction_spec.rb +98 -0
  95. data/spec/opbeat/util/inspector_spec.rb +40 -0
  96. data/spec/opbeat/util_spec.rb +20 -0
  97. data/spec/opbeat/worker_spec.rb +54 -0
  98. data/spec/opbeat_spec.rb +49 -0
  99. data/spec/spec_helper.rb +79 -6
  100. metadata +89 -149
  101. data/Makefile +0 -3
  102. data/gemfiles/rails30.gemfile +0 -9
  103. data/gemfiles/rails31.gemfile +0 -9
  104. data/gemfiles/rails32.gemfile +0 -9
  105. data/gemfiles/rails40.gemfile +0 -9
  106. data/gemfiles/rails41.gemfile +0 -9
  107. data/gemfiles/rails42.gemfile +0 -9
  108. data/gemfiles/ruby192_rails31.gemfile +0 -10
  109. data/gemfiles/ruby192_rails32.gemfile +0 -10
  110. data/gemfiles/sidekiq31.gemfile +0 -11
  111. data/lib/opbeat/better_attr_accessor.rb +0 -44
  112. data/lib/opbeat/event.rb +0 -223
  113. data/lib/opbeat/integrations/resque.rb +0 -22
  114. data/lib/opbeat/integrations/sidekiq.rb +0 -32
  115. data/lib/opbeat/interfaces.rb +0 -35
  116. data/lib/opbeat/interfaces/exception.rb +0 -16
  117. data/lib/opbeat/interfaces/http.rb +0 -57
  118. data/lib/opbeat/interfaces/message.rb +0 -19
  119. data/lib/opbeat/interfaces/stack_trace.rb +0 -50
  120. data/lib/opbeat/linecache.rb +0 -25
  121. data/lib/opbeat/logger.rb +0 -21
  122. data/lib/opbeat/rack.rb +0 -46
  123. data/lib/opbeat/rails/middleware/debug_exceptions_catcher.rb +0 -22
  124. data/lib/opbeat/railtie.rb +0 -26
  125. data/spec/opbeat/better_attr_accessor_spec.rb +0 -99
  126. data/spec/opbeat/event_spec.rb +0 -138
  127. data/spec/opbeat/integrations/delayed_job_spec.rb +0 -38
  128. data/spec/opbeat/logger_spec.rb +0 -55
  129. data/spec/opbeat/opbeat_spec.rb +0 -64
  130. data/spec/opbeat/rack_spec.rb +0 -117
@@ -1,16 +0,0 @@
1
- require 'opbeat/interfaces'
2
-
3
- module Opbeat
4
-
5
- class ExceptionInterface < Interface
6
-
7
- name 'exception'
8
- attr_accessor :type
9
- attr_accessor :value
10
- attr_accessor :module
11
-
12
- end
13
-
14
- register_interface :exception => ExceptionInterface
15
-
16
- end
@@ -1,57 +0,0 @@
1
- require 'opbeat/interfaces'
2
-
3
- module Opbeat
4
-
5
- class HttpInterface < Interface
6
-
7
- name 'http'
8
- attr_accessor :url
9
- attr_accessor :method
10
- attr_accessor :data
11
- attr_accessor :query_string
12
- attr_accessor :cookies
13
- attr_accessor :headers
14
- attr_accessor :remote_host
15
- attr_accessor :http_host
16
- attr_accessor :env
17
-
18
- def initialize(*arguments)
19
- self.headers = {}
20
- self.env = {}
21
- super(*arguments)
22
- end
23
-
24
- def from_rack(env)
25
- require 'rack'
26
- req = ::Rack::Request.new(env)
27
- self.url = req.url.split('?').first
28
- self.method = req.request_method
29
- self.query_string = req.query_string
30
- self.cookies = req.cookies.collect {|k,v| "#{k}=#{v}"}.join(';')
31
- self.remote_host = req.ip
32
- self.http_host = req.host_with_port
33
- env.each_pair do |key, value|
34
- next unless key.upcase == key # Non-upper case stuff isn't either
35
- if key.start_with?('HTTP_')
36
- # Header
37
- http_key = key[5..key.length-1].split('_').map{|s| s.capitalize}.join('-')
38
- self.headers[http_key] = value.to_s
39
- else
40
- # Environment
41
- self.env[key] = value.to_s
42
- end
43
- end
44
- self.data = if req.form_data?
45
- req.POST
46
- elsif req.body
47
- data = req.body.read
48
- req.body.rewind
49
- data
50
- end
51
- end
52
-
53
- end
54
-
55
- register_interface :http => HttpInterface
56
-
57
- end
@@ -1,19 +0,0 @@
1
- require 'opbeat/interfaces'
2
-
3
- module Opbeat
4
-
5
- class MessageInterface < Interface
6
-
7
- name 'param_message'
8
- attr_accessor :message
9
- attr_accessor :params
10
-
11
- def initialize(*arguments)
12
- self.params = []
13
- super(*arguments)
14
- end
15
- end
16
-
17
- register_interface :message => MessageInterface
18
-
19
- end
@@ -1,50 +0,0 @@
1
- require 'opbeat/interfaces'
2
-
3
- module Opbeat
4
-
5
- class StacktraceInterface < Interface
6
-
7
- name 'stacktrace'
8
- attr_accessor :frames, :default => []
9
-
10
- def initialize(*arguments)
11
- self.frames = []
12
- super(*arguments)
13
- end
14
-
15
- def to_hash
16
- data = super
17
- data['frames'] = data['frames'].map{|frame| frame.to_hash}
18
- data
19
- end
20
-
21
- def frame(attributes=nil, &block)
22
- Frame.new(attributes, &block)
23
- end
24
-
25
- # Not actually an interface, but I want to use the same style
26
- class Frame < Interface
27
- attr_accessor :abs_path
28
- attr_accessor :filename
29
- attr_accessor :function
30
- attr_accessor :vars, :default => {}
31
- attr_accessor :pre_context, :default => []
32
- attr_accessor :post_context, :default => []
33
- attr_accessor :context_line
34
- attr_accessor :lineno
35
-
36
- def to_hash
37
- data = super
38
- data.delete('vars') unless self.vars && !self.vars.empty?
39
- data.delete('pre_context') unless self.pre_context && !self.pre_context.empty?
40
- data.delete('post_context') unless self.post_context && !self.post_context.empty?
41
- data.delete('context_line') unless self.context_line && !self.context_line.empty?
42
- data
43
- end
44
- end
45
-
46
- end
47
-
48
- register_interface :stack_trace => StacktraceInterface
49
-
50
- end
@@ -1,25 +0,0 @@
1
- # A much simpler source line cacher because linecache sucks at platform compat
2
-
3
- module Opbeat
4
-
5
- class LineCache
6
- class << self
7
- CACHE = {}
8
-
9
- def getlines(path)
10
- CACHE[path] ||= begin
11
- IO.readlines(path)
12
- rescue
13
- []
14
- end
15
- end
16
-
17
- def getline(path, n)
18
- return nil if n < 1
19
- getlines(path)[n-1]
20
- end
21
-
22
- end
23
- end
24
-
25
- end
data/lib/opbeat/logger.rb DELETED
@@ -1,21 +0,0 @@
1
- module Opbeat
2
- class Logger
3
- LOG_PREFIX = "** [Opbeat] "
4
-
5
- [
6
- :fatal,
7
- :error,
8
- :warn,
9
- :info,
10
- :debug,
11
- ].each do |level|
12
- define_method level do |*args, &block|
13
- msg = args[0] # Block-level default args is a 1.9 feature
14
- msg ||= block.call if block
15
- logger = Opbeat.configuration[:logger]
16
- logger.send(level, "#{LOG_PREFIX}#{msg}") if logger
17
- end
18
- end
19
-
20
- end
21
- end
data/lib/opbeat/rack.rb DELETED
@@ -1,46 +0,0 @@
1
- module Opbeat
2
- # Middleware for Rack applications. Any errors raised by the upstream
3
- # application will be delivered to Opbeat and re-raised.
4
- #
5
- # Synopsis:
6
- #
7
- # require 'rack'
8
- # require 'opbeat'
9
- #
10
- # Opbeat.configure do |config|
11
- # config.server = 'http://my_dsn'
12
- # end
13
- #
14
- # app = Rack::Builder.app do
15
- # use Opbeat::Rack
16
- # run lambda { |env| raise "Rack down" }
17
- # end
18
- #
19
- # Use a standard Opbeat.configure call to configure your server credentials.
20
- class Rack
21
- def initialize(app)
22
- @app = app
23
- end
24
-
25
- def call(env)
26
- begin
27
- response = @app.call(env)
28
- rescue Error => e
29
- raise # Don't capture Opbeat errors
30
- rescue Exception => e
31
- evt = Event.from_rack_exception(e, env)
32
- Opbeat.send(evt)
33
- raise
34
- end
35
-
36
- error = env['rack.exception'] || env['sinatra.error']
37
-
38
- if error
39
- evt = Event.from_rack_exception(error, env)
40
- Opbeat.send(evt) if evt
41
- end
42
-
43
- response
44
- end
45
- end
46
- end
@@ -1,22 +0,0 @@
1
- module Opbeat
2
- module Rails
3
- module Middleware
4
- module DebugExceptionsCatcher
5
- def self.included(base)
6
- base.send(:alias_method_chain, :render_exception, :opbeat)
7
- end
8
-
9
- def render_exception_with_opbeat(env, exception)
10
- begin
11
- evt = Opbeat::Event.from_rack_exception(exception, env)
12
- Opbeat.send(evt) if evt
13
- rescue
14
- ::Rails::logger.debug "Error capturing or sending exception #{$!}"
15
- end
16
-
17
- render_exception_without_opbeat(env, exception)
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,26 +0,0 @@
1
- require 'opbeat'
2
- require 'rails'
3
-
4
- module Opbeat
5
- class Railtie < ::Rails::Railtie
6
- initializer "opbeat.use_rack_middleware" do |app|
7
- app.config.middleware.insert 0, "Opbeat::Rack"
8
- end
9
- config.after_initialize do
10
- Opbeat.configure(true) do |config|
11
- config.logger ||= ::Rails.logger
12
- end
13
-
14
- if defined?(::ActionDispatch::DebugExceptions)
15
- require 'opbeat/rails/middleware/debug_exceptions_catcher'
16
- ::ActionDispatch::DebugExceptions.send(:include, Opbeat::Rails::Middleware::DebugExceptionsCatcher)
17
- elsif defined?(::ActionDispatch::ShowExceptions)
18
- require 'opbeat/rails/middleware/debug_exceptions_catcher'
19
- ::ActionDispatch::ShowExceptions.send(:include, Opbeat::Rails::Middleware::DebugExceptionsCatcher)
20
- end
21
- end
22
- rake_tasks do
23
- require 'opbeat/tasks'
24
- end
25
- end
26
- end
@@ -1,99 +0,0 @@
1
- require File::expand_path('../../spec_helper', __FILE__)
2
- require 'opbeat'
3
-
4
- describe Opbeat::BetterAttrAccessor do
5
-
6
- let :klass do
7
- Class.new do
8
- include Opbeat::BetterAttrAccessor
9
-
10
- attr_accessor :a
11
- attr_accessor :b, :default => []
12
- attr_accessor :c
13
- end
14
- end
15
-
16
- let :child do
17
- Class.new klass do
18
- attr_accessor :d
19
- end
20
- end
21
-
22
- subject{ klass.new }
23
-
24
- describe 'the reader method' do
25
- context 'when a value is not set' do
26
- it 'should default to nil' do
27
- expect(subject.a).to eq nil
28
- end
29
- it 'should use a default value if provided' do
30
- expect(subject.b).to eq []
31
- expect(subject.instance_variable_get '@b').to eq []
32
- end
33
- end
34
-
35
- context 'when a value is set' do
36
- before do
37
- subject.a = 'foo'
38
- subject.b = :bar
39
- subject.c = false
40
- end
41
-
42
- it 'should save the value' do
43
- expect(subject.a).to eq 'foo'
44
- end
45
- it 'should save a boolean `false` value' do
46
- expect(subject.c).to eq false
47
- end
48
- it 'should no longer return the default' do
49
- expect(subject.b).to eq :bar
50
- end
51
- end
52
-
53
- context 'when a default value is directly modified' do
54
- before { subject.b << 9 }
55
- it 'should not affect a new instance' do
56
- expect(klass.new.b).to eq []
57
- end
58
- end
59
- end
60
-
61
- describe '.attributes' do
62
- it 'should be a Set of all attributes set up' do
63
- expect(klass.attributes).to be_a Set
64
- expect(klass.attributes).to eq %w[a b c].to_set
65
- end
66
- it 'should work with inheritance' do
67
- expect(child.attributes).to eq %w[d a b c].to_set
68
- end
69
- end
70
-
71
- describe '#attributes' do
72
- it 'should return a hash of all attributes' do
73
- subject.a = {'foo' => :bar}
74
- subject.b << 8
75
- expect(subject.attributes).to eq \
76
- 'a' => {'foo' => :bar},
77
- 'b' => [8],
78
- 'c' => nil
79
- end
80
-
81
- describe 'inheritance' do
82
- subject{ child.new }
83
-
84
- before do
85
- subject.a = 21
86
- subject.d = true
87
- end
88
-
89
- it 'should work' do
90
- expect(subject.attributes).to eq \
91
- 'a' => 21,
92
- 'b' => [],
93
- 'c' => nil,
94
- 'd' => true
95
- end
96
- end
97
- end
98
-
99
- end
@@ -1,138 +0,0 @@
1
- require File::expand_path('../../spec_helper', __FILE__)
2
- require 'opbeat'
3
-
4
- describe Opbeat::Event do
5
- describe '.from_message' do
6
- let(:message) { 'This is a message' }
7
- let(:hash) { Opbeat::Event.from_message(message, caller).to_hash }
8
-
9
- context 'for a Message' do
10
- it 'returns an event' do
11
- expect(Opbeat::Event.from_message(message, caller)).to be_a(Opbeat::Event)
12
- end
13
-
14
- it "sets the message to the value passed" do
15
- expect(hash['message']).to eq(message)
16
- end
17
-
18
- it 'has level ERROR' do
19
- expect(hash['level']).to eq('error')
20
- end
21
- end
22
- end
23
-
24
- describe '.from_exception' do
25
- let(:message) { 'This is a message' }
26
- let(:exception) {
27
- exc = Exception.new(message)
28
- exc.set_backtrace caller
29
- exc
30
- }
31
- let(:hash) { Opbeat::Event.from_exception(exception).to_hash }
32
-
33
- context 'for an Exception' do
34
- it 'returns an event' do
35
- expect(Opbeat::Event.from_exception(exception)).to be_a(Opbeat::Event)
36
- end
37
-
38
- it "sets the message to the exception's message and type" do
39
- expect(hash['message']).to eq("Exception: #{message}")
40
- end
41
-
42
- it 'has level ERROR' do
43
- expect(hash['level']).to eq('error')
44
- end
45
-
46
- it 'uses the exception class name as the exception type' do
47
- expect(hash['exception']['type']).to eq('Exception')
48
- end
49
-
50
- it 'uses the exception message as the exception value' do
51
- expect(hash['exception']['value']).to eq(message)
52
- end
53
-
54
- it 'does not belong to a module' do
55
- expect(hash['exception']['module']).to eq('')
56
- end
57
- end
58
-
59
- context 'for a nested exception type' do
60
- module Opbeat::Test
61
- class Exception < Exception; end
62
- end
63
- let(:exception) {
64
- exc = Opbeat::Test::Exception.new(message)
65
- exc.set_backtrace caller
66
- exc
67
- }
68
-
69
- it 'sends the module name as part of the exception info' do
70
- expect(hash['exception']['module']).to eq('Opbeat::Test')
71
- end
72
- end
73
-
74
- context 'for a Opbeat::Error' do
75
- let(:exception) { Opbeat::Error.new }
76
- it 'does not create an event' do
77
- expect(Opbeat::Event.from_exception(exception)).to be_nil
78
- end
79
- end
80
-
81
- context 'when the exception has a backtrace' do
82
- let(:exception) do
83
- e = Exception.new(message)
84
- allow(e).to receive(:backtrace).and_return([
85
- "/path/to/some/file:22:in `function_name'",
86
- "/some/other/path:1412:in `other_function'",
87
- ])
88
- e
89
- end
90
-
91
- it 'parses the backtrace' do
92
- expect(hash['stacktrace']['frames'].length).to eq(2)
93
- expect(hash['stacktrace']['frames'][0]['lineno']).to eq(1412)
94
- expect(hash['stacktrace']['frames'][0]['function']).to eq('other_function')
95
- expect(hash['stacktrace']['frames'][0]['filename']).to eq('/some/other/path')
96
-
97
- expect(hash['stacktrace']['frames'][1]['lineno']).to eq(22)
98
- expect(hash['stacktrace']['frames'][1]['function']).to eq('function_name')
99
- expect(hash['stacktrace']['frames'][1]['filename']).to eq('/path/to/some/file')
100
- end
101
-
102
- it "sets the culprit" do
103
- expect(hash['culprit']).to eq("/some/other/path in other_function")
104
- end
105
-
106
- context 'when a path in the stack trace is on the laod path' do
107
- before do
108
- $LOAD_PATH << '/some'
109
- end
110
-
111
- after do
112
- $LOAD_PATH.delete('/some')
113
- end
114
-
115
- it 'strips prefixes in the load path from frame filenames' do
116
- expect(hash['stacktrace']['frames'][0]['filename']).to eq('other/path')
117
- end
118
- end
119
- end
120
-
121
- context 'when there is user context' do
122
- it 'sends the context and is_authenticated' do
123
- Opbeat::Event.set_context(:user => {:id => 99})
124
- hash = Opbeat::Event.from_exception(exception).to_hash
125
- expect(hash['user']).to eq({:id => 99, :is_authenticated => true})
126
- end
127
- end
128
-
129
- context 'when there is extra context' do
130
- it 'sends the context and is_authenticated' do
131
- extra_context = {:jobid => 99}
132
- Opbeat::Event.set_context(:extra => extra_context)
133
- hash = Opbeat::Event.from_exception(exception).to_hash
134
- expect(hash['extra']).to eq(extra_context)
135
- end
136
- end
137
- end
138
- end