summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mailman/Logging/.cvsignore1
-rw-r--r--Mailman/Logging/Logger.py79
-rw-r--r--Mailman/Logging/Makefile.in69
-rw-r--r--Mailman/Logging/MultiLogger.py69
-rw-r--r--Mailman/Logging/StampedLogger.py82
-rw-r--r--Mailman/Logging/Utils.py24
-rw-r--r--Mailman/Logging/__init__.py0
7 files changed, 324 insertions, 0 deletions
diff --git a/Mailman/Logging/.cvsignore b/Mailman/Logging/.cvsignore
new file mode 100644
index 000000000..f3c7a7c5d
--- /dev/null
+++ b/Mailman/Logging/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/Mailman/Logging/Logger.py b/Mailman/Logging/Logger.py
new file mode 100644
index 000000000..8a111940a
--- /dev/null
+++ b/Mailman/Logging/Logger.py
@@ -0,0 +1,79 @@
+# Copyright (C) 1998 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""File-based logger, writes to named category files in mm_cfg.LOG_DIR."""
+
+import sys
+import os
+import Mailman.mm_cfg
+from Mailman.Logging.Utils import __logexc
+
+
+class Logger:
+ def __init__(self, category, nofail=1):
+ """Nofail (by default) says to fallback to sys.stderr if write
+ fails to category file. A message is emitted, but the IOError is
+ caught. Set nofail=0 if you want to handle the error in your code,
+ instead.
+ """
+ self.__filename = os.path.join(Mailman.mm_cfg.LOG_DIR, category)
+ self.__fp = None
+ self.__nofail = nofail
+
+ def __del__(self):
+ self.close()
+
+ def __repr__(self):
+ return '<Logger to file: %s>' % self.__filename
+
+ def __get_f(self):
+ if self.__fp:
+ return self.__fp
+ else:
+ try:
+ ou = os.umask(002)
+ try:
+ f = self.__fp = open(self.__filename, 'a+')
+ finally:
+ os.umask(ou)
+ except IOError, msg:
+ if self.__nofail:
+ __logexc(self, msg)
+ else:
+ # re-raise the original exception
+ raise
+ return f
+
+ def flush(self):
+ f = self.__get_f()
+ if hasattr(f, 'flush'):
+ f.flush()
+
+ def write(self, msg):
+ f = self.__get_f()
+ try:
+ f.write(msg)
+ except IOError, msg:
+ __logexc(self, msg)
+
+ def writelines(self, lines):
+ for l in lines:
+ self.write(l)
+
+ def close(self):
+ if not self.__fp:
+ return
+ self.__get_f().close()
diff --git a/Mailman/Logging/Makefile.in b/Mailman/Logging/Makefile.in
new file mode 100644
index 000000000..8a11e0799
--- /dev/null
+++ b/Mailman/Logging/Makefile.in
@@ -0,0 +1,69 @@
+# Copyright (C) 1998 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# NOTE: Makefile.in is converted into Makefile by the configure script
+# in the parent directory. Once configure has run, you can recreate
+# the Makefile by running just config.status.
+
+# Variables set by configure
+
+VERSION= @VERSION@
+
+VPATH= @srcdir@
+srcdir= @srcdir@
+bindir= @bindir@
+prefix= @prefix@
+exec_prefix= @exec_prefix@
+
+CC= @CC@
+CHMOD= @CHMOD@
+INSTALL= @INSTALL@
+
+DEFS= @DEFS@
+
+# Customizable but not set by configure
+
+OPT= @OPT@
+CFLAGS= $(OPT) $(DEFS)
+PACKAGEDIR= $(prefix)/Mailman/Logging
+SHELL= /bin/sh
+
+MODULES= __init__.py Logger.py MultiLogger.py StampedLogger.py \
+Utils.py
+
+# Modes for directories and executables created by the install
+# process. Default to group-writable directories but
+# user-only-writable for executables.
+DIRMODE= 775
+EXEMODE= 755
+FILEMODE= 644
+INSTALL_PROGRAM=$(INSTALL) -m $(EXEMODE)
+
+
+# Rules
+
+all:
+
+install:
+ for f in $(MODULES); \
+ do \
+ $(INSTALL) -m $(FILEMODE) $$f $(PACKAGEDIR); \
+ done
+
+clean:
+
+distclean:
+ -rm Makefile
diff --git a/Mailman/Logging/MultiLogger.py b/Mailman/Logging/MultiLogger.py
new file mode 100644
index 000000000..728c5c7de
--- /dev/null
+++ b/Mailman/Logging/MultiLogger.py
@@ -0,0 +1,69 @@
+# Copyright (C) 1998 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""A mutiple sink logger. Any message written goes to all sub-loggers."""
+
+import sys
+from Mailman.Logging.Utils import __logexc
+
+
+
+class MultiLogger:
+ def __init__(self, *args):
+ self.__loggers = []
+ for logger in args:
+ self.__loggers.append(logger)
+
+ def add_logger(self, logger):
+ if logger not in self.__loggers:
+ self.__loggers.append(logger)
+
+ def del_logger(self, logger):
+ if logger in self.__loggers:
+ self.__loggers.remove(logger)
+
+ def write(self, msg):
+ for logger in self.__loggers:
+ # you want to be sure that a bug in one logger doesn't prevent
+ # logging to all the other loggers
+ try:
+ logger.write(msg)
+ except:
+ __logexc(logger, msg)
+
+ def writelines(self, lines):
+ for line in lines:
+ self.write(line)
+
+ def flush(self):
+ for logger in self.__loggers:
+ if hasattr(logger, 'flush'):
+ # you want to be sure that a bug in one logger doesn't prevent
+ # logging to all the other loggers
+ try:
+ logger.flush()
+ except:
+ __logexc(logger)
+
+ def close(self):
+ for logger in self.__loggers:
+ # you want to be sure that a bug in one logger doesn't prevent
+ # logging to all the other loggers
+ try:
+ if logger <> sys.__stderr__ and logger <> sys.__stdout__:
+ logger.close()
+ except:
+ __logexc(logger)
diff --git a/Mailman/Logging/StampedLogger.py b/Mailman/Logging/StampedLogger.py
new file mode 100644
index 000000000..a7a9d9b65
--- /dev/null
+++ b/Mailman/Logging/StampedLogger.py
@@ -0,0 +1,82 @@
+# Copyright (C) 1998 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import time
+from Mailman.Logging.Logger import Logger
+
+class StampedLogger(Logger):
+ """Record messages in log files, including date stamp and optional label.
+
+ If manual_reprime is on (off by default), then timestamp prefix will
+ included only on first .write() and on any write immediately following a
+ call to the .reprime() method. This is useful for when StampedLogger is
+ substituting for sys.stderr, where you'd like to see the grouping of
+ multiple writes under a single timestamp (and there is often is one group,
+ for uncaught exceptions where a script is bombing).
+
+ In any case, the identifying prefix will only follow writes that start on
+ a new line.
+
+ Nofail (by default) says to fallback to sys.stderr if write fails to
+ category file. A message is emitted, but the IOError is caught.
+ Initialize with nofail=0 if you want to handle the error in your code,
+ instead.
+
+ """
+ def __init__(self, category, label=None, manual_reprime=0, nofail=1):
+ "If specified, optional label is included after timestamp."
+ self.__label = label
+ self.__manual_reprime = manual_reprime
+ self.__primed = 1
+ self.__bol = 1
+ Logger.__init__(self, category, nofail=nofail)
+
+ def reprime(self):
+ """Reset so timestamp will be included with next write."""
+ self.__primed = 1
+
+ def write(self, msg):
+ if not self.__bol:
+ prefix = ""
+ else:
+ if not self.__manual_reprime or self.__primed:
+ stamp = time.strftime("%b %d %H:%M:%S %Y ",
+ time.localtime(time.time()))
+ self.__primed = 0
+ else:
+ stamp = ""
+ if self.__label == None:
+ label = ""
+ else:
+ label = "%s:" % self.__label
+ prefix = stamp + label
+ Logger.write(self, "%s %s" % (prefix, msg))
+ if msg and msg[-1] == '\n':
+ self.__bol = 1
+ else:
+ self.__bol = 0
+
+ def writelines(self, lines):
+ first = 1
+ for l in lines:
+ if first:
+ self.write(l)
+ first = 0
+ else:
+ if l and l[0] not in [' ', '\t', '\n']:
+ Logger.write(self, ' ' + l)
+ else:
+ Logger.write(self, l)
diff --git a/Mailman/Logging/Utils.py b/Mailman/Logging/Utils.py
new file mode 100644
index 000000000..aba3d389d
--- /dev/null
+++ b/Mailman/Logging/Utils.py
@@ -0,0 +1,24 @@
+# Copyright (C) 1998 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import sys
+import traceback
+
+
+def __logexc(logger=None, msg=''):
+ sys.__stderr__.write('Logging error: %s\n' % logger)
+ traceback.print_exc(file=sys.__stderr__)
+ sys.__stderr__.write('Original log message:\n%s\n' % msg)
diff --git a/Mailman/Logging/__init__.py b/Mailman/Logging/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Mailman/Logging/__init__.py