class MongodbLogger::Logger

Constants

ADAPTERS
CONFIGURATION_FILES

Looks for configuration files in this order

DEFAULT_COLLECTION_SIZE
LOG_LEVEL_SYM

Attributes

app_env[R]
app_root[R]
db_configuration[R]
excluded_from_log[W]
mongo_adapter[R]

Public Class Methods

new(path = nil, level = DEBUG) click to toggle source
Calls superclass method
# File lib/mongodb_logger/logger.rb, line 28
def initialize(path = nil, level = DEBUG)
  set_root_and_env
  begin
    path ||= File.join(app_root, "log/#{app_env}.log")
    @level = level
    internal_initialize
  rescue => e
    # should use a config block for this
    "production" == app_env ? (raise e) : (puts "MongodbLogger WARNING: Using Rails Logger due to exception: #{e.message}")
  ensure
    if disable_file_logging?
      @log            = ::Logger.new(STDOUT)
      @log.level      = @level
    else
      super(path, @level)
    end
  end
end

Public Instance Methods

add(severity, message = nil, progname = nil, &block) click to toggle source
Calls superclass method
# File lib/mongodb_logger/logger.rb, line 57
def add(severity, message = nil, progname = nil, &block)
  $stdout.puts(message) if ENV['HEROKU_RACK'] # log in stdout on Heroku
  if @level && @level <= severity && (message.present? || progname.present?) && @mongo_record.present?
    add_log_message(severity, message, progname)
  end
  # may modify the original message
  disable_file_logging? ? message : (@level ? super : message)
end
add_metadata(options = {}) click to toggle source
# File lib/mongodb_logger/logger.rb, line 47
def add_metadata(options = {})
  options.each do |key, value|
    unless [:messages, :request_time, :ip, :runtime, :application_name, :is_exception, :params, :session, :method].include?(key.to_sym)
      @mongo_record[key] = value
    else
      raise ArgumentError, ":#{key} is a reserved key for the mongodb logger. Please choose a different key"
    end
  end if @mongo_record
end
excluded_from_log() click to toggle source
# File lib/mongodb_logger/logger.rb, line 86
def excluded_from_log
  @excluded_from_log ||= nil
end
mongoize(options = {}) { || ... } click to toggle source
# File lib/mongodb_logger/logger.rb, line 66
def mongoize(options = {})
  @mongo_record = options.merge({
    messages: Hash.new { |hash, key| hash[key] = Array.new },
    request_time: Time.now.getutc,
    application_name: @db_configuration['application_name']
  })

  runtime = Benchmark.measure{ yield }.real if block_given?
rescue Exception => e
  log_raised_error(e)
  # Reraise the exception for anyone else who cares
  raise e
ensure
  # In case of exception, make sure runtime is set
  @mongo_record[:runtime] = ((runtime ||= 0) * 1000).ceil
  # error callback
  Base.on_log_exception(@mongo_record) if @mongo_record[:is_exception]
  ensure_write_to_mongodb
end

Private Instance Methods

add_log_message(severity, message, progname) click to toggle source
# File lib/mongodb_logger/logger.rb, line 125
def add_log_message(severity, message, progname)
  # do not modify the original message used by the buffered logger
  msg = (message ? message : progname)
  msg = logging_colorized? ? msg.to_s.gsub(/(\e(\[([\d;]*[mz]?))?)?/, '').strip : msg
  @mongo_record[:messages][LOG_LEVEL_SYM[severity]] << msg
end
check_for_collection() click to toggle source
# File lib/mongodb_logger/logger.rb, line 192
def check_for_collection
  @mongo_adapter.check_for_collection
end
configure() click to toggle source
# File lib/mongodb_logger/logger.rb, line 102
def configure
  @db_configuration = {
    host: 'localhost',
    port: 27017,
    capsize: DEFAULT_COLLECTION_SIZE,
    ssl: false}.merge(resolve_config).with_indifferent_access
  @db_configuration[:collection] ||= "#{app_env}_log"
  @db_configuration[:application_name] ||= resolve_application_name
  @db_configuration[:write_options] ||= { w: 0, wtimeout: 200 }

  @insert_block = @db_configuration.has_key?(:replica_set) && @db_configuration[:replica_set] ?
    lambda { rescue_connection_failure{ insert_log_record(@db_configuration[:write_options]) } } :
    lambda { insert_log_record(@db_configuration[:write_options]) }
end
connect() click to toggle source
# File lib/mongodb_logger/logger.rb, line 185
def connect
  adapter = find_adapter
  raise "!!! MongodbLogger not found supported adapter. Please, add mongo with bson_ext gems or moped gem into Gemfile !!!" if adapter.nil?
  @mongo_adapter ||= adapter.new(@db_configuration)
  @db_configuration = @mongo_adapter.configuration
end
disable_file_logging?() click to toggle source
# File lib/mongodb_logger/logger.rb, line 98
def disable_file_logging?
  @db_configuration && @db_configuration.fetch(:disable_file_logging, false)
end
ensure_write_to_mongodb() click to toggle source
# File lib/mongodb_logger/logger.rb, line 138
def ensure_write_to_mongodb
  @insert_block.call
rescue
  begin
    # try to nice serialize record
    record_serializer @mongo_record, true
    @insert_block.call
  rescue
    # do extra work to inspect (and flatten)
    record_serializer @mongo_record, false
    @insert_block.call rescue nil
  end
end
find_adapter() click to toggle source
# File lib/mongodb_logger/logger.rb, line 170
def find_adapter
  return Adapers::Mongo if defined?(::Mongo)
  return Adapers::Moped if defined?(::Moped)

  ADAPTERS.each do |(library, adapter)|
    begin
      require library
      return adapter
    rescue LoadError
      next
    end
  end
  return nil
end
insert_log_record(write_options) click to toggle source
# File lib/mongodb_logger/logger.rb, line 196
def insert_log_record(write_options)
  return if excluded_from_log && excluded_from_log.any? { |k, v| v.include?(@mongo_record[k]) }
  @mongo_adapter.insert_log_record(@mongo_record, write_options: write_options)
end
internal_initialize() click to toggle source
# File lib/mongodb_logger/logger.rb, line 92
def internal_initialize
  configure
  connect
  check_for_collection
end
log_raised_error(e) click to toggle source
# File lib/mongodb_logger/logger.rb, line 132
def log_raised_error(e)
  add(3, "#{e.message}\n#{e.backtrace.join("\n")}")
  # log exceptions
  @mongo_record[:is_exception] = true
end
logging_colorized?() click to toggle source
# File lib/mongodb_logger/logger.rb, line 201
def logging_colorized?
  # Cache it since these ActiveRecord attributes are assigned after logger initialization occurs in Rails boot
  @colorized ||= Object.const_defined?(:ActiveRecord) && ActiveRecord::LogSubscriber.colorize_logging
end
nice_serialize_object(data) click to toggle source
# File lib/mongodb_logger/logger.rb, line 217
def nice_serialize_object(data)
  case data
    when NilClass, String, Fixnum, Bignum, Float, TrueClass, FalseClass, Time, Regexp, Symbol
      data
    when Hash
      hvalues = Hash.new
      data.each{ |k,v| hvalues[k] = nice_serialize_object(v) }
      hvalues
    when Array
      data.map{ |v| nice_serialize_object(v) }
    when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile # uploaded files
      {
        original_filename: data.original_filename,
        content_type: data.content_type
      }
    else
      data.inspect
  end
end
read_config_from_file(config_file) click to toggle source
# File lib/mongodb_logger/logger.rb, line 161
def read_config_from_file(config_file)
  if File.file? config_file
    config = ::YAML.load(ERB.new(File.new(config_file).read).result)[app_env]
    config = config['mongodb_logger'] if config && config.has_key?('mongodb_logger')
    return config unless config.blank?
  end
  return nil
end
record_serializer(rec, nice = true) click to toggle source

try to serialyze data by each key and found invalid object

# File lib/mongodb_logger/logger.rb, line 207
def record_serializer(rec, nice = true)
  [:messages, :params].each do |key|
    if msgs = rec[key]
      msgs.each do |i, j|
        msgs[i] = (true == nice ? nice_serialize_object(j) : j.inspect)
      end
    end
  end
end
resolve_application_name() click to toggle source
# File lib/mongodb_logger/logger.rb, line 117
def resolve_application_name
  if defined?(Rails)
    Rails.application.class.to_s.split("::").first
  else
    "RackApp"
  end
end
resolve_config() click to toggle source
# File lib/mongodb_logger/logger.rb, line 152
def resolve_config
  config = {}
  CONFIGURATION_FILES.each do |filename|
    config = read_config_from_file(File.join(app_root, 'config', filename))
    break unless config.blank?
  end
  config
end
set_root_and_env() click to toggle source
# File lib/mongodb_logger/logger.rb, line 237
def set_root_and_env
  if defined? Rails
    @app_root, @app_env = Rails.root.to_s, Rails.env.to_s
  elsif defined? RACK_ROOT
    @app_root, @app_env = RACK_ROOT, (ENV['RACK_ENV'] || 'production')
  else
    @app_root, @app_env = File.dirname(__FILE__), 'production'
  end
end