Class: ErrorRadar::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/error_radar/configuration.rb

Overview

Holds every host-app-specific decision so the engine stays decoupled. Configure from an initializer (see the install generator's template).

Constant Summary collapse

DEFAULT_CATEGORIES =

Built-in categories (name => stored integer). Hosts can override the whole map (config.categories = {...}) or add their own (register_category).

{
  application:    0, # generic Ruby/Rails runtime error
  external_api:   1, # any 3rd-party API error
  background_job: 2, # uncategorised background-job failure
  syntax:         3, # SyntaxError / NameError / NoMethodError / ArgumentError / TypeError
  database:       4, # ActiveRecord / DB level
  network:        5  # timeouts, connection resets, DNS, ...
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/error_radar/configuration.rb', line 141

def initialize
  @enabled            = true
  @backtrace_lines    = 30
  @max_message_length = 4_000
  @ignored_exceptions = %w[
    ActionController::RoutingError
    ActiveRecord::RecordNotFound
    ActionController::ParameterMissing
    ActionController::UnknownFormat
    ActionController::BadRequest
    ActionController::InvalidAuthenticityToken
    ActionDispatch::Http::Parameters::ParseError
  ]
  @sensitive_params   = %w[password password_confirmation token access_token authorization secret]
  @install_middleware  = true
  @install_sidekiq     = true
  @install_rails_admin = true
  @install_active_job  = true
  @install_rake        = true

  @notify_on            = [:new_error]
  @slack_webhook_url    = nil
  @slack_channel        = nil
  @discord_webhook_url  = nil
  @email_recipients     = []
  @email_from           = nil
  @webhook_urls         = []
  @app_name             = nil
  @app_host             = nil
  @error_callbacks      = []

  @digest_enabled    = false
  @digest_recipients = []

  @spike_threshold      = 10
  @spike_window_minutes = 5

  @track_occurrences        = false
  @max_occurrences_per_error = 200

  @async_capture     = false
  @capture_job_queue = :default
  @retention_days    = nil
  @max_records       = nil

  @api_token    = nil
  @github_token = nil
  @github_repo  = nil
  @categorizers       = []
  @detail_extractors  = []
  @expected_servers   = []
  @authenticate       = nil
  @current_user       = nil
  @categories         = DEFAULT_CATEGORIES.dup
end

Instance Attribute Details

#api_tokenObject

REST API ──────────────────────────────────────────────────────────────── Bearer token for /api/* endpoints. nil = unauthenticated (not for prod).



108
109
110
# File 'lib/error_radar/configuration.rb', line 108

def api_token
  @api_token
end

#app_hostObject

Base URL used to build deep-links (e.g. "https://myapp.com").



63
64
65
# File 'lib/error_radar/configuration.rb', line 63

def app_host
  @app_host
end

#app_nameObject

App name shown in notification subject/title. Defaults to Rails app name.



61
62
63
# File 'lib/error_radar/configuration.rb', line 61

def app_name
  @app_name
end

#async_captureObject

Performance ───────────────────────────────────────────────────────────── When true, ErrorLog.record is enqueued via ActiveJob (non-blocking). Requires ActiveJob to be configured. Falls back to sync if ActiveJob is absent.



96
97
98
# File 'lib/error_radar/configuration.rb', line 96

def async_capture
  @async_capture
end

#authenticateObject

Dashboard auth: ->(controller) { ... } run as a before_action. Raise / redirect inside it to deny access. nil => no auth (NOT recommended in prod).



131
132
133
# File 'lib/error_radar/configuration.rb', line 131

def authenticate
  @authenticate
end

#backtrace_linesObject

How many backtrace lines to persist.



22
23
24
# File 'lib/error_radar/configuration.rb', line 22

def backtrace_lines
  @backtrace_lines
end

#capture_job_queueObject

Queue name for CaptureJob when async_capture is enabled.



98
99
100
# File 'lib/error_radar/configuration.rb', line 98

def capture_job_queue
  @capture_job_queue
end

#categoriesObject

The category name => integer map backing ErrorLog's category enum. Read-only accessor; mutate through categories= or register_category so the built-in defaults are always preserved.



139
140
141
# File 'lib/error_radar/configuration.rb', line 139

def categories
  @categories
end

#categorizersObject

Custom classification rules. Each is a callable ->(exception) { :category | nil }. The first rule that returns a non-nil category wins; built-in rules run after.



118
119
120
# File 'lib/error_radar/configuration.rb', line 118

def categorizers
  @categorizers
end

#current_userObject

->(controller) { "who@acted" } — stamped onto resolved errors.



134
135
136
# File 'lib/error_radar/configuration.rb', line 134

def current_user
  @current_user
end

#detail_extractorsObject

Extract extra structured columns from custom exception types. Each is a callable ->(exception) { { http_status:, request_url:, api_code:, api_subcode: } | nil }.



122
123
124
# File 'lib/error_radar/configuration.rb', line 122

def detail_extractors
  @detail_extractors
end

#digest_enabledObject

Digest email ──────────────────────────────────────────────────────────── Set to true to enable digest delivery (rake error_radar:digest).



74
75
76
# File 'lib/error_radar/configuration.rb', line 74

def digest_enabled
  @digest_enabled
end

#digest_recipientsObject

Separate recipient list for digests. Falls back to email_recipients if empty.



76
77
78
# File 'lib/error_radar/configuration.rb', line 76

def digest_recipients
  @digest_recipients
end

#discord_webhook_urlObject

Discord incoming-webhook URL



50
51
52
# File 'lib/error_radar/configuration.rb', line 50

def discord_webhook_url
  @discord_webhook_url
end

#email_fromObject

From address for notification emails.



55
56
57
# File 'lib/error_radar/configuration.rb', line 55

def email_from
  @email_from
end

#email_recipientsObject

ActionMailer recipients. Requires ActionMailer to be configured in host app.



53
54
55
# File 'lib/error_radar/configuration.rb', line 53

def email_recipients
  @email_recipients
end

#enabledObject

Master switch — set false (e.g. in test env) to make capture a no-op.



19
20
21
# File 'lib/error_radar/configuration.rb', line 19

def enabled
  @enabled
end

#error_callbacksObject (readonly)

Custom callbacks: ->(error_log) { ... }. Called after built-in channels.



66
67
68
# File 'lib/error_radar/configuration.rb', line 66

def error_callbacks
  @error_callbacks
end

#expected_serversObject

Optional Sidekiq process expectations for the dashboard's server panel. Each entry: { key:, name:, tag:, host:, queue_hint: }. Empty => the panel simply lists whatever live processes exist.



127
128
129
# File 'lib/error_radar/configuration.rb', line 127

def expected_servers
  @expected_servers
end

#github_repoObject

"owner/repo" string, e.g. "myorg/myapp".



114
115
116
# File 'lib/error_radar/configuration.rb', line 114

def github_repo
  @github_repo
end

#github_tokenObject

GitHub integration ────────────────────────────────────────────────────── Personal access token with repo scope.



112
113
114
# File 'lib/error_radar/configuration.rb', line 112

def github_token
  @github_token
end

#ignored_exceptionsObject

Exception class names the Rack middleware must NOT log (expected client outcomes: routing errors, 404s, bad requests, ...).



29
30
31
# File 'lib/error_radar/configuration.rb', line 29

def ignored_exceptions
  @ignored_exceptions
end

#install_active_jobObject

Integration toggles.



35
36
37
# File 'lib/error_radar/configuration.rb', line 35

def install_active_job
  @install_active_job
end

#install_middlewareObject

Integration toggles.



35
36
37
# File 'lib/error_radar/configuration.rb', line 35

def install_middleware
  @install_middleware
end

#install_rails_adminObject

Integration toggles.



35
36
37
# File 'lib/error_radar/configuration.rb', line 35

def install_rails_admin
  @install_rails_admin
end

#install_rakeObject

Integration toggles.



35
36
37
# File 'lib/error_radar/configuration.rb', line 35

def install_rake
  @install_rake
end

#install_sidekiqObject

Integration toggles.



35
36
37
# File 'lib/error_radar/configuration.rb', line 35

def install_sidekiq
  @install_sidekiq
end

#max_message_lengthObject

Truncate stored messages to this many chars.



25
26
27
# File 'lib/error_radar/configuration.rb', line 25

def max_message_length
  @max_message_length
end

#max_occurrences_per_errorObject

Maximum occurrences to keep per ErrorLog. Oldest are pruned on each new hit. nil = keep all (not recommended for high-volume apps).



91
92
93
# File 'lib/error_radar/configuration.rb', line 91

def max_occurrences_per_error
  @max_occurrences_per_error
end

#max_recordsObject

Keep at most this many total records; deletes oldest resolved/ignored first (nil = unlimited).



104
105
106
# File 'lib/error_radar/configuration.rb', line 104

def max_records
  @max_records
end

#notify_onObject

Notifications ───────────────────────────────────────────────────────── When to fire: :new_error (first time a fingerprint is seen), :critical (any critical-severity occurrence, throttled), :all (every occurrence, throttled to 1/hour/fingerprint)



42
43
44
# File 'lib/error_radar/configuration.rb', line 42

def notify_on
  @notify_on
end

#retention_daysObject

Retention ─────────────────────────────────────────────────────────────── Auto-delete resolved/ignored records older than this many days (nil = keep forever).



102
103
104
# File 'lib/error_radar/configuration.rb', line 102

def retention_days
  @retention_days
end

#sensitive_paramsObject

Request param keys to scrub before persisting them in context.



32
33
34
# File 'lib/error_radar/configuration.rb', line 32

def sensitive_params
  @sensitive_params
end

#slack_channelObject

Override target channel. Leave nil to use webhook's default channel.



47
48
49
# File 'lib/error_radar/configuration.rb', line 47

def slack_channel
  @slack_channel
end

#slack_webhook_urlObject

Slack incoming-webhook URL (https://hooks.slack.com/services/...)



45
46
47
# File 'lib/error_radar/configuration.rb', line 45

def slack_webhook_url
  @slack_webhook_url
end

#spike_thresholdObject

Spike detection ───────────────────────────────────────────────────────── Number of occurrences within spike_window_minutes that triggers a spike alert. Add :spike to notify_on to enable: config.notify_on = [:new_error, :spike]



81
82
83
# File 'lib/error_radar/configuration.rb', line 81

def spike_threshold
  @spike_threshold
end

#spike_window_minutesObject

Rolling time window in minutes for counting occurrences.



83
84
85
# File 'lib/error_radar/configuration.rb', line 83

def spike_window_minutes
  @spike_window_minutes
end

#track_occurrencesObject

Occurrences ───────────────────────────────────────────────────────────── When true, each individual error hit is stored in error_radar_occurrences. Requires running: bin/rails generate error_radar:upgrade_v060 && bin/rails db:migrate



88
89
90
# File 'lib/error_radar/configuration.rb', line 88

def track_occurrences
  @track_occurrences
end

#webhook_urlsObject

One or more plain HTTPS URLs that receive a POST with JSON body on each alert.



58
59
60
# File 'lib/error_radar/configuration.rb', line 58

def webhook_urls
  @webhook_urls
end

Instance Method Details

#categorize(&block) ⇒ Object

Convenience DSL inside configure:

c.categorize { |e| :external_api if e.is_a?(MyApi::Error) }


224
225
226
# File 'lib/error_radar/configuration.rb', line 224

def categorize(&block)
  @categorizers << block
end

#extract_details(&block) ⇒ Object

c.extract_details { |e| { http_status: e.status } if e.is_a?(MyApi::Error) }



229
230
231
# File 'lib/error_radar/configuration.rb', line 229

def extract_details(&block)
  @detail_extractors << block
end

#on_error(&block) ⇒ Object



68
69
70
# File 'lib/error_radar/configuration.rb', line 68

def on_error(&block)
  @error_callbacks << block
end

#register_category(name, value) ⇒ Object

Add a single custom category without disturbing the rest:

config.register_category(:instagram_api, 6)


209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/error_radar/configuration.rb', line 209

def register_category(name, value)
  name = name.to_sym
  value = Integer(value)
  if @categories[name] && @categories[name] != value
    raise ArgumentError, "category #{name.inspect} already mapped to #{@categories[name]}"
  end
  existing = @categories.key(value)
  if existing && existing != name
    raise ArgumentError, "category value #{value} already used by #{existing.inspect}"
  end
  @categories = @categories.merge(name => value)
end