File: railtie.rb

package info (click to toggle)
ruby-sentry-rails 5.18.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 232 kB
  • sloc: ruby: 1,035; makefile: 7; sh: 4
file content (139 lines) | stat: -rw-r--r-- 5,678 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
require "sentry/rails/capture_exceptions"
require "sentry/rails/rescued_exception_interceptor"
require "sentry/rails/backtrace_cleaner"

module Sentry
  class Railtie < ::Rails::Railtie
    # middlewares can't be injected after initialize
    initializer "sentry.use_rack_middleware" do |app|
      # placed after all the file-sending middlewares so we can avoid unnecessary transactions
      app.config.middleware.insert_after ActionDispatch::ShowExceptions, Sentry::Rails::CaptureExceptions
      # need to place as close to DebugExceptions as possible to intercept most of the exceptions, including those raised by middlewares
      app.config.middleware.insert_after ActionDispatch::DebugExceptions, Sentry::Rails::RescuedExceptionInterceptor
    end

    # because the extension works by registering the around_perform callback, it should always be run
    # before the application is eager-loaded (before user's jobs register their own callbacks)
    # See https://github.com/getsentry/sentry-ruby/issues/1249#issuecomment-853871871 for the detail explanation
    initializer "sentry.extend_active_job", before: :eager_load! do |app|
      ActiveSupport.on_load(:active_job) do
        require "sentry/rails/active_job"
        prepend Sentry::Rails::ActiveJobExtensions
      end
    end

    initializer "sentry.extend_action_cable", before: :eager_load! do |app|
      ActiveSupport.on_load(:action_cable_connection) do
        require "sentry/rails/action_cable"
        prepend Sentry::Rails::ActionCableExtensions::Connection
      end

      ActiveSupport.on_load(:action_cable_channel) do
        require "sentry/rails/action_cable"
        include Sentry::Rails::ActionCableExtensions::Channel::Subscriptions
        prepend Sentry::Rails::ActionCableExtensions::Channel::Actions
      end
    end

    config.after_initialize do |app|
      next unless Sentry.initialized?

      configure_project_root
      configure_trusted_proxies
      configure_cron_timezone
      extend_controller_methods if defined?(ActionController)
      patch_background_worker if defined?(ActiveRecord)
      override_streaming_reporter if defined?(ActionView)
      setup_backtrace_cleanup_callback
      inject_breadcrumbs_logger
      activate_tracing

      register_error_subscriber(app) if ::Rails.version.to_f >= 7.0 && Sentry.configuration.rails.register_error_subscriber
    end

    runner do
      next unless Sentry.initialized?
      Sentry.configuration.background_worker_threads = 0

      at_exit do
        # TODO: Add a condition for Rails 7.1 to avoid confliction with https://github.com/rails/rails/pull/44999
        if $ERROR_INFO && !($ERROR_INFO.is_a?(SystemExit) && $ERROR_INFO.success?)
          Sentry::Rails.capture_exception($ERROR_INFO, tags: { source: "runner" })
        end
      end
    end

    def configure_project_root
      Sentry.configuration.project_root = ::Rails.root.to_s
    end

    def configure_trusted_proxies
      Sentry.configuration.trusted_proxies += Array(::Rails.application.config.action_dispatch.trusted_proxies)
    end

    def configure_cron_timezone
      tz_info = ::ActiveSupport::TimeZone.find_tzinfo(::Rails.application.config.time_zone)
      Sentry.configuration.cron.default_timezone = tz_info.name
    end

    def extend_controller_methods
      require "sentry/rails/controller_methods"
      require "sentry/rails/controller_transaction"
      require "sentry/rails/overrides/streaming_reporter"

      ActiveSupport.on_load :action_controller do
        include Sentry::Rails::ControllerMethods
        include Sentry::Rails::ControllerTransaction
        ActionController::Live.send(:prepend, Sentry::Rails::Overrides::StreamingReporter)
      end
    end

    def patch_background_worker
      require "sentry/rails/background_worker"
    end

    def inject_breadcrumbs_logger
      if Sentry.configuration.breadcrumbs_logger.include?(:active_support_logger)
        require 'sentry/rails/breadcrumb/active_support_logger'
        Sentry::Rails::Breadcrumb::ActiveSupportLogger.inject(Sentry.configuration.rails.active_support_logger_subscription_items)
      end

      if Sentry.configuration.breadcrumbs_logger.include?(:monotonic_active_support_logger)
        return warn "Usage of `monotonic_active_support_logger` require a version of Rails >= 6.1, please upgrade your Rails version or use another logger" if ::Rails.version.to_f < 6.1

        require 'sentry/rails/breadcrumb/monotonic_active_support_logger'
        Sentry::Rails::Breadcrumb::MonotonicActiveSupportLogger.inject
      end
    end

    def setup_backtrace_cleanup_callback
      backtrace_cleaner = Sentry::Rails::BacktraceCleaner.new

      Sentry.configuration.backtrace_cleanup_callback ||= lambda do |backtrace|
        backtrace_cleaner.clean(backtrace)
      end
    end

    def override_streaming_reporter
      require "sentry/rails/overrides/streaming_reporter"

      ActiveSupport.on_load :action_view do
        ActionView::StreamingTemplateRenderer::Body.send(:prepend, Sentry::Rails::Overrides::StreamingReporter)
      end
    end

    def activate_tracing
      if Sentry.configuration.tracing_enabled? && Sentry.configuration.instrumenter == :sentry
        subscribers = Sentry.configuration.rails.tracing_subscribers
        Sentry::Rails::Tracing.register_subscribers(subscribers)
        Sentry::Rails::Tracing.subscribe_tracing_events
        Sentry::Rails::Tracing.patch_active_support_notifications
      end
    end

    def register_error_subscriber(app)
      require "sentry/rails/error_subscriber"
      app.executor.error_reporter.subscribe(Sentry::Rails::ErrorSubscriber.new)
    end
  end
end