lib/zuora_connect.rb



require 'zuora_connect/configuration'
require "zuora_connect/engine"
require 'zuora_connect/exceptions'
require 'zuora_connect/controllers/helpers'
require 'zuora_connect/railtie'
require 'resque/additions'
require 'resque/dynamic_queues'
require 'resque/silence_done'
require 'resque/self_lookup'
require 'resque/plugins/custom_logger'
require 'resque/plugins/app_instance_job'
require 'logging/connect_formatter'
require 'metrics/influx/point_value'
require 'metrics/net'
require 'mono_logger'

module ZuoraConnect
  class << self
    attr_accessor :configuration
    attr_writer :logger

    def logger
      case Rails.env.to_s
      when 'development'
        Rails.logger
       when 'test'
        Rails.logger
      else
        @logger ||= custom_logger(name: "Connect", level: Rails.logger.level)
      end
    end

    def custom_logger(name: "", level: Rails.logger.present? ? Rails.logger.level : MonoLogger::INFO, type: :ougai)
      #puts name + ' - ' + {Logger::WARN => 'Logger::WARN', Logger::ERROR => 'Logger::ERROR', Logger::DEBUG => 'Logger::DEBUG', Logger::INFO => 'Logger::INFO' }[level] + ' - '
      if type == :ougai
        require 'ougai'
        require "ougai/formatters/customizable"
        #logger = Ougai::Logger.new(MonoLogger.new(STDOUT))
        logger = Ougai::Logger.new(STDOUT)
        logger.level = level
        if ZuoraConnect.configuration.json_logging
          logger.formatter = Ougai::Formatters::ConnectFormatter.new(name)
          logger.before_log = lambda do |data|
            data[:trace_id] = ZuoraConnect::RequestIdMiddleware.request_id if ZuoraConnect::RequestIdMiddleware.request_id.present?
            data[:zuora_trace_id] = ZuoraConnect::RequestIdMiddleware.zuora_request_id if ZuoraConnect::RequestIdMiddleware.zuora_request_id.present?
            #data[:traces] = {amazon_id: data[:trace_id], zuora_id: data[:zuora_trace_id]}
          end
        else
          logger.formatter = Ougai::Formatters::Customizable.new(
            format_err: proc do |data|
              next nil unless data.key?(:err)
              err = data.delete(:err)
              "  #{err[:name]} (#{err[:message]})\n #{err[:stack]}"
            end,
            format_data: proc do |data|
              data.delete(:app_instance_id); data.delete(:tenant_ids); data.delete(:organization); data.delete(:environment)
              format('%s %s: %s', 'DATA'.ljust(6), Time.now.strftime('%FT%T.%6NZ'), "#{data.to_json}") if data.present?
            end,
            format_msg: proc do |severity, datetime, _progname, data|
              msg = data.delete(:msg)
              format('%s %s: %s', severity.ljust(6), datetime, msg)
            end
          )
          logger.formatter.datetime_format = '%FT%T.%6NZ'
        end
      else
        logger = MonoLogger.new(STDOUT)
        logger.level = level
        logger.formatter =  proc do |serverity, datetime, progname, msg|
          begin
            msg = JSON.parse(msg)
          rescue JSON::ParserError => ex
          end
          if ZuoraConnect.configuration.json_logging
            require 'json'
            store = {
              name: name,
              level: serverity,
              timestamp: datetime.strftime('%FT%T.%6NZ'),
              pid: Process.pid,
              message: name == "ActionMailer" ? msg.strip : msg
            }
            JSON.dump(store) + "\n"
          else
            format('%s %s: %s', serverity.ljust(6), datetime, msg) + "\n"
          end
        end
      end
      return logger
    end
  end

  module Controllers
    autoload :Helpers,        'zuora_connect/controllers/helpers'
  end

  def self.configuration
    @configuration ||= Configuration.new
  end

  def self.reset
    @configuration = Configuration.new
  end

  def self.configure
    yield(configuration)
    ::Apartment.excluded_models << "Delayed::Job" if configuration.delayed_job
    ::Apartment.excluded_models.concat(configuration.additional_apartment_models) if configuration.additional_apartment_models.class == Array

    return configuration
  end

  def self.elastic_apm_defaults
    defaults = {}
    case Rails.env.to_s
    when 'production'
      defaults = {
        server_url: "http://apm-server.logging:8200",
        transaction_sample_rate: 0.20,
        capture_body: 'errors'
      }
    when 'staging'
      defaults = {
        server_url: "http://apm-server.logging:8200",
        transaction_sample_rate: 1.0
      }
    when 'development'
      defaults = {
        server_url: "http://logging.0.ecc.auw2.zuora:8200",
        transaction_sample_rate: 1.0
      }
    when 'test'
      defaults = {
        active: false,
        disable_send: true
      }
    end

    defaults.merge!({
      disable_start_message: true,
      pool_size: 1,
      transaction_max_spans: 500,
      ignore_url_patterns: ['^\/admin\/resque.*', '^\/admin\/redis.*', '^\/admin\/peek.*', '^\/peek.*'],
      verify_server_cert: false,
      log_level: Logger::INFO,
      service_name: ENV['DEIS_APP'].present? ? ENV['DEIS_APP'] : Rails.application.class.parent_name,
      logger: ZuoraConnect.custom_logger(name: "ElasticAPM", level: MonoLogger::WARN)
    })
    defaults.merge!({disable_send: true}) if defined?(Rails::Console)

    return defaults
  end
end