appflux/appflux-ruby

View on GitHub
lib/appflux_ruby/message_builders/bugflux.rb

Summary

Maintainability
A
0 mins
Test Coverage
## TODO: Add Rack Env. Current User.
##
# This class builds payload message to send to the backyard application.
# custom_tabs appear as individual tabs on Bugflux UI and are only set per
#  exception occurrence.
# TODO: This might be Rails specific. Need to check for other Rack based
#  frameworks.
# {
#   bugflux: {
#     app_id: '',
#     env: {
#       app_env: 'staging'

#       request: {

#       },
#       params: {

#       },
#       headers: {

#       },
#       session: {

#       }
#     },
#     exception: {

#     }
#   },
#   custom_tabs: {
#     tab_1: {},
#     tab_2: {}
#   }
# }

module AppfluxRuby
  module MessageBuilders
    class Bugflux < AppfluxRuby::MessageBuilders::Base

      ENV_REQUEST_METHODS = %i( path host scheme user_agent port url ip
                                content_type request_method referrer )
      ENV_REQUEST_KEYS    = %i( SERVER_PROTOCOL SERVER_SOFTWARE )

      ENV_EXCEPTION_METHODS = %i( backtrace message cause class )

      SUPPORTED_BACKGROUND_JOB_PROCESSORS = %w(delayed_job sidekiq)

      def initialize exception, rack_env
        super(exception, rack_env)

        @notice[:bugflux] = Hash.new { |hsh, key| hsh[key] = Hash.new }
        @bugflux_notice = @notice[:bugflux]
      end

      def build
        super
        add_app_id
        add_request_data
        add_params
        add_exception_data
        add_env
        add_headers
        add_session_data
        add_background_job_info
        add_custom_tabs

        @notice
      end

      def self.build exception, rack_env
        new(exception, rack_env).build
      end

      private

        def add_request_data
          @bugflux_notice[:env][:request] = Hash.new
          _req_hash = @bugflux_notice[:env][:request]

          ENV_REQUEST_METHODS.each do |_method|
            _req_hash[_method.to_sym] = @request.public_send(_method)
          end

          ENV_REQUEST_KEYS.each do |_key|
            _req_hash[_key.to_sym] = @request.env[_key.to_s]
          end
        end

        def add_exception_data
          ENV_EXCEPTION_METHODS.each do |_method|
            @bugflux_notice[:exception][_method.to_sym] = @exception.public_send(_method)
          end
        end

        def add_session_data
          load_session
          return unless session_loaded?

          @bugflux_notice[:env][:session]= @request.env['rack.request.cookie_hash']
        end

        def add_headers
          @bugflux_notice[:env][:headers] = Hash.new

          @rack_env.keys.grep(/^HTTP_/).each do |_key|
            @bugflux_notice[:env][:headers][_key] = @rack_env[_key]
          end

          @bugflux_notice[:env][:headers].delete('HTTP_COOKIE')
        end

        def add_params
          @bugflux_notice[:env][:params] = @request.env['action_dispatch.request.parameters']
        end

        def add_app_id
          @bugflux_notice[:app_id] = ::AppfluxRuby::Bugflux.config.app_id
        end

        def add_env
          @bugflux_notice[:env][:app_env] = ::Rails.env if defined?(::Rails)
        end

        def add_custom_tabs
          @bugflux_notice[:custom_tabs] ||= Hash.new
          @bugflux_notice[:custom_tabs].merge!(::AppfluxRuby::Bugflux.additional_data)
        end

        ## Adds background processor information as a dedicated tab on the UI.
        def add_background_job_info
          if @rack_env[:component].in?(SUPPORTED_BACKGROUND_JOB_PROCESSORS)
            builder_klass_string = @rack_env[:component].classify
            builder_klass = "::AppfluxRuby::MessageBuilders::#{ builder_klass_string }".constantize

            @bugflux_notice[:custom_tabs] ||= Hash.new
            @bugflux_notice[:custom_tabs]["#{@rack_env[:component]}".to_sym] = builder_klass.to_hash(@rack_env)
          end
        end

        private

          def load_session
            unless session_loaded?
              @session['___bugflux_dummy_key___'] ||= 'bugflux'
            end
          end

          def session_loaded?
            @session.respond_to?(:loaded?) ? @session.loaded? : true
          end
    end
  end
end