class Flor::Logger

No log rotation, just dump to stdout (or stderr), see 12factor.net/logs

Constants

BLOB_CHARS
LEVELS_I

NB: logger configuration entries start with “log_”

Attributes

level[R]

Public Class Methods

new(unit) click to toggle source
# File lib/flor/unit/logger.rb, line 17
def initialize(unit)

  @unit = unit
  @unit.hooker.add('logger', self)

  @out = Flor::Logger::Out.prepare(@unit)

  @uni = @unit.identifier

  self.level = @unit.conf['log_level'] || 1
end

Public Instance Methods

db_log(level, msg) click to toggle source
# File lib/flor/unit/logger.rb, line 111
    def db_log(level, msg)

      return unless @unit.conf['log_sto']
#return unless msg.match(/flor_timers/)
#p Time.now

      _c = Flor.colours(out: @out)

      #m = msg.match(/ (INSERT|UPDATE) .+ (0?[xX]'?[a-fA-F0-9]+'?)/)
      #msg = msg.sub(m[2], "#{m[2][0, 14]}(...len#{m[2].length})") if m
        #
        # with a fat blob, may lead to memory problems very quickly, hence:
        #
      msg = summarize_blob(msg)

      msg = "#{_c.dg}#{msg}"
      msg = msg.gsub(/\b(INSERT|UPDATE)\b/) { |m| "#{_c.rs}#{m}#{_c.dg}" }

      tim = Time.now.utc.strftime('%T.%L') # HH:MM:SS.123
      dbi = @unit.storage.db.object_id.to_s(16)
      tid = Thread.current.object_id.to_s(16)
      lvl = level.upcase

      @out.puts(
        "#{_c.blg}sto#{_c.rs} " +
        "#{tim} #{_c.dg}db#{dbi} th#{tid} " +
        "#{_c.rs}#{lvl}#{_c.rs} #{msg}#{_c.rs}")
    end
debug(*m) click to toggle source
# File lib/flor/unit/logger.rb, line 51
def debug(*m); log(:debug, *m); end
error(*m) click to toggle source
# File lib/flor/unit/logger.rb, line 54
def error(*m); log(:error, *m); end
fatal(*m) click to toggle source
# File lib/flor/unit/logger.rb, line 55
def fatal(*m); log(:fatal, *m); end
info(*m) click to toggle source
# File lib/flor/unit/logger.rb, line 52
def info(*m); log(:info, *m); end
level=(i) click to toggle source
# File lib/flor/unit/logger.rb, line 38
def level=(i)

  original = i
  i = LEVELS_I.index(i.to_s.upcase) unless i.is_a?(Integer)

  fail ArgumentError.new(
    "'log_level' must be between 0 (DEBUG) and 4 (FATAL). " +
    "#{original.inspect} not acceptable"
  ) unless i.is_a?(Integer) && i > -1 && i < 6

  @level = i
end
log(level, *elts) click to toggle source
# File lib/flor/unit/logger.rb, line 58
def log(level, *elts)

  lvl = level.to_s.upcase
  lvi = LEVELS_I.index(lvl)
  return if lvi < @level

  n = Time.now.utc
  stp = Flor.tstamp(n)

  dbi =
    case @unit.storage.db.to_s
    when /SQLite/ then @unit.storage.db.uri
    else ''
    end
  dbi = ' ' + dbi if dbi.length > 0

  txt = elts.collect(&:to_s).join(' ')

  err = find_err(elts)

  head = "#{stp} #{@uni}#{dbi} #{lvl} "

  if err
    dig = lvl[0, 1] + Digest::MD5.hexdigest(head + txt)[0, 4]
    @out.puts(head + dig + ' ' + txt)
    err.backtrace.each { |lin| @out.puts("  #{dig} #{@uni} #{lin}") }
  else
    @out.puts(head + txt)
  end
end
log_err(executor, message, opts={}) click to toggle source
# File lib/flor/unit/logger.rb, line 199
def log_err(executor, message, opts={})

  return unless @unit.conf['log_err']

  s = Flor.msg_to_detail_s(executor, message, opts.merge(flag: true))
  @out.puts(s) if s
end
log_run_end(executor, tstamp, duration) click to toggle source
# File lib/flor/unit/logger.rb, line 166
def log_run_end(executor, tstamp, duration)

  return unless @unit.conf['log_run']

  execution = executor.execution
  exid = executor.exid

  _c = Flor.colours(out: @out)
  s = StringIO.new

  s << _c.dg
  s << "    |   run ends #{self.class} #{self.object_id} #{exid}"
  #s << "\n    |   "; s << Flor.to_dnc(started: tstamp, took: duration)
  s << "\n    |   "; s << Flor.to_dnc(started: tstamp, took: duration)
  s << "\n    |   "; s << Flor.to_dnc(
    thread: Thread.current.object_id,
    consumed: executor.consumed.count,
    traps: executor.traps.count)
  s << "\n    |   "; s << Flor.to_dnc(
    #own_traps: @traps.reject { |t| t.texid == nil }.size, # FIXME
    counters: execution['counters'],
    nodes: execution['nodes'].size,
    execution_size: size_to_s(execution['size']))
  if @unit.archive
    s << "\n    |   "
    s << Flor.to_dnc(archive_size: (@unit.archive[exid].size rescue '???'))
  end
  s << "\n    \\--- ."
  s << _c.rs

  @out.puts(s.string)
end
log_run_start(executor) click to toggle source
# File lib/flor/unit/logger.rb, line 145
def log_run_start(executor)

  return unless @unit.conf['log_run']

  execution = executor.execution
  _c = Flor.colours(out: @out)
  s = StringIO.new

  s << _c.dg
  s << "    /--- #{_c.lg}run starts#{_c.dg} "
  s << "#{executor.class} #{executor.object_id} #{execution['exid']}"
  s << "\n    |   "; s << Flor.to_dnc(thread: Thread.current.object_id)
  s << "\n    |   "; s << Flor.to_dnc(
    counters: execution['counters'],
    nodes: execution['nodes'].size,
    execution_size: size_to_s(execution['size']))
  s << _c.rs

  @out.puts(s.string)
end
log_src(source, opts, log_opts={}) click to toggle source
# File lib/flor/unit/logger.rb, line 207
def log_src(source, opts, log_opts={})

  return unless @unit.conf['log_src']

  @out.puts(Flor.src_to_s(source, opts, log_opts))
end
log_tree(tree, nid='0', opts={}) click to toggle source
# File lib/flor/unit/logger.rb, line 214
def log_tree(tree, nid='0', opts={})

  return unless @unit.conf['log_tree']

  @out.puts(Flor.tree_to_s(tree, nid, opts.merge(out: @out)))
end
notify(executor, msg) click to toggle source
# File lib/flor/unit/logger.rb, line 89
def notify(executor, msg)

  if msg['rewritten'] && @unit.conf['log_tree_rw']

    @out <<
      Flor.to_compact_tree_s(
        msg['rewritten'], msg['nid'],
        ind: 6, title: "rewrote #{msg['exid']} #{msg['nid']}")
    @out << "\n" <<
      Flor.to_compact_tree_s(
        msg['tree'], msg['nid'],
        ind: 6, title: "into #{msg['exid']} #{msg['nid']}",
        close: true)
  end

  @out.puts(
    Flor.message_to_one_line_s(executor, msg, out: @out)
  ) if @unit.conf['log_msg'] && msg['point'] != 'end'

  [] # we're only logging, do not queue further messages
end
opts() click to toggle source
# File lib/flor/unit/logger.rb, line 29
def opts; { consumed: true }; end
shutdown() click to toggle source
# File lib/flor/unit/logger.rb, line 31
def shutdown

  @out.close
end
size_to_s(s) click to toggle source
# File lib/flor/unit/logger.rb, line 140
def size_to_s(s)

  "%.2fk" % (s.to_f / 1024)
end
unknown(*m) click to toggle source
# File lib/flor/unit/logger.rb, line 56
def unknown(*m); log(:unknown, *m); end
warn(*m) click to toggle source
# File lib/flor/unit/logger.rb, line 53
def warn(*m); log(:warn, *m); end

Protected Instance Methods

find_err(elts) click to toggle source
# File lib/flor/unit/logger.rb, line 251
def find_err(elts)

  elts.find { |e| e.is_a?(Exception) } ||
  (defined?(Java) &&
   elts.find { |e| e.class.ancestors.include?(Java::JavaLang::Error) })
end
summarize_blob(message) click to toggle source
# File lib/flor/unit/logger.rb, line 225
def summarize_blob(message)

  #
  # /!\ reminder: substitutes only one blob
  #

  i = message.index(' INSERT ') || message.index(' UPDATE ')
  return message unless i

  j = message.index(" x'") || message.index(" X'")
  k = j || message.index(" 0x") || message.index(" 0X")
  return message unless k

  over = j ? [ "'" ] : [ ' ', nil ]

  i = k + 3
  loop do
    c = message[i, 1]
    break if over.include?(c)
    return message unless BLOB_CHARS.index(c)
    i = i + 1
  end

  message[0..k + 2 + 4] + "(...len#{i - (k + 2 + 1)})" + message[i..-1]
end