Class: Dispatch::Rails::Configuration

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

Constant Summary collapse

MODES =

Install mode. :widget is the default (a UI app embeds the bug-report button); :errors_only is for API-only / headless apps that have no UI to render into — server-side exception capture and manual reporting still work, but the widget and browser-error tags become no-ops.

%i[widget errors_only].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



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
# File 'lib/dispatch/rails/configuration.rb', line 30

def initialize
  @api_key = nil
  @endpoint = "https://dispatchit.app/api/v1/tickets"
  @user = ->(_ctx) { nil }
  @metadata = ->(_ctx) { {} }
  @capture_console = false
  @capture_clicks = true # track the last few clicks as a "user path" for context
  @button_position = "bottom-right"

  # Mode + API-only context
  @mode = :widget
  @context = ->(_ctx) { {} } # extra tags resolved from the controller (API key user, headers, …)
  @send_default_params = false # opt-in: include Rails' filtered_parameters in the event

  # Exception tracking defaults
  @capture_exceptions = true
  @capture_browser_errors = true
  @error_endpoint = nil # derived from endpoint when nil
  @environment = nil    # derived from Rails.env when nil
  @release = nil        # e.g. ENV["GIT_SHA"]
  @enabled_environments = %w[production staging]
  @error_sample_rate = 1.0
  @before_send = nil    # ->(event) { event or nil to drop }

  # Browser security/reporting capture. Both opt-in: a permissive or
  # report-only CSP can emit these in bulk, and capture_browser_reports also
  # makes the gem own a URL path. Pick ONE CSP mechanism — the JS
  # securitypolicyviolation listener (capture_csp_violations) OR the native
  # report endpoint (capture_browser_reports) — or a violation reported
  # through both is counted twice.
  @capture_csp_violations = false   # JS: listen for SecurityPolicyViolationEvent
  @capture_browser_reports = false  # Server: accept native browser report POSTs
  @reporting_endpoint_path = "/dispatch/reports"

  # Process lifecycle. Report the exception killing the process (a crash
  # during boot, a dying runner) and drain the send queue before exit so
  # deploys/restarts don't drop captured events.
  @capture_at_exit = true
  @shutdown_timeout = 3 # seconds to wait for the queue to drain at exit; 0 skips the flush

  # Structured error responses (off by default — opt-in so we never alter a
  # host app's error contract without being asked).
  @structured_error_responses = false
  @annotate_error_body = false # headers-only unless explicitly enabled
  @report_base_url = nil       # derived from endpoint host when nil

  # Traffic heartbeats. On by default in enabled environments: aggregate
  # counts only (one small POST per flush window, regardless of request
  # volume), so the cost is negligible and the confound guard works out of
  # the box. Sampling is independent of error_sample_rate.
  @capture_traffic = true
  @traffic_sample_rate = 1.0
  @heartbeat_flush_seconds = 60
  @heartbeat_endpoint = nil # derived from endpoint when nil
end

Instance Attribute Details

#annotate_error_bodyObject

Structured error responses (API-only)



24
25
26
# File 'lib/dispatch/rails/configuration.rb', line 24

def annotate_error_body
  @annotate_error_body
end

#api_keyObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def api_key
  @api_key
end

#before_sendObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def before_send
  @before_send
end

#button_positionObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def button_position
  @button_position
end

#capture_at_exitObject

Process lifecycle (crash-at-exit capture, rake failures, shutdown flush)



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

def capture_at_exit
  @capture_at_exit
end

#capture_browser_errorsObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def capture_browser_errors
  @capture_browser_errors
end

#capture_browser_reportsObject

Browser security/reporting capture (both opt-in; high-volume + noise-prone)



20
21
22
# File 'lib/dispatch/rails/configuration.rb', line 20

def capture_browser_reports
  @capture_browser_reports
end

#capture_clicksObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def capture_clicks
  @capture_clicks
end

#capture_consoleObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def capture_console
  @capture_console
end

#capture_csp_violationsObject

Browser security/reporting capture (both opt-in; high-volume + noise-prone)



20
21
22
# File 'lib/dispatch/rails/configuration.rb', line 20

def capture_csp_violations
  @capture_csp_violations
end

#capture_exceptionsObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def capture_exceptions
  @capture_exceptions
end

#capture_trafficObject

Traffic heartbeats — per-transaction success counts that let the Dispatch server tell “the error stopped because we fixed it” from “…because the path went quiet” (the confound guard behind fix verification).



28
29
30
# File 'lib/dispatch/rails/configuration.rb', line 28

def capture_traffic
  @capture_traffic
end

#contextObject

Mode + API-only context



15
16
17
# File 'lib/dispatch/rails/configuration.rb', line 15

def context
  @context
end

#enabled_environmentsObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def enabled_environments
  @enabled_environments
end

#endpointObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def endpoint
  @endpoint
end

#environmentObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def environment
  @environment
end

#error_endpointObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def error_endpoint
  @error_endpoint
end

#error_sample_rateObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def error_sample_rate
  @error_sample_rate
end

#heartbeat_endpointObject

Traffic heartbeats — per-transaction success counts that let the Dispatch server tell “the error stopped because we fixed it” from “…because the path went quiet” (the confound guard behind fix verification).



28
29
30
# File 'lib/dispatch/rails/configuration.rb', line 28

def heartbeat_endpoint
  @heartbeat_endpoint
end

#heartbeat_flush_secondsObject

Traffic heartbeats — per-transaction success counts that let the Dispatch server tell “the error stopped because we fixed it” from “…because the path went quiet” (the confound guard behind fix verification).



28
29
30
# File 'lib/dispatch/rails/configuration.rb', line 28

def heartbeat_flush_seconds
  @heartbeat_flush_seconds
end

#metadataObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def 
  @metadata
end

#modeObject

Mode + API-only context



15
16
17
# File 'lib/dispatch/rails/configuration.rb', line 15

def mode
  @mode
end

#releaseObject

Exception tracking



17
18
19
# File 'lib/dispatch/rails/configuration.rb', line 17

def release
  @release
end

#report_base_urlObject

Structured error responses (API-only)



24
25
26
# File 'lib/dispatch/rails/configuration.rb', line 24

def report_base_url
  @report_base_url
end

#reporting_endpoint_pathObject

Browser security/reporting capture (both opt-in; high-volume + noise-prone)



20
21
22
# File 'lib/dispatch/rails/configuration.rb', line 20

def reporting_endpoint_path
  @reporting_endpoint_path
end

#send_default_paramsObject

Mode + API-only context



15
16
17
# File 'lib/dispatch/rails/configuration.rb', line 15

def send_default_params
  @send_default_params
end

#shutdown_timeoutObject

Process lifecycle (crash-at-exit capture, rake failures, shutdown flush)



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

def shutdown_timeout
  @shutdown_timeout
end

#structured_error_responsesObject

Structured error responses (API-only)



24
25
26
# File 'lib/dispatch/rails/configuration.rb', line 24

def structured_error_responses
  @structured_error_responses
end

#traffic_sample_rateObject

Traffic heartbeats — per-transaction success counts that let the Dispatch server tell “the error stopped because we fixed it” from “…because the path went quiet” (the confound guard behind fix verification).



28
29
30
# File 'lib/dispatch/rails/configuration.rb', line 28

def traffic_sample_rate
  @traffic_sample_rate
end

#userObject

Bug-report widget



13
14
15
# File 'lib/dispatch/rails/configuration.rb', line 13

def user
  @user
end

Instance Method Details

#browser_reports_enabled?Boolean

Fast-path guard for ReportingEndpointMiddleware: own the reporting path only when the host opted in and we have credentials to deliver. Otherwise the middleware passes the request straight through (no surprise 204s).

Returns:

  • (Boolean)


138
139
140
# File 'lib/dispatch/rails/configuration.rb', line 138

def browser_reports_enabled?
  configured? && @capture_browser_reports
end

#configured?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/dispatch/rails/configuration.rb', line 86

def configured?
  api_key.present? && endpoint.present?
end

#effective_environmentObject



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

def effective_environment
  @environment.presence || (defined?(::Rails) && ::Rails.respond_to?(:env) ? ::Rails.env.to_s : "production")
end

#effective_error_endpointObject

Where exception events are posted. Defaults to the same host as the widget endpoint with the path swapped to the Sentry-compatible /store endpoint.



98
99
100
101
102
# File 'lib/dispatch/rails/configuration.rb', line 98

def effective_error_endpoint
  return @error_endpoint if @error_endpoint.present?

  endpoint.to_s.sub(%r{/[^/]+\z}, "/store")
end

#effective_heartbeat_endpointObject

Where per-transaction traffic rollups are posted. Defaults to the same host as the widget endpoint with the path swapped to /heartbeats.



121
122
123
124
125
# File 'lib/dispatch/rails/configuration.rb', line 121

def effective_heartbeat_endpoint
  return @heartbeat_endpoint if @heartbeat_endpoint.present?

  endpoint.to_s.sub(%r{/[^/]+\z}, "/heartbeats")
end

#effective_report_base_urlObject

The base URL (scheme + host) where the Dispatch tenant lives, used to build the human-facing report link surfaced in structured error responses. Falls back to the origin of ‘endpoint` (dispatchit.app).



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/dispatch/rails/configuration.rb', line 107

def effective_report_base_url
  return @report_base_url.to_s.chomp("/") if @report_base_url.present?

  uri = URI.parse(endpoint.to_s)
  return nil if uri.host.nil?

  port = uri.port && ![80, 443].include?(uri.port) ? ":#{uri.port}" : ""
  "#{uri.scheme}://#{uri.host}#{port}"
rescue StandardError
  nil
end

#environment_enabled?Boolean

Returns:

  • (Boolean)


148
149
150
151
# File 'lib/dispatch/rails/configuration.rb', line 148

def environment_enabled?
  list = Array(@enabled_environments).map(&:to_s)
  list.empty? || list.include?(effective_environment)
end

#error_tracking_enabled?Boolean

Returns:

  • (Boolean)


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

def error_tracking_enabled?
  configured? && @capture_exceptions
end

#errors_only?Boolean

Returns:

  • (Boolean)


90
91
92
93
94
# File 'lib/dispatch/rails/configuration.rb', line 90

def errors_only?
  mode.to_sym == :errors_only
rescue StandardError
  false
end

#traffic_tracking_enabled?Boolean

Heartbeats piggyback on the same gating as error capture, plus their own toggle. Off in non-enabled environments (so dev/test never phone home).

Returns:

  • (Boolean)


144
145
146
# File 'lib/dispatch/rails/configuration.rb', line 144

def traffic_tracking_enabled?
  @capture_traffic && error_tracking_enabled? && environment_enabled?
end