Repository: rails/rails
File: actionpack/lib/action_controller/structured_event_subscriber.rb (Ruby)

Code before:
      emit_event("action_controller.rescue_from_handled",
        exception_class: exception.class.name,
        exception_message: exception.message,
        exception_backtrace: exception.backtrace&.first&.delete_prefix("#{Rails.root}/")
      )
    end

    def send_file(event)
      emit_event("action_controller.file_sent", path: event.payload[:path], duration_ms: event.duration.round(1))
    end

    def redirect_to(event)
      emit_event("action_controller.redirected", location: event.payload[:location])
    end

    def send_data(event)
      emit_event("action_controller.data_sent", filename: event.payload[:filename], duration_ms: event.duration.round(1))
    end

    def open_redirect(event)
      payload = event.payload
      emit_event("action_controller.open_redirect_detected",
        location: payload[:location],
        request_method: payload[:request]&.method,
        request_path: payload[:request]&.path,
        stacktrace: payload[:stacktrace]&.first&.delete_prefix("#{Rails.root}/")
      )
    end

    def unpermitted_parameters(event)
      unpermitted_keys = event.payload[:keys]
      context = event.payload[:context]

      emit_debug_event("action_controller.unpermitted_parameters",
        unpermitted_keys:,
        context: context.except(:request)
      )
    end
    debug_only :unpermitted_parameters

    def write_fragment(event)
      fragment_cache(__method__, event)
    end

    def read_fragment(event)
      fragment_cache(__method__, event)
    end

    def exist_fragment?(event)
      fragment_cache(__method__, event)
    end

Review comment (suggestion):
We probably need a `defined?(Rails)`, otherwise this won't work in projects using actionpack as a standalone gem

Code after:

      exception_backtrace = exception.backtrace&.first
      exception_backtrace = exception_backtrace&.delete_prefix("#{Rails.root}/") if defined?(Rails.root) && Rails.root

      emit_event("action_controller.rescue_from_handled",
        exception_class: exception.class.name,
        exception_message: exception.message,
        exception_backtrace:
      )
    end

    def send_file(event)
      emit_event("action_controller.file_sent", path: event.payload[:path], duration_ms: event.duration.round(1))
    end

    def redirect_to(event)
      emit_event("action_controller.redirected", location: event.payload[:location])
    end

    def send_data(event)
      emit_event("action_controller.data_sent", filename: event.payload[:filename], duration_ms: event.duration.round(1))
    end

    def open_redirect(event)
      payload = event.payload

      emit_event("action_controller.open_redirect",
        location: payload[:location],
        request_method: payload[:request]&.method,
        request_path: payload[:request]&.path,
        stacktrace: payload[:stack_trace],
      )
    end

    def unpermitted_parameters(event)
      unpermitted_keys = event.payload[:keys]
      context = event.payload[:context]

      emit_debug_event("action_controller.unpermitted_parameters",
        unpermitted_keys:,
        context: context.except(:request)
      )
    end
    debug_only :unpermitted_parameters

    def write_fragment(event)
      fragment_cache(__method__, event)
    end

    def read_fragment(event)
      fragment_cache(__method__, event)