# frozen_string_literal: true require 'lograge' require 'rails' require 'opentelemetry/sdk' module Loggable # Railtie to configure logging before rails starts class Railtie < Rails::Railtie # We add a new loggable namespace to the config object, to keep all the configuration related to this gem organized config.loggable = ActiveSupport::OrderedOptions.new config.loggable.production_like = false config.loggable.current_user_method = :current_user # Initializer runs before initialize_logger (found in Bootstrap) so from the very beginning we are logging using # the logfmt format, even during the initialization process # rubocop:disable Metrics/BlockLength initializer :loggable_web, before: :initialize_logger do Rails.application.configure do production_like = Rails.env.production? || config.loggable.production_like if production_like if Rails.application.config.respond_to?(:assets) && Rails.application.config.assets.quiet Loggable::Logfmt::Logger.include_logger_silence end Rails.logger = Loggable::Logfmt::Logger.new($stdout) Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase || 'INFO') Loggable::OpenTelemetryConfig.configure(Rails.application.class.module_parent_name.underscore.dasherize) end # lograge configuration config.lograge.enabled = true config.lograge.base_controller_class = 'ApplicationController' config.lograge.custom_payload do |controller| response_code = controller.response.code if controller.respond_to?(config.loggable.current_user_method) user_id = controller.send(config.loggable.current_user_method).try(:id) end { 'source.ip': controller.request.ip, 'user.id': user_id, status: response_code, span_id: OpenTelemetry::Trace.current_span.context.hex_span_id, trace_id: OpenTelemetry::Trace.current_span.context.hex_trace_id } end config.lograge.custom_options = lambda do |event| return if event.payload[:params].blank? exceptions = %w[controller action format id] params = event.payload[:params].except(*exceptions) # append a suffix to each param params.each_with_object({}) do |(key, value), result| result["params.#{key}"] = value end end config.lograge.formatter = ::Lograge::Formatters::Raw.new end end # rubocop:enable Metrics/BlockLength initializer :loggable_worker, before: :initializer_logger do Rails.application.configure do if defined?(Delayed::Worker) if Rails.env.production? || config.loggable.production_like Delayed::Worker.logger = Loggable::Logfmt::Logger.new($stdout) Delayed::Worker.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase || 'INFO') Loggable::OpenTelemetryConfig.configure("#{Rails.application.class.module_parent_name.underscore.dasherize} -worker") else Delayed::Worker.logger = Logger.new($stdout) Delayed::Worker.logger.level = Logger::DEBUG Delayed::Worker.logger.datetime_format = '%Y-%m-%d %H:%M:%S' end end end end end end