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
@@ -0,0 +1,32 @@
1
+ module Opbeat
2
+ module Injections
3
+ module Sequel
4
+ class Injector
5
+ KIND = 'db.sequel.sql'.freeze
6
+
7
+ def self.sql_parser
8
+ @sql_parser ||= SqlSummarizer.new(nil)
9
+ end
10
+
11
+ def install
12
+ require 'sequel/database/logging'
13
+
14
+ ::Sequel::Database.class_eval do
15
+ alias log_yield_without_opb log_yield
16
+
17
+ def log_yield sql, args = nil, &block
18
+ log_yield_without_opb(sql, *args) do
19
+ sig = Opbeat::Injections::Sequel::Injector.sql_parser.signature_for(sql)
20
+ Opbeat.trace(sig, KIND, sql: sql) do
21
+ block.call
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ register 'Sequel', 'sequel', Sequel::Injector.new
31
+ end
32
+ end
@@ -0,0 +1,56 @@
1
+ module Opbeat
2
+ module Injections
3
+ module Sinatra
4
+ class Injector
5
+ def install
6
+ ::Sinatra::Base.class_eval do
7
+ alias dispatch_without_opb! dispatch!
8
+ alias compile_template_with_opb compile_template
9
+
10
+ def dispatch!(*args, &block)
11
+ dispatch_without_opb!(*args, &block).tap do
12
+ if route = env['sinatra.route']
13
+ Opbeat.transaction(nil).endpoint = route
14
+ end
15
+ end
16
+ end
17
+
18
+ def compile_template engine, data, opts, *args, &block
19
+ case data
20
+ when Symbol
21
+ opts[:__opbeat_template_sig] = data.to_s
22
+ else
23
+ opts[:__opbeat_template_sig] = "Inline #{engine}"
24
+ end
25
+
26
+ compile_template_with_opb(engine, data, opts, *args, &block)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ module Tilt
34
+ class Injector
35
+ KIND = 'template.view'
36
+
37
+ def install
38
+ ::Tilt::Template.class_eval do
39
+ alias render_without_opb render
40
+
41
+ def render(*args, &block)
42
+ sig = options[:__opbeat_template_sig] || 'Uknown template'.freeze
43
+
44
+ Opbeat.trace sig, KIND do
45
+ render_without_opb(*args, &block)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ register 'Sinatra::Base', 'sinatra/base', Sinatra::Injector.new
54
+ register 'Tilt::Template', 'tilt/template', Tilt::Injector.new
55
+ end
56
+ end
@@ -1,6 +1,5 @@
1
- require 'capistrano'
2
-
3
1
  module Opbeat
2
+ # @api private
4
3
  module Capistrano
5
4
  def self.load_into(configuration)
6
5
 
@@ -17,13 +16,13 @@ module Opbeat
17
16
  puts "Skipping Opbeat deployment notification because scm is not git."
18
17
  next
19
18
  end
20
-
19
+
21
20
  branches = capture("cd #{current_release}; /usr/bin/env git branch --contains #{current_revision}").split
22
21
  if branches.length == 1
23
22
  branch = branch[0].sub("* ")
24
23
  else
25
24
  branch = nil
26
- end
25
+ end
27
26
 
28
27
  notify_command = "cd #{current_release}; REV=#{current_revision} "
29
28
  notify_command << "BRANCH=#{branch} " if branch
@@ -32,9 +31,9 @@ module Opbeat
32
31
  notify_command << "RAILS_ENV=#{rails_env} "
33
32
 
34
33
  executable = fetch(:rake, 'bundle exec rake ')
35
- notify_command << "#{executable} opbeat:deployment"
34
+ notify_command << "#{executable} opbeat:release"
36
35
  capture notify_command, :once => true
37
-
36
+
38
37
  end
39
38
  end
40
39
  end
@@ -45,3 +44,4 @@ end
45
44
  if Capistrano::Configuration.instance
46
45
  Opbeat::Capistrano.load_into(Capistrano::Configuration.instance)
47
46
  end
47
+
@@ -1,11 +1,11 @@
1
1
  namespace :opbeat do
2
- desc "Notifies Opbeat of new deployments"
2
+ desc "Notifies Opbeat of new releases"
3
3
  task :notify do
4
4
  on roles(:app) do
5
5
 
6
6
  scm = fetch(:scm)
7
7
  if scm.to_s != "git"
8
- info "Skipping Opbeat deployment because scm is not git."
8
+ info "Skipping Opbeat release because scm is not git."
9
9
  next
10
10
  end
11
11
 
@@ -14,7 +14,7 @@ namespace :opbeat do
14
14
 
15
15
  within release_path do
16
16
  with rails_env: fetch(:rails_env), rev: rev, branch: branch do
17
- capture :rake, 'opbeat:deployment'
17
+ capture :rake, 'opbeat:release'
18
18
  end
19
19
  end
20
20
  end
@@ -3,23 +3,19 @@ begin
3
3
  rescue LoadError
4
4
  end
5
5
 
6
- # Based on the Sentry equivalent.
7
6
  if defined?(Delayed)
8
-
9
7
  module Delayed
10
8
  module Plugins
11
- class Opbeat < ::Delayed::Plugin
9
+ class Opbeat < Delayed::Plugin
12
10
  callbacks do |lifecycle|
13
11
  lifecycle.around(:invoke_job) do |job, *args, &block|
14
12
  begin
15
- # Forward the call to the next callback in the callback chain
16
13
  block.call(job, *args)
17
-
14
+ rescue ::Opbeat::Error
15
+ raise # don't report Opbeat errors
18
16
  rescue Exception => exception
19
- # Log error to Opbeat
20
- ::Opbeat.capture_exception(exception)
21
- # Make sure we propagate the failure!
22
- raise exception
17
+ ::Opbeat.report exception
18
+ raise
23
19
  end
24
20
  end
25
21
  end
@@ -27,6 +23,5 @@ if defined?(Delayed)
27
23
  end
28
24
  end
29
25
 
30
- # Register DelayedJob Opbeat plugin
31
26
  Delayed::Worker.plugins << Delayed::Plugins::Opbeat
32
- end
27
+ end
@@ -0,0 +1,23 @@
1
+ module Opbeat
2
+ module Integration
3
+ module Rails
4
+ module InjectExceptionsCatcher
5
+ def self.included(cls)
6
+ cls.send(:alias_method_chain, :render_exception, :opbeat)
7
+ end
8
+
9
+ def render_exception_with_opbeat(env, exception)
10
+ begin
11
+ Opbeat.report(exception, rack_env: env) if Opbeat.started?
12
+ rescue
13
+ ::Rails::logger.error "** [Opbeat] Error capturing or sending exception #{$!}"
14
+ ::Rails::logger.debug $!.backtrace.join("\n")
15
+ end
16
+
17
+ render_exception_without_opbeat(env, exception)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,53 @@
1
+ require 'opbeat'
2
+ require 'rails'
3
+
4
+ module Opbeat
5
+ class Railtie < Rails::Railtie
6
+
7
+ config.opbeat = ActiveSupport::OrderedOptions.new
8
+ # bootstrap options with the defaults
9
+ Configuration::DEFAULTS.each { |k,v| config.opbeat[k] = v }
10
+
11
+ initializer "opbeat.configure" do |app|
12
+ config = Configuration.new app.config.opbeat do |conf|
13
+ conf.logger = Rails.logger
14
+ conf.view_paths = app.config.paths['app/views'].existent
15
+ end
16
+
17
+ if config.enabled_environments.include?(Rails.env)
18
+ if Opbeat.start!(config)
19
+ app.config.middleware.insert 0, Middleware
20
+ Rails.logger.info "** [Opbeat] Client running"
21
+ else
22
+ # :nocov:
23
+ Rails.logger.info "** [Opbeat] Failed to start"
24
+ # :nocov:
25
+ end
26
+ else
27
+ # :nocov:
28
+ Rails.logger.info "** [Opbeat] Disabled in #{Rails.env} environment"
29
+ # :nocov:
30
+ end
31
+ end
32
+
33
+ config.after_initialize do
34
+ # :nocov:
35
+ require 'opbeat/integration/rails/inject_exceptions_catcher'
36
+ if defined?(ActionDispatch::DebugExceptions)
37
+ ActionDispatch::DebugExceptions.send(
38
+ :include, Opbeat::Integration::Rails::InjectExceptionsCatcher)
39
+ elsif defined?(::ActionDispatch::ShowExceptions)
40
+ ::ActionDispatch::ShowExceptions.send(
41
+ :include, Opbeat::Integration::Rails::InjectExceptionsCatcher)
42
+ end
43
+ # :nocov:
44
+ end
45
+
46
+ rake_tasks do
47
+ # :nocov:
48
+ require 'opbeat/tasks'
49
+ # :nocov:
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'resque'
3
+ rescue LoadError
4
+ end
5
+
6
+ if defined? Resque
7
+ module Opbeat
8
+ module Integration
9
+ class Resque < Resque::Failure::Base
10
+ def save
11
+ Opbeat.report exception
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ begin
2
+ require 'sidekiq'
3
+ rescue LoadError
4
+ end
5
+
6
+ if defined? Sidekiq
7
+ module Opbeat
8
+ module Integration
9
+ class Sidekiq
10
+ def call worker, msg, queue
11
+ begin
12
+ yield
13
+ rescue Exception => exception
14
+ if [Interrupt, SystemExit, SignalException].include? exception.class
15
+ raise exception
16
+ end
17
+
18
+ Opbeat.report exception
19
+
20
+ raise
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ Sidekiq.configure_server do |config|
28
+ if Sidekiq::VERSION.to_i < 3
29
+ config.server_middleware do |chain|
30
+ chain.add Opbeat::Integration::Sidekiq
31
+ end
32
+ else
33
+ config.error_handlers << lambda do |exception|
34
+ Opbeat.report exception
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ module Opbeat
2
+ # @api private
3
+ class LineCache
4
+
5
+ CACHE = {}
6
+
7
+ def self.all path
8
+ CACHE[path] ||= begin
9
+ File.readlines(path)
10
+ rescue
11
+ []
12
+ end
13
+ end
14
+
15
+ def self.find path, line
16
+ return nil if line < 1
17
+ all(path)[line - 1]
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ module Opbeat
2
+ # @api private
3
+ module Logging
4
+ PREFIX = "** [Opbeat] ".freeze
5
+
6
+ def debug *args, &block
7
+ config.logger.debug(log_message(*args, &block)) if has_logger?
8
+ end
9
+
10
+ def info *args, &block
11
+ config.logger.info(log_message(*args, &block)) if has_logger?
12
+ end
13
+
14
+ def warn *args, &block
15
+ config.logger.warn(log_message(*args, &block)) if has_logger?
16
+ end
17
+
18
+ def error *args, &block
19
+ config.logger.error(log_message(*args, &block)) if has_logger?
20
+ end
21
+
22
+ def fatal *args, &block
23
+ config.logger.fatal(log_message(*args, &block)) if has_logger?
24
+ end
25
+
26
+ private
27
+
28
+ def has_logger?
29
+ respond_to?(:config) && config && config.logger
30
+ end
31
+
32
+ def log_message *args, &block
33
+ msg = block_given? && block.call || args.first
34
+ "#{PREFIX}#{msg}"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,59 @@
1
+ module Opbeat
2
+ class Middleware
3
+ def initialize app
4
+ @app = app
5
+ end
6
+
7
+ def call env
8
+ begin
9
+ transaction = Opbeat.transaction "Rack", "app.rack.request"
10
+ resp = @app.call env
11
+ resp[2] = BodyProxy.new(resp[2]) { transaction.submit(resp[0]) } if transaction
12
+ rescue Error
13
+ raise # Don't report Opbeat errors
14
+ rescue Exception => e
15
+ Opbeat.report e, rack_env: env
16
+ transaction.submit(500) if transaction
17
+ raise
18
+ ensure
19
+ transaction.release if transaction
20
+ end
21
+
22
+ if error = env['rack.exception'] || env['sinatra.error']
23
+ Opbeat.report error, rack_env: env
24
+ end
25
+
26
+ resp
27
+ end
28
+ end
29
+
30
+ class BodyProxy
31
+ def initialize body, &block
32
+ @body, @block, @closed = body, block, false
33
+ end
34
+
35
+ def respond_to? *args
36
+ super || @body.respond_to?(*args)
37
+ end
38
+
39
+ def close
40
+ return if closed?
41
+
42
+ @closed = true
43
+
44
+ begin
45
+ @body.close if @body.respond_to?(:close)
46
+ ensure
47
+ @block.call
48
+ end
49
+ end
50
+
51
+ def closed?
52
+ @closed
53
+ end
54
+
55
+ def method_missing *args, &block
56
+ @body.__send__(*args, &block)
57
+ end
58
+ end
59
+ end