Class: Upfluence::ErrorLogger::Sentry

Inherits:
Object
  • Object
show all
Defined in:
lib/upfluence/error_logger/sentry.rb

Defined Under Namespace

Classes: RackMiddleware

Constant Summary collapse

EXCLUDED_ERRORS =
(
  ::Sentry::Configuration::IGNORE_DEFAULT + [
    'ActiveRecord::RecordNotFound',
    'ActiveRecord::ConcurrentMigrationError'
  ]
)
DEFAULT_LEVEL_PROCS =
[
  exception_name_lambda(:warning, 'Net::ReadTimeout'),
  exception_name_lambda(:warning, 'EOFError'),
  exception_name_lambda(:warning, 'ActiveRecord::QueryCanceled'),
  exception_name_lambda(:warning, 'Timeout::Error'),
  exception_name_lambda(:warning, 'Errno::ECONNRESET'),
  exception_name_lambda(:warning, 'OAuth2::ConnectionError'),
  exception_message_lambda(:warning, 'Connection reset by peer'),
  exception_message_lambda(:warning, 'Connection refused'),
  exception_message_lambda(:warning, 'connection refused'),
  exception_message_lambda(:warning, 'Failed to open TCP connection'),
  exception_message_lambda(:warning, 'Net::ReadTimeout')
].freeze
MAX_TAG_SIZE =
8 * 1024

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSentry

Returns a new instance of Sentry.



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
# File 'lib/upfluence/error_logger/sentry.rb', line 46

def initialize
  @tag_extractors = []
  @level_procs = [*DEFAULT_LEVEL_PROCS]

  ::Sentry.init do |config|
    config.send_default_pii = true
    config.dsn = ENV.fetch('SENTRY_DSN', nil)
    config.environment = Upfluence.env
    config.excluded_exceptions = EXCLUDED_ERRORS
    config.sdk_logger = Upfluence.logger
    config.release = "#{ENV.fetch('PROJECT_NAME', nil)}-#{ENV.fetch('SEMVER_VERSION', nil)}"
    config.enable_tracing = false
    config.auto_session_tracking = false
  end

  ::Sentry.set_tags(
    { unit_name: unit_name, unit_type: unit_type }.select { |_, v| v }
  )

  ::Sentry.with_scope do |scope|
    scope.add_event_processor do |event, hint|
      tags = @tag_extractors.map(&:extract).compact.reduce({}, &:merge)

      exc = hint[:exception]

      tags.merge!(exc.tags) if exc.respond_to? :tags

      tx_name = transaction_name(tags)

      event.transaction = tx_name if tx_name
      event.extra.merge!(prepare_extra(tags))

      event.level = compute_exception_level(exc)

      event
    end
  end
end

Class Method Details

.exception_message_lambda(level, message) ⇒ Object



22
23
24
25
26
27
28
# File 'lib/upfluence/error_logger/sentry.rb', line 22

def exception_message_lambda(level, message)
  downcased_message = message.downcase

  lambda do |exception|
    level if exception.message.downcase.include?(downcased_message)
  end
end

.exception_name_lambda(level, name) ⇒ Object



16
17
18
19
20
# File 'lib/upfluence/error_logger/sentry.rb', line 16

def exception_name_lambda(level, name)
  lambda do |exception|
    level if exception.class.name.eql? name
  end
end

Instance Method Details

#append_level_procs(proc) ⇒ Object

proc must accept an exception and return either a sentry level (:error, :warning, etc.) or nil if the exception is not matched



91
92
93
# File 'lib/upfluence/error_logger/sentry.rb', line 91

def append_level_procs(proc)
  @level_procs << proc
end

#append_tag_extractors(klass) ⇒ Object



85
86
87
# File 'lib/upfluence/error_logger/sentry.rb', line 85

def append_tag_extractors(klass)
  @tag_extractors << klass
end

#ignore_exception(*klss) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/upfluence/error_logger/sentry.rb', line 124

def ignore_exception(*klss)
  klss.each do |kls|
    case kls.class
    when Class
      ::Sentry.configuration.excluded_exceptions << kls.name
    when String
      ::Sentry.configuration.excluded_exceptions << kls
    else
      Upfluence.logger.warn "Unexcepted argument for ignore_exception #{kls}"
    end
  end
end

#middlewareObject



120
121
122
# File 'lib/upfluence/error_logger/sentry.rb', line 120

def middleware
  RackMiddleware
end

#notify(error, *args) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/upfluence/error_logger/sentry.rb', line 95

def notify(error, *args)
  ::Sentry.with_scope do |scope|
    context = args.reduce({}) do |acc, arg|
      v = if arg.is_a?(Hash)
            arg
          else
            key = acc.empty? ? 'method' : "arg_#{acc.length}"
            { key => arg.inspect }
          end

      acc.merge(v)
    end

    scope.set_extras(prepare_extra(context))

    ::Sentry.capture_exception(error)
  end
rescue ::Sentry::Error => e
  Upfluence.logger.warning e.message
end

#user=(user) ⇒ Object



116
117
118
# File 'lib/upfluence/error_logger/sentry.rb', line 116

def user=(user)
  ::Sentry.set_user(id: user.id, email: user.email)
end