lib/zuora_connect/railtie.rb



require 'middleware/metrics_middleware'
require 'middleware/request_id_middleware'
require 'middleware/json_parse_errors'
require 'middleware/bad_multipart_form_data_sanitizer'

module ZuoraConnect
  class Railtie < Rails::Railtie
    REQUEST_HEADERS_TO_IGNORE = %W(
      RAW_POST_DATA
      REQUEST_METHOD
      REQUEST_URI
      REQUEST_PATH
      PATH_INFO
      CONTENT_TYPE
      ORIGINAL_FULLPATH
      QUERY_STRING
    )

    config.before_initialize do
      version = Rails.version
      if version >= "5.0.0"
        ::Rails.configuration.public_file_server.enabled = true
      elsif version >= "4.2.0"
        ::Rails.configuration.serve_static_files = true
      else
        ::Rails.configuration.serve_static_assets = true
      end
      ::Rails.configuration.action_dispatch.x_sendfile_header = nil
    end

    if defined? Prometheus
      initializer "prometheus.configure_rails_initialization" do |app|
        app.middleware.use Prometheus::Middleware::Exporter,(options ={:path => '/connect/internal/metrics'})
      end
    end
    initializer "zuora_connect.configure_rails_initialization" do |app|
      app.middleware.insert_after Rack::Sendfile, ZuoraConnect::MetricsMiddleware
      app.middleware.insert_after ActionDispatch::RequestId, ZuoraConnect::RequestIdMiddleware
      app.middleware.insert_before Rack::Runtime, ZuoraConnect::BadMultipartFormDataSanitizer
      app.config.middleware.use ZuoraConnect::JsonParseErrors
    end

    # hook to process_action
    ActiveSupport::Notifications.subscribe('process_action.action_controller', ZuoraConnect::PageRequest.new)

    initializer(:rails_stdout_logging, before: :initialize_logger) do
      require 'lograge'
      
      Rails.configuration.logger = ZuoraConnect.custom_logger(name: "Rails") 
      if !Rails.env.test? && !Rails.env.development?
        Rails.configuration.lograge.enabled = true
        Rails.configuration.colorize_logging = false
      end

      if Rails.configuration.lograge.enabled
        if Rails.configuration.logger.class.to_s == 'Ougai::Logger'
          Rails.configuration.lograge.formatter = Class.new do |fmt|
            def fmt.call(data)
              { msg: 'Rails Request', request: data }
            end
          end
        end
        #Rails.configuration.lograge.formatter = Lograge::Formatters::Json.new
        Rails.configuration.lograge.custom_options = lambda do |event|
          exceptions = %w(controller action format)
          items = {
            #time: event.time.strftime('%FT%T.%6N'),  
            params: event.payload[:params].as_json(except: exceptions).to_json.to_s
          }
          items.merge!({exception_object: event.payload[:exception_object]}) if event.payload[:exception_object].present?
          items.merge!({exception: event.payload[:exception]}) if event.payload[:exception].present?

          if event.payload[:headers].present?
            # By convertion, headers usually do not have dots. Nginx even rejects headers with dots
            # All Rails headers are namespaced, like 'rack.input'.
            # Thus, we can obtain the client headers by rejecting dots
            request_headers =
              event.payload[:headers].env.
                reject { |key| key.to_s.include?('.') || REQUEST_HEADERS_TO_IGNORE.include?(key.to_s) }
            items.merge!({ headers: request_headers.to_s })
          end

          if Thread.current[:appinstance].present? 
            items.merge!({connect_user: Thread.current[:appinstance].connect_user, new_session: Thread.current[:appinstance].new_session_message})
            if Thread.current[:appinstance].logitems.present? && Thread.current[:appinstance].logitems.class == Hash
              items.merge!(Thread.current[:appinstance].logitems)
            end
          end
          return items        
        end
      end
    end
  end
end