diff options
Diffstat (limited to 'demo/medusa054/logger.py')
-rw-r--r-- | demo/medusa054/logger.py | 261 |
1 files changed, 0 insertions, 261 deletions
diff --git a/demo/medusa054/logger.py b/demo/medusa054/logger.py deleted file mode 100644 index d131ab5..0000000 --- a/demo/medusa054/logger.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- Mode: Python -*- - -import asynchat -import socket -import time # these three are for the rotating logger -import os # | -import stat # v - -# -# three types of log: -# 1) file -# with optional flushing. Also, one that rotates the log. -# 2) socket -# dump output directly to a socket connection. [how do we -# keep it open?] -# 3) syslog -# log to syslog via tcp. this is a per-line protocol. -# - -# -# The 'standard' interface to a logging object is simply -# log_object.log (message) -# - -# a file-like object that captures output, and -# makes sure to flush it always... this could -# be connected to: -# o stdio file -# o low-level file -# o socket channel -# o syslog output... - -class file_logger: - - # pass this either a path or a file object. - def __init__ (self, file, flush=1, mode='a'): - if type(file) == type(''): - if (file == '-'): - import sys - self.file = sys.stdout - else: - self.file = open (file, mode) - else: - self.file = file - self.do_flush = flush - - def __repr__ (self): - return '<file logger: %s>' % self.file - - def write (self, data): - self.file.write (data) - self.maybe_flush() - - def writeline (self, line): - self.file.writeline (line) - self.maybe_flush() - - def writelines (self, lines): - self.file.writelines (lines) - self.maybe_flush() - - def maybe_flush (self): - if self.do_flush: - self.file.flush() - - def flush (self): - self.file.flush() - - def softspace (self, *args): - pass - - def log (self, message): - if message[-1] not in ('\r', '\n'): - self.write (message + '\n') - else: - self.write (message) - -# like a file_logger, but it must be attached to a filename. -# When the log gets too full, or a certain time has passed, -# it backs up the log and starts a new one. Note that backing -# up the log is done via "mv" because anything else (cp, gzip) -# would take time, during which medusa would do nothing else. - -class rotating_file_logger (file_logger): - - # If freq is non-None we back up "daily", "weekly", or "monthly". - # Else if maxsize is non-None we back up whenever the log gets - # to big. If both are None we never back up. - def __init__ (self, file, freq=None, maxsize=None, flush=1, mode='a'): - self.filename = file - self.mode = mode - self.file = open (file, mode) - self.freq = freq - self.maxsize = maxsize - self.rotate_when = self.next_backup(self.freq) - self.do_flush = flush - - def __repr__ (self): - return '<rotating-file logger: %s>' % self.file - - # We back up at midnight every 1) day, 2) monday, or 3) 1st of month - def next_backup (self, freq): - (yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) - if freq == 'daily': - return time.mktime((yr,mo,day+1, 0,0,0, 0,0,-1)) - elif freq == 'weekly': - return time.mktime((yr,mo,day-wd+7, 0,0,0, 0,0,-1)) # wd(monday)==0 - elif freq == 'monthly': - return time.mktime((yr,mo+1,1, 0,0,0, 0,0,-1)) - else: - return None # not a date-based backup - - def maybe_flush (self): # rotate first if necessary - self.maybe_rotate() - if self.do_flush: # from file_logger() - self.file.flush() - - def maybe_rotate (self): - if self.freq and time.time() > self.rotate_when: - self.rotate() - self.rotate_when = self.next_backup(self.freq) - elif self.maxsize: # rotate when we get too big - try: - if os.stat(self.filename)[stat.ST_SIZE] > self.maxsize: - self.rotate() - except os.error: # file not found, probably - self.rotate() # will create a new file - - def rotate (self): - (yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) - try: - self.file.close() - newname = '%s.ends%04d%02d%02d' % (self.filename, yr, mo, day) - try: - open(newname, "r").close() # check if file exists - newname = newname + "-%02d%02d%02d" % (hr, min, sec) - except: # YEARMODY is unique - pass - os.rename(self.filename, newname) - self.file = open(self.filename, self.mode) - except: - pass - -# syslog is a line-oriented log protocol - this class would be -# appropriate for FTP or HTTP logs, but not for dumping stderr to. - -# TODO: a simple safety wrapper that will ensure that the line sent -# to syslog is reasonable. - -# TODO: async version of syslog_client: now, log entries use blocking -# send() - -import m_syslog -syslog_logger = m_syslog.syslog_client - -class syslog_logger (m_syslog.syslog_client): - def __init__ (self, address, facility='user'): - m_syslog.syslog_client.__init__ (self, address) - self.facility = m_syslog.facility_names[facility] - self.address=address - - def __repr__ (self): - return '<syslog logger address=%s>' % (repr(self.address)) - - def log (self, message): - m_syslog.syslog_client.log ( - self, - message, - facility=self.facility, - priority=m_syslog.LOG_INFO - ) - -# log to a stream socket, asynchronously - -class socket_logger (asynchat.async_chat): - - def __init__ (self, address): - - if type(address) == type(''): - self.create_socket (socket.AF_UNIX, socket.SOCK_STREAM) - else: - self.create_socket (socket.AF_INET, socket.SOCK_STREAM) - - self.connect (address) - self.address = address - - def __repr__ (self): - return '<socket logger: address=%s>' % (self.address) - - def log (self, message): - if message[-2:] != '\r\n': - self.socket.push (message + '\r\n') - else: - self.socket.push (message) - -# log to multiple places -class multi_logger: - def __init__ (self, loggers): - self.loggers = loggers - - def __repr__ (self): - return '<multi logger: %s>' % (repr(self.loggers)) - - def log (self, message): - for logger in self.loggers: - logger.log (message) - -class resolving_logger: - """Feed (ip, message) combinations into this logger to get a - resolved hostname in front of the message. The message will not - be logged until the PTR request finishes (or fails).""" - - def __init__ (self, resolver, logger): - self.resolver = resolver - self.logger = logger - - class logger_thunk: - def __init__ (self, message, logger): - self.message = message - self.logger = logger - - def __call__ (self, host, ttl, answer): - if not answer: - answer = host - self.logger.log ('%s:%s' % (answer, self.message)) - - def log (self, ip, message): - self.resolver.resolve_ptr ( - ip, - self.logger_thunk ( - message, - self.logger - ) - ) - -class unresolving_logger: - "Just in case you don't want to resolve" - def __init__ (self, logger): - self.logger = logger - - def log (self, ip, message): - self.logger.log ('%s:%s' % (ip, message)) - - -def strip_eol (line): - while line and line[-1] in '\r\n': - line = line[:-1] - return line - -class tail_logger: - "Keep track of the last <size> log messages" - def __init__ (self, logger, size=500): - self.size = size - self.logger = logger - self.messages = [] - - def log (self, message): - self.messages.append (strip_eol (message)) - if len (self.messages) > self.size: - del self.messages[0] - self.logger.log (message) |