Module: Axn::Internal::ExceptionContext
- Defined in:
- lib/axn/internal/exception_context.rb
Overview
Builds context data for exception reporting to error tracking services (e.g., Honeybadger, Sentry).
Class Method Summary collapse
-
.build(action:, retry_context: nil, tags: {}, dimensions: {}) ⇒ Hash
Build enhanced context for global on_exception handler.
Class Method Details
.build(action:, retry_context: nil, tags: {}, dimensions: {}) ⇒ Hash
Build enhanced context for global on_exception handler. This method is called internally by Axn's exception handling system.
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 |
# File 'lib/axn/internal/exception_context.rb', line 32 def build(action:, retry_context: nil, tags: {}, dimensions: {}) # Get structured execution context (inputs, outputs, and extra keys at top level) exec_ctx = action.execution_context # Start building the context with formatted execution context context = { inputs: format_hash_values(exec_ctx[:inputs]), outputs: format_hash_values(exec_ctx[:outputs] || {}), } # Add any extra keys from execution context (from set_execution_context / hook) extra_keys = exec_ctx.except(:inputs, :outputs) context.merge!(format_hash_values(extra_keys)) if extra_keys.any? # When this ran nested inside other actions, record the call! chain (outermost → innermost) # so a report shows which path reached the failure — the structured breadcrumb the # user-facing result.error aggregation deliberately keeps out of the message. The live stack # is the full path here because the global report fires once, at the innermost action (which # is still on the stack). Omitted for a single (non-nested) action. :axn_stack is a # RESERVED_EXECUTION_CONTEXT_KEY, so this never clobbers a user-supplied value. stack = Core::NestingTracking._current_axn_stack context[:axn_stack] = stack.map { |a| a.class.resolved_axn_name } if stack.length > 1 # Add async information if available context[:async] = retry_context.to_h if retry_context # Declared observability facets (PRO-2853), attached under reserved namespaced keys so a # consumer's on_exception can route tag → freeform extra, dimension → indexed tags. Values # arrive already coerced (Core::Tagging.coerce) and pre-duped (Core::Tagging.dup_facets) by # the Executor, so they are attached verbatim — NOT re-run through format_hash_values (which # would diverge from what the span/metrics observe) — and a handler mutating them can't # corrupt the memoized maps. Omitted when empty, mirroring the other optional keys above. context[:tags] = if .any? context[:dimensions] = dimensions if dimensions.any? context end |