1require 'syslog' 2require 'logger' 3 4## 5# Syslog::Logger is a Logger work-alike that logs via syslog instead of to a 6# file. You can use Syslog::Logger to aggregate logs between multiple 7# machines. 8# 9# By default, Syslog::Logger uses the program name 'ruby', but this can be 10# changed via the first argument to Syslog::Logger.new. 11# 12# NOTE! You can only set the Syslog::Logger program name when you initialize 13# Syslog::Logger for the first time. This is a limitation of the way 14# Syslog::Logger uses syslog (and in some ways, a limitation of the way 15# syslog(3) works). Attempts to change Syslog::Logger's program name after 16# the first initialization will be ignored. 17# 18# === Example 19# 20# The following will log to syslogd on your local machine: 21# 22# require 'syslog/logger' 23# 24# log = Syslog::Logger.new 'my_program' 25# log.info 'this line will be logged via syslog(3)' 26# 27# You may need to perform some syslog.conf setup first. For a BSD machine add 28# the following lines to /etc/syslog.conf: 29# 30# !my_program 31# *.* /var/log/my_program.log 32# 33# Then touch /var/log/my_program.log and signal syslogd with a HUP 34# (killall -HUP syslogd, on FreeBSD). 35# 36# If you wish to have logs automatically roll over and archive, see the 37# newsyslog.conf(5) and newsyslog(8) man pages. 38 39class Syslog::Logger 40 # Default formatter for log messages. 41 class Formatter 42 def call severity, time, progname, msg 43 clean msg 44 end 45 46 private 47 48 ## 49 # Clean up messages so they're nice and pretty. 50 51 def clean message 52 message = message.to_s.strip 53 message.gsub!(/\e\[[0-9;]*m/, '') # remove useless ansi color codes 54 return message 55 end 56 end 57 58 ## 59 # The version of Syslog::Logger you are using. 60 61 VERSION = '2.0' 62 63 ## 64 # Maps Logger warning types to syslog(3) warning types. 65 # 66 # Messages from ruby applications are not considered as critical as messages 67 # from other system daemons using syslog(3), so most messages are reduced by 68 # one level. For example, a fatal message for ruby's Logger is considered 69 # an error for syslog(3). 70 71 LEVEL_MAP = { 72 ::Logger::UNKNOWN => Syslog::LOG_ALERT, 73 ::Logger::FATAL => Syslog::LOG_ERR, 74 ::Logger::ERROR => Syslog::LOG_WARNING, 75 ::Logger::WARN => Syslog::LOG_NOTICE, 76 ::Logger::INFO => Syslog::LOG_INFO, 77 ::Logger::DEBUG => Syslog::LOG_DEBUG, 78 } 79 80 ## 81 # Returns the internal Syslog object that is initialized when the 82 # first instance is created. 83 84 def self.syslog 85 @@syslog 86 end 87 88 ## 89 # Specifies the internal Syslog object to be used. 90 91 def self.syslog= syslog 92 @@syslog = syslog 93 end 94 95 ## 96 # Builds a methods for level +meth+. 97 98 def self.make_methods meth 99 level = ::Logger.const_get(meth.upcase) 100 eval <<-EOM, nil, __FILE__, __LINE__ + 1 101 def #{meth}(message = nil, &block) 102 add(#{level}, message, &block) 103 end 104 105 def #{meth}? 106 @level <= #{level} 107 end 108 EOM 109 end 110 111 ## 112 # :method: unknown 113 # 114 # Logs a +message+ at the unknown (syslog alert) log level, or logs the 115 # message returned from the block. 116 117 ## 118 # :method: fatal 119 # 120 # Logs a +message+ at the fatal (syslog err) log level, or logs the message 121 # returned from the block. 122 123 ## 124 # :method: error 125 # 126 # Logs a +message+ at the error (syslog warning) log level, or logs the 127 # message returned from the block. 128 129 ## 130 # :method: warn 131 # 132 # Logs a +message+ at the warn (syslog notice) log level, or logs the 133 # message returned from the block. 134 135 ## 136 # :method: info 137 # 138 # Logs a +message+ at the info (syslog info) log level, or logs the message 139 # returned from the block. 140 141 ## 142 # :method: debug 143 # 144 # Logs a +message+ at the debug (syslog debug) log level, or logs the 145 # message returned from the block. 146 147 Logger::Severity::constants.each do |severity| 148 make_methods severity.downcase 149 end 150 151 ## 152 # Log level for Logger compatibility. 153 154 attr_accessor :level 155 156 # Logging formatter, as a +Proc+ that will take four arguments and 157 # return the formatted message. The arguments are: 158 # 159 # +severity+:: The Severity of the log message. 160 # +time+:: A Time instance representing when the message was logged. 161 # +progname+:: The #progname configured, or passed to the logger method. 162 # +msg+:: The _Object_ the user passed to the log message; not necessarily a 163 # String. 164 # 165 # The block should return an Object that can be written to the logging 166 # device via +write+. The default formatter is used when no formatter is 167 # set. 168 attr_accessor :formatter 169 170 ## 171 # Fills in variables for Logger compatibility. If this is the first 172 # instance of Syslog::Logger, +program_name+ may be set to change the logged 173 # program name. 174 # 175 # Due to the way syslog works, only one program name may be chosen. 176 177 def initialize program_name = 'ruby' 178 @level = ::Logger::DEBUG 179 @formatter = Formatter.new 180 181 @@syslog ||= Syslog.open(program_name) 182 end 183 184 ## 185 # Almost duplicates Logger#add. +progname+ is ignored. 186 187 def add severity, message = nil, progname = nil, &block 188 severity ||= ::Logger::UNKNOWN 189 @level <= severity and 190 @@syslog.log LEVEL_MAP[severity], '%s', formatter.call(severity, Time.now, progname, (message || block.call)) 191 true 192 end 193end 194 195