Class: Rollbar::Notifier

Inherits:
Object
  • Object
show all
Defined in:
lib/rollbar/notifier.rb

Overview

The notifier class. It has the core functionality for sending reports to the API.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent_notifier = nil, payload_options = nil, scope = nil) ⇒ Notifier

Returns a new instance of Notifier.



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rollbar/notifier.rb', line 23

def initialize(parent_notifier = nil, payload_options = nil, scope = nil)
  if parent_notifier
    self.configuration = parent_notifier.configuration.clone
    self.scope_object = parent_notifier.scope_object.clone

    Rollbar::Util.deep_merge(scope_object, scope) if scope
  else
    self.configuration = ::Rollbar::Configuration.new
    self.scope_object = ::Rollbar::LazyStore.new(scope)
  end

  Rollbar::Util.deep_merge(configuration.payload_options, payload_options) if payload_options
end

Instance Attribute Details

#configurationObject

Returns the value of attribute configuration.



17
18
19
# File 'lib/rollbar/notifier.rb', line 17

def configuration
  @configuration
end

#last_reportObject

Returns the value of attribute last_report.



18
19
20
# File 'lib/rollbar/notifier.rb', line 18

def last_report
  @last_report
end

#scope_objectObject

Returns the value of attribute scope_object.



19
20
21
# File 'lib/rollbar/notifier.rb', line 19

def scope_object
  @scope_object
end

Instance Method Details

#configure {|configuration| ... } ⇒ Object

Configures the notifier instance

Yields:



48
49
50
51
52
# File 'lib/rollbar/notifier.rb', line 48

def configure
  configuration.enabled = true if configuration.enabled.nil?

  yield(configuration)
end

#critical(*args) ⇒ Object

See log() above



178
179
180
# File 'lib/rollbar/notifier.rb', line 178

def critical(*args)
  log('critical', *args)
end

#debug(*args) ⇒ Object

See log() above



153
154
155
# File 'lib/rollbar/notifier.rb', line 153

def debug(*args)
  log('debug', *args)
end

#error(*args) ⇒ Object

See log() above



173
174
175
# File 'lib/rollbar/notifier.rb', line 173

def error(*args)
  log('error', *args)
end

#info(*args) ⇒ Object

See log() above



158
159
160
# File 'lib/rollbar/notifier.rb', line 158

def info(*args)
  log('info', *args)
end

#levelObject

Logging



287
288
289
290
291
# File 'lib/rollbar/notifier.rb', line 287

%w(debug info warn error).each do |level|
  define_method(:"log_#{level}") do |message|
    logger.send(level, message)
  end
end

#log(level, *args) ⇒ Object

Sends a report to Rollbar.

Accepts any number of arguments. The last String argument will become the message or description of the report. The last Exception argument will become the associated exception for the report. The last hash argument will be used as the extra data for the report.

Examples:

begin
  foo = bar
rescue => e
  Rollbar.log(e)
end
Rollbar.log('This is a simple log message')
Rollbar.log(e, 'This is a description of the exception')


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/rollbar/notifier.rb', line 123

def log(level, *args)
  return 'disabled' unless configuration.enabled

  message, exception, extra = extract_arguments(args)
  use_exception_level_filters = extra && extra.delete(:use_exception_level_filters) == true

  return 'ignored' if ignored?(exception, use_exception_level_filters)

  begin
    call_before_process(:level => level,
                        :exception => exception,
                        :message => message,
                        :extra => extra)
  rescue Rollbar::Ignore
    return 'ignored'
  end

  level = lookup_exception_level(level, exception,
                                 use_exception_level_filters)

  begin
    report(level, message, exception, extra)
  rescue StandardError, SystemStackError => e
    report_internal_error(e)

    'error'
  end
end

#preconfigure {|configuration| ... } ⇒ Object

Similar to configure below, but used only internally within the gem to configure it without initializing any of the third party hooks

Yields:



43
44
45
# File 'lib/rollbar/notifier.rb', line 43

def preconfigure
  yield(configuration)
end

#process_from_async_handler(payload) ⇒ Object

We will reraise exceptions in this method so async queues can retry the job or, in general, handle an error report some way.

At same time that exception is silenced so we don’t generate infinite reports. This example is what we want to avoid:

  1. New exception in a the project is raised

  2. That report enqueued to Sidekiq queue.

  3. The Sidekiq job tries to send the report to our API

  4. The report fails, for example cause a network failure, and a exception is raised

  5. We report an internal error for that exception

  6. We reraise the exception so Sidekiq job fails and Sidekiq can retry the job reporting the original exception

  7. Because the job failed and Sidekiq can be managed by rollbar we’ll report a new exception.

  8. Go to point 2.

We’ll then push to Sidekiq queue indefinitely until the network failure is fixed.

Using Rollbar.silenced we avoid the above behavior but Sidekiq will have a chance to retry the original job.



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/rollbar/notifier.rb', line 222

def process_from_async_handler(payload)
  payload = Rollbar::JSON.load(payload) if payload.is_a?(String)

  item = Item.build_with(payload,
                         :notifier => self,
                         :configuration => configuration,
                         :logger => logger)

  Rollbar.silenced do
    begin
      process_item(item)
    rescue => e
      report_internal_error(e)

      raise
    end
  end
end

#process_item(item) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/rollbar/notifier.rb', line 182

def process_item(item)
  if configuration.write_to_file
    if configuration.use_async
      @file_semaphore.synchronize do
        write_item(item)
      end
    else
      write_item(item)
    end
  else
    send_item(item)
  end
rescue => e
  log_error("[Rollbar] Error processing the item: #{e.class}, #{e.message}. Item: #{item.payload.inspect}")
  raise e
end

#reconfigure {|configuration| ... } ⇒ Object

Yields:



54
55
56
57
58
59
# File 'lib/rollbar/notifier.rb', line 54

def reconfigure
  self.configuration = Configuration.new
  configuration.enabled = true

  yield(configuration)
end

#reset!Object



37
38
39
# File 'lib/rollbar/notifier.rb', line 37

def reset!
  self.scope_object = ::Rollbar::LazyStore.new({})
end

#safelyObject

Returns a new notifier with same configuration options but it sets Configuration#safely to true. We are using this flag to avoid having inifite loops when evaluating some custom user methods.



83
84
85
86
87
88
# File 'lib/rollbar/notifier.rb', line 83

def safely
  new_notifier = scope
  new_notifier.configuration.safely = true

  new_notifier
end

#scope(scope_overrides = {}, config_overrides = {}) ⇒ Object



65
66
67
68
69
70
# File 'lib/rollbar/notifier.rb', line 65

def scope(scope_overrides = {}, config_overrides = {})
  new_notifier = self.class.new(self, nil, scope_overrides)
  new_notifier.configuration = configuration.merge(config_overrides)

  new_notifier
end

#scope!(options = {}, config_overrides = {}) ⇒ Object



72
73
74
75
76
77
# File 'lib/rollbar/notifier.rb', line 72

def scope!(options = {}, config_overrides = {})
  Rollbar::Util.deep_merge(scope_object, options)
  configuration.merge!(config_overrides)

  self
end

#send_failsafe(message, exception, uuid = nil, host = nil) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/rollbar/notifier.rb', line 241

def send_failsafe(message, exception, uuid = nil, host = nil)
  exception_reason = failsafe_reason(message, exception)

  log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"

  body = failsafe_body(exception_reason)

  failsafe_data = {
    :level => 'error',
    :environment => configuration.environment.to_s,
    :body => {
      :message => {
        :body => body
      }
    },
    :notifier => {
      :name => 'rollbar-gem',
      :version => VERSION
    },
    :custom => {
      :orig_uuid => uuid,
      :orig_host => host
    },
    :internal => true,
    :failsafe => true
  }

  failsafe_payload = {
    'access_token' => configuration.access_token,
    'data' => failsafe_data
  }

  begin
    item = Item.build_with(failsafe_payload,
                           :notifier => self,
                           :configuration => configuration,
                           :logger => logger)
    schedule_item(item)
  rescue => e
    log_error "[Rollbar] Error sending failsafe : #{e}"
  end

  failsafe_payload
end

#silenced { ... } ⇒ Object

Turns off reporting for the given block.

Examples:

Rollbar.silenced { raise }

Yields:

  • Block which exceptions won’t be reported.



96
97
98
99
100
101
# File 'lib/rollbar/notifier.rb', line 96

def silenced
  yield
rescue => e
  e.instance_variable_set(:@_rollbar_do_not_report, true)
  raise
end

#unconfigureObject



61
62
63
# File 'lib/rollbar/notifier.rb', line 61

def unconfigure
  self.configuration = nil
end

#warn(*args) ⇒ Object

See log() above



163
164
165
# File 'lib/rollbar/notifier.rb', line 163

def warn(*args)
  log('warning', *args)
end

#warning(*args) ⇒ Object

See log() above



168
169
170
# File 'lib/rollbar/notifier.rb', line 168

def warning(*args)
  log('warning', *args)
end