Module: Dispatch::Rails
- Defined in:
- lib/dispatch-rails.rb,
lib/dispatch/rails/engine.rb,
lib/dispatch/rails/version.rb,
lib/dispatch/rails/reporter.rb,
lib/dispatch/rails/transport.rb,
lib/dispatch/rails/middleware.rb,
lib/dispatch/rails/rake_handler.rb,
lib/dispatch/rails/configuration.rb,
lib/dispatch/rails/event_builder.rb,
lib/dispatch/rails/asset_middleware.rb,
lib/dispatch/rails/error_subscriber.rb,
lib/dispatch/rails/response_annotator.rb,
lib/dispatch/rails/heartbeat_aggregator.rb,
lib/dispatch/rails/heartbeat_middleware.rb,
lib/dispatch/rails/solid_queue_subscriber.rb,
lib/dispatch/rails/reporting_endpoint_middleware.rb
Defined Under Namespace
Modules: RakeHandler, Reporter, SolidQueueSubscriber Classes: AssetMiddleware, BrowserReport, Configuration, CspViolation, Engine, ErrorSubscriber, EventBuilder, HeartbeatAggregator, HeartbeatMiddleware, Middleware, ReportingEndpointMiddleware, ResponseAnnotator, SolidQueueEnqueueError, SolidQueueError, SolidQueueJobsLost, Transport
Constant Summary collapse
- VERSION =
"0.10.2".freeze
Class Method Summary collapse
-
.capture_exception(exception, env: nil, context: {}, level: "error") ⇒ Object
Manually report a handled exception, e.g.
- .configuration ⇒ Object
- .configure {|configuration| ... } ⇒ Object
-
.handle_at_exit(exception = nil) ⇒ Object
The at_exit body, extracted so it can be exercised in tests.
-
.ignored_exit_exception?(exception) ⇒ Boolean
Normal exits and SIGTERM-driven graceful shutdowns (deploys, scale-downs) are not crashes.
-
.install_at_exit_callback ⇒ Object
Process-exit safety net: report the exception that is killing the process (a crash during boot, a dying runner/script), then ship the in-progress heartbeat window and drain the transport queue so already-captured events survive the shutdown.
-
.report(description:, severity: nil, source: "api", metadata: {}, reporter: nil, correlation_id: nil) ⇒ Object
File a curated bug report (a ticket) programmatically — the API-only analogue of a human clicking the widget.
- .reset! ⇒ Object
Class Method Details
.capture_exception(exception, env: nil, context: {}, level: "error") ⇒ Object
Manually report a handled exception, e.g. inside a rescue:
rescue => e
Dispatch::Rails.capture_exception(e, context: { tags: { area: "import" } })
end
36 37 38 |
# File 'lib/dispatch-rails.rb', line 36 def capture_exception(exception, env: nil, context: {}, level: "error") Reporter.capture(exception, handled: true, env: env, context: context, level: level) end |
.configuration ⇒ Object
20 21 22 |
# File 'lib/dispatch-rails.rb', line 20 def configuration @configuration ||= Configuration.new end |
.configure {|configuration| ... } ⇒ Object
24 25 26 |
# File 'lib/dispatch-rails.rb', line 24 def configure yield(configuration) end |
.handle_at_exit(exception = nil) ⇒ Object
The at_exit body, extracted so it can be exercised in tests.
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/dispatch-rails.rb', line 79 def handle_at_exit(exception = nil) if exception && !ignored_exit_exception?(exception) && configuration.capture_at_exit Reporter.capture(exception, handled: false, context: { tags: { source: "at_exit" } }) end timeout = configuration.shutdown_timeout.to_f return unless timeout.positive? HeartbeatAggregator.instance.deliver_all Transport.instance.flush(timeout: timeout) end |
.ignored_exit_exception?(exception) ⇒ Boolean
Normal exits and SIGTERM-driven graceful shutdowns (deploys, scale-downs) are not crashes.
93 94 95 96 97 98 99 |
# File 'lib/dispatch-rails.rb', line 93 def ignored_exit_exception?(exception) return true if exception.is_a?(SystemExit) return false unless exception.is_a?(SignalException) name = exception.respond_to?(:signm) ? exception.signm.to_s : exception.to_s name.end_with?("TERM") end |
.install_at_exit_callback ⇒ Object
Process-exit safety net: report the exception that is killing the process (a crash during boot, a dying runner/script), then ship the in-progress heartbeat window and drain the transport queue so already-captured events survive the shutdown. Exceptions captured upstream (middleware, rake handler) carry the Reporter dedup marker and aren’t re-sent.
71 72 73 74 75 76 |
# File 'lib/dispatch-rails.rb', line 71 def install_at_exit_callback return if @at_exit_installed @at_exit_installed = true at_exit { handle_at_exit($!) } end |
.report(description:, severity: nil, source: "api", metadata: {}, reporter: nil, correlation_id: nil) ⇒ Object
File a curated bug report (a ticket) programmatically — the API-only analogue of a human clicking the widget. Ideal for an AI agent or a rescue block that wants to turn a failure into a tracked, human-readable report. Pass a correlation_id (e.g. request.request_id) to link the report to an already-captured error. Synchronous — returns the created ticket’s { “id”, “status”, “url” } Hash, or nil on failure. Never raises.
Dispatch::Rails.report(
description: "Nightly import aborted: upstream returned 502",
severity: "high",
correlation_id: request.request_id,
metadata: { job: "ImportJob" }
)
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/dispatch-rails.rb', line 53 def report(description:, severity: nil, source: "api", metadata: {}, reporter: nil, correlation_id: nil) return nil unless configuration.configured? = ( || {}).dup [:correlation_id] = correlation_id if correlation_id ticket = { description: description, source: source, severity: severity, metadata: , reporter: reporter }.compact Transport.instance.post_ticket(ticket: ticket) end |
.reset! ⇒ Object
28 29 30 |
# File 'lib/dispatch-rails.rb', line 28 def reset! @configuration = Configuration.new end |