class Swiftcore::LoggerClass

Constants

DefaultSeverityLevels
EXEC_ARGUMENTS
EXIT_SIGNALS
RELOAD_SIGNALS
RESTART_SIGNALS
VERSION

Public Class Methods

_handle_pending_and_exit() click to toggle source
# File lib/swiftcore/Analogger.rb, line 101
def _handle_pending_and_exit
  if any_in_queue?
    write_queue
    EventMachine.next_tick {_handle_pending_and_exit}
  else
    EventMachine.stop
  end
end
add_log(log) click to toggle source
# File lib/swiftcore/Analogger.rb, line 206
def add_log(log)
  @queue[log.first] << log
  @rcount += 1
end
any_in_queue?() click to toggle source
# File lib/swiftcore/Analogger.rb, line 211
def any_in_queue?
  any = 0
  @queue.each do |service, q|
    q.each do |m|
      next unless levels.has_key?(m[1])
      any += 1
    end
  end
  any > 0 ? any : false
end
check_config_settings() click to toggle source
# File lib/swiftcore/Analogger.rb, line 174
def check_config_settings
  raise NoPortProvided unless @config[-"port"]
  raise BadPort.new(@config[-"port"]) unless @config[-"port"].to_i > 0
end
cleanup() click to toggle source
# File lib/swiftcore/Analogger.rb, line 110
def cleanup
  @logs.each do |service,l|
    l.logfile.fsync if !l.logfile.closed? and l.logfile.fileno > 2
    l.logfile.close unless l.logfile.closed? or l.logfile.fileno < 3
  end
end
cleanup_and_reopen() click to toggle source
# File lib/swiftcore/Analogger.rb, line 117
def cleanup_and_reopen
  @logs.each do |service,l|
    l.logfile.fsync if !l.logfile.closed? and l.logfile.fileno > 2
    l.logfile.reopen(l.logfile.path, -"ab+") if l.logfile.fileno > 2
  end
end
config() click to toggle source
# File lib/swiftcore/Analogger.rb, line 128
def config
  @config
end
config=(conf) click to toggle source
# File lib/swiftcore/Analogger.rb, line 132
def config=(conf)
  @config = conf
end
daemonize() click to toggle source
# File lib/swiftcore/Analogger.rb, line 76
def daemonize
  if (child_pid = fork)
    puts "PID #{child_pid}" unless @config[-"pidfile"]
    exit!
  end
  Process.setsid

  exit if fork

rescue NotImplementedError
  puts "Platform (#{RUBY_PLATFORM}) does not appear to support fork/setsid; skipping"
end
flush_queue() click to toggle source
# File lib/swiftcore/Analogger.rb, line 255
def flush_queue
  @logs.each_value do |l|
    #if !l.logfile.closed? and l.logfile.fileno > 2
    if l.logfile.fileno > 2
      l.logfile.fdatasync rescue l.logfile.fsync
    end
  end
end
handle_pending_and_exit() click to toggle source

Before exiting, try to get any logs that are still in memory handled and written to disk.

# File lib/swiftcore/Analogger.rb, line 94
def handle_pending_and_exit
  EventMachine.stop_server(@server)
  EventMachine.add_timer(1) do
    _handle_pending_and_exit
  end
end
key() click to toggle source
# File lib/swiftcore/Analogger.rb, line 264
def key
  @config[-"key"].to_s
end
logfile_destination(logfile) click to toggle source
# File lib/swiftcore/Analogger.rb, line 189
def logfile_destination(logfile)
  # We're reloading if it's already an IO.
  if logfile.is_a?(IO)
    return $stdout if logfile == $stdout
    return $stderr if logfile == $stderr
    return logfile.reopen(logfile.path, -"ab+")
  end

  if logfile =~ /^STDOUT$/i
    $stdout
  elsif logfile =~ /^STDERR$/i
    $stderr
  else
    File.open(logfile, -"ab+")
  end
end
new_log(facility = -"default", levels = @config[-"levels"] || DefaultSeverityLevels, log = @config[-"default_log"], cull = true) click to toggle source
# File lib/swiftcore/Analogger.rb, line 89
def new_log(facility = -"default", levels = @config[-"levels"] || DefaultSeverityLevels, log = @config[-"default_log"], cull = true)
  Log.new({-"service" => facility, -"levels" => levels, -"logfile" => log, -"cull" => cull})
end
normalize_levels(levels) click to toggle source
# File lib/swiftcore/Analogger.rb, line 160
def normalize_levels(levels)
  if String === levels and levels =~ /,/
    levels.split(/,/).inject({}) {|h,k| h[k.to_s] = true; h}
  elsif Array === levels
    levels.inject({}) {|h,k| h[k.to_s] = true; h}
  elsif levels.nil?
    DefaultSeverityLevels
  elsif !(Hash === levels)
    [levels.to_s => true]
  else
    levels
  end
end
populate_logs() click to toggle source
# File lib/swiftcore/Analogger.rb, line 136
def populate_logs
  @config[-"logs"].each do |log|
    next unless log[-"service"]
    if Array === log[-"service"]
      log[-"service"].each do |loglog|
        @logs[loglog] = new_log(loglog,log[-"levels"],logfile_destination(log[-"logfile"]),log[-"cull"])
      end
    else
      @logs[log[-"service"]] = new_log(log[-"service"],log[-"levels"],logfile_destination(log[-"logfile"]),log[-"cull"])
    end
  end
end
postprocess_config_load() click to toggle source
# File lib/swiftcore/Analogger.rb, line 149
def postprocess_config_load
  @config[-"logs"] ||= []
  if @config[-"levels"]
    @config[-"levels"] = normalize_levels(@config[-"levels"])
  end

  @config[-"logs"].each do |log|
    log[-"levels"] = normalize_levels(log[-"levels"])
  end
end
safe_trap(siglist, &operation) click to toggle source
# File lib/swiftcore/Analogger.rb, line 27
def safe_trap(siglist, &operation)
  (Signal.list.keys & siglist).each {|sig| trap(sig, &operation)}
end
set_config_defaults() click to toggle source
# File lib/swiftcore/Analogger.rb, line 179
def set_config_defaults
  @config[-"host"] ||= -"127.0.0.1"
  @config[-"interval"] ||= 1
  @config[-"syncinterval"] ||= 60
  @config[-"syncinterval"] = nil if @config[-"syncinterval"] == 0
  @config[-"default_log"] = @config[-"default_log"].nil? || @config[-"default_log"] == -"-" ? -"STDOUT" : @config[-"default_log"]
  @config[-"default_log"] = logfile_destination(@config[-"default_log"])
  @logs[-"default"] = new_log
end
start(config,protocol = AnaloggerProtocol) click to toggle source
# File lib/swiftcore/Analogger.rb, line 31
def start(config,protocol = AnaloggerProtocol)
  @config = config
  daemonize if @config[-"daemonize"]
  File.open(@config[-"pidfile"],-"w+") {|fh| fh.puts $$} if @config[-"pidfile"]
  @logs = Hash.new {|h,k| h[k] = new_log(k)}
  @queue = Hash.new {|h,k| h[k] = []}
  postprocess_config_load
  check_config_settings
  populate_logs
  set_config_defaults
  @rcount = 0
  @wcount = 0
  @server = nil
  safe_trap(EXIT_SIGNALS) {handle_pending_and_exit}
  safe_trap(RELOAD_SIGNALS) {cleanup_and_reopen}
  safe_trap(RESTART_SIGNALS) {exec(*EXEC_ARGUMENTS)}

  #####
  # This is gross.  EM needs to change so that it defaults to the faster
  # platform specific methods, allowing the user the option to downgrade
  # to a simple select() loop if they have a good reason for it.
  #
  EventMachine.epoll rescue nil
  EventMachine.kqueue rescue nil
  #
  # End of gross.
  #
  # TODO: The above was written YEARS ago. See if EventMachine is smarter, now.
  #####

  EventMachine.set_descriptor_table_size(4096)
  EventMachine.run {
    EventMachine.add_shutdown_hook do
      write_queue
      flush_queue
      cleanup
    end
    @server = EventMachine.start_server @config[-"host"], @config[-"port"], protocol
    EventMachine.add_periodic_timer(1) {Analogger.update_now}
    EventMachine.add_periodic_timer(@config[-"interval"]) {write_queue}
    EventMachine.add_periodic_timer(@config[-"syncinterval"]) {flush_queue}
  }
  exit
end
update_now() click to toggle source
# File lib/swiftcore/Analogger.rb, line 124
def update_now
  @now = Time.now.strftime(-"%Y/%m/%d %H:%M:%S")
end
write_queue() click to toggle source
# File lib/swiftcore/Analogger.rb, line 222
def write_queue
  @queue.each do |service, q|
    last_sv = nil
    last_m = nil
    last_count = 0
    next unless log = @logs[service]
    lf = log.logfile
    cull = log.cull
    levels = log.levels
    q.each do |m|
      next unless levels.has_key?(m[1])
      if cull
        if m.last == last_m and m[0..1] == last_sv
          last_count += 1
          next
        elsif last_count > 0
          lf.write_nonblock "#{@now}|#{last_sv.join(-"|")}|Last message repeated #{last_count} times\n"
          last_sv = last_m = nil
          last_count = 0
        end
        lf.write_nonblock "#{@now}|#{m.join(-"|")}\n"
        last_m = m.last
        last_sv = m[0..1]
      else
        lf.write_nonblock "#{@now}|#{m.join(-"|")}\n"
      end
      @wcount += 1
    end
    lf.write_nonblock "#{@now}|#{last_sv.join(-"|")}|Last message repeated #{last_count} times\n" if cull and last_count > 0
  end
  @queue.each {|service,q| q.clear}
end