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
data/Makefile DELETED
@@ -1,3 +0,0 @@
1
- test:
2
- bundle install
3
- rake spec
@@ -1,9 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 3.0.0"
4
- gem "rake"
5
- gem "rspec"
6
-
7
- gem "opbeat", :path => "../"
8
-
9
- gemspec :path => "../"
@@ -1,9 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 3.1.0"
4
- gem "rake"
5
- gem "rspec"
6
-
7
- gem "opbeat", :path => "../"
8
-
9
- gemspec :path => "../"
@@ -1,9 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 3.2.0"
4
- gem "rake"
5
- gem "rspec"
6
-
7
- gem "opbeat", :path => "../"
8
-
9
- gemspec :path => "../"
@@ -1,9 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 4.0.0"
4
- gem "rake"
5
- gem "rspec"
6
-
7
- gem "opbeat", :path => "../"
8
-
9
- gemspec :path => "../"
@@ -1,9 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 4.1.0"
4
- gem "rake"
5
- gem "rspec"
6
-
7
- gem "opbeat", :path => "../"
8
-
9
- gemspec :path => "../"
@@ -1,9 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 4.2.0"
4
- gem "rake"
5
- gem "rspec"
6
-
7
- gem "opbeat", :path => "../"
8
-
9
- gemspec :path => "../"
@@ -1,10 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "i18n", "~> 0.6.11" # pin to <0.7 to support ruby 1.9.2
4
- gem "rails", "~> 3.1.0"
5
- gem "rake"
6
- gem "rspec"
7
-
8
- gem "opbeat", :path => "../"
9
-
10
- gemspec :path => "../"
@@ -1,10 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "i18n", "~> 0.6.11" # pin to <0.7 to support ruby 1.9.2
4
- gem "rails", "~> 3.2.0"
5
- gem "rake"
6
- gem "rspec"
7
-
8
- gem "opbeat", :path => "../"
9
-
10
- gemspec :path => "../"
@@ -1,11 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gem "rails", "~> 3.2.6"
4
- gem "rake"
5
- gem "rspec"
6
- gem "simplecov"
7
- gem "delayed_job"
8
- gem "sidekiq", "~> 3.1.0"
9
- gem "opbeat", :path => "../"
10
-
11
- gemspec :path => "../"
@@ -1,44 +0,0 @@
1
- require 'set'
2
-
3
- module Opbeat
4
- module BetterAttrAccessor
5
-
6
- def attributes
7
- Hash[
8
- self.class.attributes.map do |attr|
9
- [attr, send(attr)]
10
- end
11
- ]
12
- end
13
-
14
- def self.included(base)
15
- base.extend ClassMethods
16
- end
17
-
18
- module ClassMethods
19
- def attributes
20
- @attributes ||= Set.new
21
-
22
- if superclass.include? BetterAttrAccessor
23
- @attributes + superclass.attributes
24
- else
25
- @attributes
26
- end
27
- end
28
-
29
- def attr_accessor(attr, options = {})
30
- @attributes ||= Set.new
31
- @attributes << attr.to_s
32
-
33
- define_method attr do
34
- if instance_variable_defined? "@#{attr}"
35
- instance_variable_get "@#{attr}"
36
- elsif options.key? :default
37
- instance_variable_set "@#{attr}", options[:default].dup
38
- end
39
- end
40
- attr_writer attr
41
- end
42
- end
43
- end
44
- end
data/lib/opbeat/event.rb DELETED
@@ -1,223 +0,0 @@
1
- require 'rubygems'
2
- require 'socket'
3
-
4
- require 'opbeat/error'
5
- require 'opbeat/linecache'
6
-
7
- module Opbeat
8
-
9
- class Event
10
-
11
- LOG_LEVELS = {
12
- "debug" => "debug",
13
- "info" => "info",
14
- "warn" => "warn",
15
- "warning" => "warn",
16
- "error" => "error",
17
- }
18
-
19
- BACKTRACE_RE = /^(.+?):(\d+)(?::in `(.+?)')?$/
20
-
21
- attr_reader :id
22
- attr_accessor :organization, :app, :message, :timestamp, :level
23
- attr_accessor :logger, :culprit, :hostname, :modules, :extra, :user
24
- attr_accessor :environment
25
-
26
- def initialize(options={}, configuration=nil, &block)
27
- @configuration = configuration || Opbeat.configuration
28
- @interfaces = {}
29
-
30
- @id = options[:id]
31
- @message = options[:message]
32
- @timestamp = options[:timestamp] || Time.now.utc
33
- @level = options[:level] || :error
34
- @logger = options[:logger] || 'root'
35
- @culprit = options[:culprit]
36
- @environment = @configuration[:current_environment]
37
- @extra = options[:extra]
38
- @user = options[:user]
39
-
40
- # Try to resolve the hostname to an FQDN, but fall back to whatever the load name is
41
- hostname = Socket.gethostname
42
- hostname = Socket.gethostbyname(hostname).first rescue hostname
43
- @hostname = options[:hostname] || hostname
44
-
45
- block.call(self) if block
46
-
47
- # Some type coercion
48
- @timestamp = @timestamp.strftime('%Y-%m-%dT%H:%M:%S') if @timestamp.is_a?(Time)
49
- @level = LOG_LEVELS[@level.to_s.downcase] if @level.is_a?(String) || @level.is_a?(Symbol)
50
-
51
- # Basic sanity checking
52
- raise Error.new('A message is required for all events') unless @message && !@message.empty?
53
- raise Error.new('A timestamp is required for all events') unless @timestamp
54
- end
55
-
56
- def interface(name, value=nil, &block)
57
- int = Opbeat::find_interface(name)
58
- Opbeat.logger.info "Unknown interface: #{name}" unless int
59
- raise Error.new("Unknown interface: #{name}") unless int
60
- @interfaces[int.name] = int.new(value, &block) if value || block
61
- @interfaces[int.name]
62
- end
63
-
64
- def [](key)
65
- interface(key)
66
- end
67
-
68
- def []=(key, value)
69
- interface(key, value)
70
- end
71
-
72
- def to_hash
73
- data = {
74
- 'message' => self.message,
75
- 'timestamp' => self.timestamp,
76
- 'level' => self.level,
77
- 'logger' => self.logger,
78
- }
79
- data['client_supplied_id'] = self.id if self.id
80
- data['culprit'] = self.culprit if self.culprit
81
- data['machine'] = {'hostname' => self.hostname } if self.hostname
82
- data['environment'] = self.environment if self.environment # Future proofing: Environment is currently not used by the Opbeat API
83
- data['extra'] = self.extra || {}
84
- data['extra']['ruby'] = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}" unless data['extra']['ruby']
85
- data['extra']['rails'] = ::Rails::VERSION::STRING if defined?(::Rails::VERSION::STRING) && !data['extra']['rails']
86
- if self.user
87
- data['user'] = self.user
88
- if self.user[:id] or self.user[:email] or self.user[:username]
89
- data['user'][:is_authenticated] = true
90
- end
91
- data['user'][:is_authenticated] = false if !data['user'][:is_authenticated]
92
- end
93
- @interfaces.each_pair do |name, int_data|
94
- data[name] = int_data.to_hash
95
- end
96
- data
97
- end
98
-
99
- def self.from_exception(exc, options={}, &block)
100
- configuration = Opbeat.configuration
101
- if exc.is_a?(Opbeat::Error)
102
- # Try to prevent error reporting loops
103
- Opbeat.logger.info "Refusing to capture Opbeat error: #{exc.inspect}"
104
- return nil
105
- end
106
- if configuration[:excluded_exceptions].include? exc.class.name
107
- Opbeat.logger.info "User excluded error: #{exc.inspect}"
108
- return nil
109
- end
110
- options = self.merge_context(options)
111
- self.new(options, configuration) do |evt|
112
- evt.message = "#{exc.class.to_s}: #{exc.message}"
113
- evt.level = :error
114
- evt.parse_exception(exc)
115
- evt.interface :stack_trace do |int|
116
- int.frames = exc.backtrace.reverse.map do |trace_line|
117
- int.frame {|frame| evt.parse_backtrace_line(trace_line, frame) }
118
- end
119
- evt.culprit = evt.get_culprit(int.frames)
120
- end
121
- block.call(evt) if block
122
- end
123
- end
124
-
125
- def self.from_rack_exception(exc, rack_env, options={}, &block)
126
- from_exception(exc, options) do |evt|
127
- evt.interface :http do |int|
128
- int.from_rack(rack_env)
129
- end
130
-
131
- if not evt.user
132
- controller = rack_env["action_controller.instance"]
133
- user_method_name = Opbeat.configuration.user_controller_method
134
- if controller and controller.respond_to? user_method_name
135
- user_obj = controller.send user_method_name
136
- evt.from_user_object(user_obj)
137
- end
138
- end
139
-
140
- block.call(evt) if block
141
- end
142
- end
143
-
144
- def self.from_message(message, stack, options={})
145
- configuration = Opbeat.configuration
146
- options = self.merge_context(options)
147
- self.new(options, configuration) do |evt|
148
- evt.message = message
149
- evt.level = :error
150
- evt.interface :message do |int|
151
- int.message = message
152
- end
153
- evt.interface :stack_trace do |int|
154
- int.frames = stack.reverse.map do |trace_line|
155
- int.frame {|frame| evt.parse_backtrace_line(trace_line, frame) }
156
- end
157
- end
158
- end
159
- end
160
-
161
- def self.set_context(options={})
162
- Thread.current["_opbeat_context"] = options
163
- end
164
-
165
- def get_culprit(frames)
166
- lastframe = frames[-2]
167
- "#{lastframe.filename} in #{lastframe.function}" if lastframe
168
- end
169
-
170
- def parse_exception(exception)
171
- interface(:exception) do |int|
172
- int.type = exception.class.to_s
173
- int.value = exception.message
174
- int.module = exception.class.to_s.split('::')[0...-1].join('::')
175
- end
176
- end
177
-
178
- def parse_backtrace_line(line, frame)
179
- md = BACKTRACE_RE.match(line)
180
- raise Error.new("Unable to parse backtrace line: #{line.inspect}") unless md
181
- frame.abs_path = md[1]
182
- frame.lineno = md[2].to_i
183
- frame.function = md[3] if md[3]
184
- frame.filename = strip_load_path_from(frame.abs_path)
185
- if context_lines = @configuration[:context_lines]
186
- frame.pre_context, frame.context_line, frame.post_context = \
187
- get_contextlines(frame.abs_path, frame.lineno, context_lines)
188
- end
189
- frame
190
- end
191
-
192
- def from_user_object(user_obj)
193
- @user = {} if not @user
194
- @user[:id] = user_obj.send(:id) rescue nil
195
- @user[:email] = user_obj.send(:email) rescue nil
196
- @user[:username] = user_obj.send(:username) rescue nil
197
- end
198
-
199
- private
200
-
201
- def self.merge_context(options={})
202
- context_options = Thread.current["_opbeat_context"] || {}
203
- context_options.merge(options)
204
- end
205
-
206
-
207
- # Because linecache can go to hell
208
- def self._source_lines(path, from, to)
209
- end
210
-
211
- def get_contextlines(path, line, context)
212
- lines = (2 * context + 1).times.map do |i|
213
- Opbeat::LineCache::getline(path, line - context + i)
214
- end
215
- [lines[0..(context-1)], lines[context], lines[(context+1)..-1]]
216
- end
217
-
218
- def strip_load_path_from(path)
219
- prefix = $:.select {|s| path.start_with?(s.to_s)}.sort_by {|s| s.to_s.length}.last
220
- prefix ? path[prefix.to_s.chomp(File::SEPARATOR).length+1..-1] : path
221
- end
222
- end
223
- end
@@ -1,22 +0,0 @@
1
- begin
2
- require 'resque'
3
- rescue LoadError
4
- end
5
-
6
- if defined?(Resque)
7
-
8
- module Resque
9
- module Failure
10
- # Failure backend for Opbeat
11
- class Opbeat < Base
12
- # @override (see Resque::Failure::Base#save)
13
- # @param (see Resque::Failure::Base#save)
14
- # @return (see Resque::Failure::Base#save)
15
- def save
16
- ::Opbeat.capture_exception(exception)
17
- end
18
- end
19
- end
20
- end
21
-
22
- end
@@ -1,32 +0,0 @@
1
- begin
2
- require 'sidekiq'
3
- rescue LoadError
4
- end
5
-
6
- if defined? Sidekiq
7
- module Opbeat
8
- module Integrations
9
- class Sidekiq
10
- def call(worker, msg, queue)
11
- begin
12
- yield
13
- rescue Exception => ex
14
- raise ex if [Interrupt, SystemExit, SignalException].include? ex.class
15
- ::Opbeat.capture_exception(ex)
16
- raise
17
- end
18
- end
19
- end
20
- end
21
- end
22
-
23
- ::Sidekiq.configure_server do |config|
24
- if ::Sidekiq::VERSION < '3'
25
- config.server_middleware do |chain|
26
- chain.add ::Opbeat::Integrations::Sidekiq
27
- end
28
- else
29
- config.error_handlers << Proc.new { |ex, ctx| ::Opbeat.capture_exception(ex) }
30
- end
31
- end
32
- end
@@ -1,35 +0,0 @@
1
- require 'opbeat/better_attr_accessor'
2
-
3
- module Opbeat
4
-
5
- INTERFACES = {}
6
-
7
- class Interface
8
- include BetterAttrAccessor
9
- alias_method :to_hash, :attributes
10
-
11
- def initialize(attributes = nil)
12
- attributes.each do |attr, value|
13
- send "#{attr}=", value
14
- end if attributes
15
-
16
- yield self if block_given?
17
- end
18
-
19
- def self.name(value = nil)
20
- @interface_name ||= value
21
- end
22
- end
23
-
24
- def self.register_interface(mapping)
25
- mapping.each_pair do |key, klass|
26
- INTERFACES[key.to_s] = klass
27
- INTERFACES[klass.name] = klass
28
- end
29
- end
30
-
31
- def self.find_interface(name)
32
- INTERFACES[name.to_s]
33
- end
34
-
35
- end