lib/semantic_logger/appender/syslog.rb in semantic_logger-3.0.1 vs lib/semantic_logger/appender/syslog.rb in semantic_logger-3.1.0

- old
+ new

@@ -3,31 +3,23 @@ require 'socket' # Send log messages to local syslog, or remote syslog servers over TCP or UDP. # # Example: Log to a local Syslog daemon -# SemanticLogger.add_appender(SemanticLogger::Appender::Syslog.new) +# SemanticLogger.add_appender(appender: :syslog) # # Example: Log to a remote Syslog server using TCP: -# appender = SemanticLogger::Appender::Syslog.new( -# url: 'tcp://myloghost:514' +# SemanticLogger.add_appender( +# appender: :syslog, +# url: 'tcp://myloghost:514' # ) # -# # Optional: Add filter to exclude health_check, or other log entries -# appender.filter = Proc.new { |log| log.message !~ /(health_check|Not logged in)/ } -# -# SemanticLogger.add_appender(appender) -# # Example: Log to a remote Syslog server using UDP: -# appender = SemanticLogger::Appender::Syslog.new( -# url: 'udp://myloghost:514' +# SemanticLogger.add_appender( +# appender: :syslog, +# url: 'udp://myloghost:514' # ) -# -# # Optional: Add filter to exclude health_check, or other log entries -# appender.filter = Proc.new { |log| log.message !~ /(health_check|Not logged in)/ } -# -# SemanticLogger.add_appender(appender) module SemanticLogger module Appender class Syslog < SemanticLogger::Appender::Base attr_reader :remote_syslog, :url, :server, :port, :protocol, :facility, :host, :application @@ -79,10 +71,15 @@ # # level: [:trace | :debug | :info | :warn | :error | :fatal] # Override the log level for this appender. # Default: SemanticLogger.default_level # + # formatter: [Object|Proc] + # An instance of a class that implements #call, or a Proc to be used to format + # the output from this appender + # Default: Use the built-in formatter (See: #call) + # # filter: [Regexp|Proc] # RegExp: Only include log messages where the class name matches the supplied. # regular expression. All other messages will be ignored. # Proc: Only include log messages where the supplied Proc returns true # The Proc must return true or false. @@ -141,14 +138,19 @@ # warn: ::Syslog::LOG_WARNING, # info: ::Syslog::LOG_NOTICE, # debug: ::Syslog::LOG_INFO, # trace: ::Syslog::LOG_DEBUG # } + # + # format: [Symbol] + # Format for the Syslog message + # :syslog uses the default syslog format + # :json uses the CEE JSON Syslog format + # Example: "@cee: #{JSON.dump(data)}" + # Default: :syslog def initialize(options = {}, &block) options = options.dup - level = options.delete(:level) - filter = options.delete(:filter) @application = options.delete(:application) || options.delete(:ident) || 'ruby' @options = options.delete(:options) || (::Syslog::LOG_PID | ::Syslog::LOG_CONS) @facility = options.delete(:facility) || ::Syslog::LOG_USER level_map = options.delete(:level_map) @url = options.delete(:url) || options.delete(:server) || 'syslog://localhost' @@ -159,11 +161,10 @@ @server = 'localhost' if @protocol == :syslog @host = options.delete(:host) || options.delete(:local_hostname) || SemanticLogger.host @tcp_client_options = options.delete(:tcp_client) raise "Unknown protocol #{@protocol}!" unless [:syslog, :tcp, :udp].include?(@protocol) - raise(ArgumentError, "Unknown options: #{options.inspect}") if options.size > 0 @level_map = DEFAULT_LEVEL_MAP.dup @level_map.update(level_map) if level_map # The syslog_protocol gem is required when logging over TCP or UDP. @@ -186,11 +187,11 @@ end end reopen - super(level, filter, &block) + super(options, &block) end # After forking an active process call #reopen to re-open # open the handles to resources def reopen @@ -233,48 +234,46 @@ @remote_syslog.flush if @remote_syslog && @remote_syslog.respond_to?(:flush) end # Custom log formatter for syslog. # Only difference is the removal of the timestamp string since it is in the syslog packet. - def default_formatter - Proc.new do |log| - # Header with date, time, log level and process info - entry = "#{log.level_to_s} [#{log.process_info}]" + def call(log, logger) + # Header with date, time, log level and process info + message = "#{log.level_to_s} [#{log.process_info}]" - # Tags - entry << ' ' << log.tags.collect { |tag| "[#{tag}]" }.join(' ') if log.tags && (log.tags.size > 0) + # Tags + message << ' ' << log.tags.collect { |tag| "[#{tag}]" }.join(' ') if log.tags && (log.tags.size > 0) - # Duration - entry << " (#{log.duration_human})" if log.duration + # Duration + message << " (#{log.duration_human})" if log.duration - # Class / app name - entry << " #{log.name}" + # Class / app name + message << " #{log.name}" - # Log message - entry << " -- #{log.message}" if log.message + # Log message + message << " -- #{log.message}" if log.message - # Payload - if payload = log.payload_to_s(false) - entry << ' -- ' << payload - end + # Payload + if payload = log.payload_to_s + message << ' -- ' << payload + end - # Exceptions - if log.exception - entry << " -- Exception: #{log.exception.class}: #{log.exception.message}\n" - entry << log.backtrace_to_s - end - entry + # Exceptions + if log.exception + message << " -- Exception: #{log.exception.class}: #{log.exception.message}\n" + message << log.backtrace_to_s end + message end # Format the syslog packet so it can be sent over TCP or UDP def syslog_packet_formatter(log) packet = SyslogProtocol::Packet.new packet.hostname = @host packet.facility = @facility packet.severity = @level_map[log.level] packet.tag = @application - packet.content = default_formatter.call(log, self) + packet.content = formatter.call(log, self) packet.time = log.time packet.to_s end end end