bitkeeper revision 1.1108.1.8 (40ffc44fV2fs0W-8bRw5B0XcBdmAsw)

Add python 2.3 logging to the tree. Only install
if not present. Convert xend to use logging.
This commit is contained in:
mjw@wray-m-3.hpl.hp.com committed 2004-07-22 13:42:39 +00:00
1 parent 6d88c800d3
commit 5b14d2aca3
63 files changed
+10896 -63

No files matched your search

+52
View File
@@ -311,6 +311,57 @@
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops.py
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
40ffc44dOwe1CcYXGCkYHdG_NxcccA tools/python/logging/logging-0.4.9.2/PKG-INFO
40ffc44dpqpgqgrnLfR70PsiBc3liA tools/python/logging/logging-0.4.9.2/README.txt
40ffc44ddfLckno4Gvzi3vZxwelZHQ tools/python/logging/logging-0.4.9.2/default.css
40ffc44dKSkczdvpd_x7rWGH4_BRIQ tools/python/logging/logging-0.4.9.2/liblogging.tex
40ffc44d2O51abh5t-1VTZfqhbS1ZQ tools/python/logging/logging-0.4.9.2/logging/__init__.py
40ffc44dT8ustodG0hDjYMCzQ8UCbA tools/python/logging/logging-0.4.9.2/logging/config.py
40ffc44dqbwdCcq6XgwpTvrUrABhhw tools/python/logging/logging-0.4.9.2/logging/handlers.py
40ffc44dVEL3QwvZx_Rcl3d41WxMRQ tools/python/logging/logging-0.4.9.2/python_logging.html
40ffc44dXypIfRTyuTD48cN0o-gAXg tools/python/logging/logging-0.4.9.2/setup.py
40ffc44dqqdkY-Ox_eoPuNmQR0_ebw tools/python/logging/logging-0.4.9.2/test/app.py
40ffc44d9vEJEV_44B-23sJHkT1-gA tools/python/logging/logging-0.4.9.2/test/critical.ini
40ffc44dA5BiSVip8DlCh0DfAaQzbg tools/python/logging/logging-0.4.9.2/test/debug.ini
40ffc44dAuxUnJx7Fu2puaiNheBRkg tools/python/logging/logging-0.4.9.2/test/error.ini
40ffc44dkAIw1gbAzj_XiQyoru93_Q tools/python/logging/logging-0.4.9.2/test/events.xml
40ffc44eZwnQ4wGs1zVaAGsnEoyz6Q tools/python/logging/logging-0.4.9.2/test/log_test.py
40ffc44epbz06Y2nCkuYotfQFY4bJQ tools/python/logging/logging-0.4.9.2/test/log_test0.py
40ffc44eVNdi9lXQOZ2n7yT1DXVQRQ tools/python/logging/logging-0.4.9.2/test/log_test1.py
40ffc44eeqydHPpipbO4oVhRt90v0A tools/python/logging/logging-0.4.9.2/test/log_test10.py
40ffc44eSum6e6Y_sh7hRBHnnRurfw tools/python/logging/logging-0.4.9.2/test/log_test11.py
40ffc44euWPhfnbZw64ShBIrZot84A tools/python/logging/logging-0.4.9.2/test/log_test12.py
40ffc44ekj8Hdg-2SLb0qdqJzGkXdA tools/python/logging/logging-0.4.9.2/test/log_test13.py
40ffc44e5DnmO4OEa54mS8Q9AgP3rg tools/python/logging/logging-0.4.9.2/test/log_test14.py
40ffc44e6uWMQdikNEzYeNeFewGQew tools/python/logging/logging-0.4.9.2/test/log_test15.py
40ffc44eHJ_XsDp2Le-qc96G2n7GdQ tools/python/logging/logging-0.4.9.2/test/log_test16.py
40ffc44eCIq8wSc2UI16VfkLPlW-SQ tools/python/logging/logging-0.4.9.2/test/log_test17.py
40ffc44eHWycPlgiEpt8pE8xYTbUkg tools/python/logging/logging-0.4.9.2/test/log_test18.py
40ffc44eeRuZcrB3tQzfrQnh22NBow tools/python/logging/logging-0.4.9.2/test/log_test19.py
40ffc44e6jQPP-ASsVux4-ERGuDrmQ tools/python/logging/logging-0.4.9.2/test/log_test2.py
40ffc44eNHf6r77J1VCNedKPTufY8Q tools/python/logging/logging-0.4.9.2/test/log_test20.py
40ffc44emS2gplqyEwbcLS43QNrnyA tools/python/logging/logging-0.4.9.2/test/log_test21.py
40ffc44e1Ojd79zACM2KAnXZyO3Nuw tools/python/logging/logging-0.4.9.2/test/log_test22.py
40ffc44ektXcwDnK4h4HqMHFSTA3BA tools/python/logging/logging-0.4.9.2/test/log_test3.ini
40ffc44e8ka-b5_nPYzWn0hXDSagMw tools/python/logging/logging-0.4.9.2/test/log_test3.py
40ffc44eVmFkQt7FaHxspmMV7IZLxw tools/python/logging/logging-0.4.9.2/test/log_test4.py
40ffc44eYJ7tjlUpS5bIF9I8YKK39g tools/python/logging/logging-0.4.9.2/test/log_test5.py
40ffc44eo9GvB3GvC2Aoaxu74ffS4A tools/python/logging/logging-0.4.9.2/test/log_test6.py
40ffc44eajjKGx6tj2nOVuYCfy-PoA tools/python/logging/logging-0.4.9.2/test/log_test7.py
40ffc44eEM_uMfIGRNoxRSP7_jpc7w tools/python/logging/logging-0.4.9.2/test/log_test8.py
40ffc44e4NBnAweOds3owURsSHZKyQ tools/python/logging/logging-0.4.9.2/test/log_test9.py
40ffc44eu_SYlzJ464qUFb8fdSGHsg tools/python/logging/logging-0.4.9.2/test/logconf.ini
40ffc44eTnvlvCSmjgGgfcOBm6SSAw tools/python/logging/logging-0.4.9.2/test/logconf.py
40ffc44egchRehfcmsPX0WdV06yp_w tools/python/logging/logging-0.4.9.2/test/logging.dtd
40ffc44ee9peTFswy96mwgBslmqEvQ tools/python/logging/logging-0.4.9.2/test/logging.xml
40ffc44ekRTWScJDGTe7k2aAp_ltRg tools/python/logging/logging-0.4.9.2/test/logrecv.ini
40ffc44eeQBA_QbbwrucZfYtksuEMA tools/python/logging/logging-0.4.9.2/test/logrecv.py
40ffc44eECASCQD_QL3wJd4dyK2KVg tools/python/logging/logging-0.4.9.2/test/myapp.py
40ffc44eUwKMOAwPTIBq0A8N8b56HQ tools/python/logging/logging-0.4.9.2/test/mymodule.py
40ffc44evyvayldKLSsizMmsDpBtkQ tools/python/logging/logging-0.4.9.2/test/stderr.exp
40ffc44eb-39RIR551oZoTiK11amSw tools/python/logging/logging-0.4.9.2/test/stdout.exp
40ffc44eGvzBilqBZEozKaMHz-HdxA tools/python/logging/logging-0.4.9.2/test/warn.ini
40ffc44eLXLuINsYi8eG0oJ6a2dSRA tools/python/logging/setup.py
40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/python/setup.py
40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/python/xen/__init__.py
40dfd40aMOhnw_cQLve9462UR5yYxQ tools/python/xen/lowlevel/__init__.py
@@ -336,6 +387,7 @@
40c9c468bbKq3uC7_fuNUkiMMjArdw tools/python/xen/xend/XendDomainConfig.py
40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
40f50d99YiiaMI1fZBh1VCDFLD57qg tools/python/xen/xend/XendError.py
40ffc44eGsgTEY355E3nN4mPLZHhMQ tools/python/xen/xend/XendLogging.py
40c9c46854nsHmuxHQHncKk5rAs5NA tools/python/xen/xend/XendMigrate.py
40c9c468M96gA1EYDvNa5w5kQNYLFA tools/python/xen/xend/XendNode.py
40c9c4686jruMyZIqiaZRMiMoqMJtg tools/python/xen/xend/XendRoot.py
@@ -0,0 +1,25 @@
Metadata-Version: 1.0
Name: logging
Version: 0.4.9.2
Summary: A logging module for Python
Home-page: http://www.red-dove.com/python_logging.html
Author: Vinay Sajip
Author-email: vinay_sajip@red-dove.com
License: Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Vinay Sajip
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Description: This module is intended to provide a standard error logging mechanism in Python as per PEP 282.
Platform: UNKNOWN
@@ -0,0 +1,311 @@
This module is intended to provide error logging functionality for Python
programs. It aims to be aligned with Python Enhancement Proposal (PEP) 282.
For more information on the package itself, see python_logging.html. In it,
there is a description of each file in the distribution.
You can also use pydoc to browse the interfaces.
Change History
--------------
Version Date Description
=============================================================================
0.4.9.2 28 Feb 2004 Traceback text is now cached.
Tracebacks can be propagated across sockets as text.
Added makeLogRecord() to allow a LogRecord to be
created from a dictionary.
Closing a handler now removes it from the internal list
used by shutdown().
Made close() call flush() for handlers where this makes
sense (thanks to Jim Jewett).
The exc_info keyword parameter can be used to pass an
exception tuple as well as a flag indicating that the
current exception should be logged.
A shutdown hook is registered to call shutdown() on
application (Python) exit (thanks to Jim Jewett).
Removed redundant error check in setLoggerClass().
Added RESET_ERROR to logging.config.
SocketHandler now uses an exponential backoff strategy
(thanks to Robert Olson).
Minor documentation corrections.
-----------------------------------------------------------------------------
0.4.8 22 Apr 2003 Made _listener global in stopListening().
Made listen() correctly pass the specified port.
Removed some redundant imports in __init__.py.
Added the record being processed as a parameter to
handleError (thanks to Gordon den Otter for the idea).
Handler.handle returns the result of applying the
filter to the record (thanks to Gordon den Otter for
the idea).
Added a seek(0, 2) in RotatingFileHandler before the
tell() call. This is because under Windows, tell()
returns 0 until the first actual write (thanks to
Gordon den Otter for the patch).
Altered findCaller to not use inspect (thanks to
Jeremy Hylton for the patch).
Renamed warn and WARN to warning and WARNING. This may
break existing code, but the standard Python module
will use warning/WARNING rather than warn/WARN. The
fatal and FATAL synonyms for critical and CRITICAL
have also been removed.
Added defaultEncoding and some support for encoding
Unicode messages (thanks to Stéphane Bidoul for the
suggestion).
Added process ID to the list of LogRecord attributes.
Modified Logger.removeHandler so that it does not
close the handler on removal.
Modified SMTPHandler to treat a single "to address"
correctly (thanks to Anthony Baxter).
Modified SMTPHandler to add a date header to the SMTP
message (thanks to David Driver for the suggestion).
Modified HTTPHandler to factor out the mapping of
a LogRecord to a dictionary (thanks to Franz Glasner
for the patch).
-----------------------------------------------------------------------------
0.4.7 15 Nov 2002 Made into a package with three modules: __init__ (the
core code), handlers (all handlers other than
FileHandler and its bases) and config (all the config
stuff). Before doing this:
Updated docstrings to include a short line, then a
blank line, then more descriptive text.
Renamed 'lvl' to 'level' in various functions.
Changed FileHandler to use "a" and "w" instead of "a+"
and "w+".
Moved log file rotation functionality from FileHandler
to a new class RotatingFileHandler.
Improved docstring describing rollover.
Updated makePickle to use 4-byte length and struct
module, likewise logrecv.py. Also updated on-the-fly
config reader to use 4-byte length/struct module.
Altered ConfigParser test to look at 'readline' rather
than 'read'.
Added optional "defaults" argument to fileConfig, to
be passed to ConfigParser.
Renamed ALL to NOTSET to avoid confusion.
Commented out getRootLogger(), as obsolete.
To do regression testing, run log_test.py and compare
the created files stdout.log and stderr.log against
the files stdout.exp and stderr.exp. They should match
except fir a couple of exception messages which give
absolute file paths.
Updated python_logging.html to remove links to
logging_pydoc.html, which has been removed from the
distribution.
Changed default for raiseExceptions to 1.
-----------------------------------------------------------------------------
0.4.6 08 Jul 2002 Added raiseExceptions to allow conditional propagation
of exceptions which occur during handling.
Added converter to Formatter to allow use of any
function to convert time from seconds to a tuple. It
still defaults to time.localtime but now you can also
use time.gmtime.
Added log_test22.py to test the conversion feature.
Changed rootlogger default level to WARN - was DEBUG.
Updated some docstrings.
Moved import of threading to where thread is imported.
If either is unavailable, threading support is off.
Updated minor defects in python_logging.html.
Check to see if ConfigParser has readfp method; if it
does and an object with a 'read' method is passed in,
assumes a file-like object and uses readfp to read it
in.
-----------------------------------------------------------------------------
0.4.5 04 Jun 2002 Fixed bug which caused problem if no args to message
(suggested by Hye-Shik Chang).
Fixed bug in _fixupParents (thanks to Nicholas Veeser)
and added log_test19.py as a test case for this bug.
Added getMessage to LogRecord (code was moved here from
Formatter.format)
Applied str() to record.msg to allow arbitrary classes
to determine the formatting (as msg can now be a class
instance).
Table of Contents added to python_logging.html, the
section on Loggers updated, and the logconf.ini file
section annotated.
Added log_test20.py which demonstrates how to use
class instances to provide alternatives to numeric
severities as mechanisms for control of logging.
Added log_test21.py which builds on log_test20.py to
show how you can use a regular expression-based Filter
for flexible matching similar to e.g. Protomatter
Syslog, where you can filter on e.g. "a.*" or "*.b" or
"a.*.c".
_levelNames changed to contain reverse mappings as well
as forward mappings (leveltext->level as well as level
-> leveltext). The reverse mappings are used by
fileConfig().
fileConfig() now more forgiving of missing options in
.ini file - sensible defaults now used when some
options are absent. Also, eval() is used less when
interpreting .ini file contents - int() and dict lookup
are used in more places.
-----------------------------------------------------------------------------
0.4.4 02 May 2002 getEffectiveLevel() returns ALL instead of None when
nothing found. Modified references to level=0 to
level=ALL in a couple of places.
SocketHandler now inherits from Handler (it used to
inherit from StreamHandler, for no good reason).
getLock() renamed to createLock().
Docstring tidy-ups, and some tidying up of
DatagramHandler.
Factored out unpickling in logrecv.py.
Added log_test18.py to illustrate MatchFilter, which is
a general matching filter.
Improved FileHandler.doRollover() so that the base
file name is always the most recent, then .1, then .2
etc. up to the maximum backup count. Renamed formal
args and attributes used in rollover.
Changed LogRecord attributes lvl -> levelno, level ->
levelname (less ambiguity)
Formatter.format searches for "%(asctime)" rather than
"(asctime)"
Renamed _start_time to _startTime
Formatter.formatTime now returns the time
Altered logrecv.py to support stopping servers
programmatically
Added log_test.py as overall test harness
basicConfig() can now be safely called more than once
Modified test scripts to make it easier to call them
from log_test.py
Moved SOAPHandler from core to log_test13.py. It's not
general enough to be in the core; most production use
will have differing RPC signatures.
-----------------------------------------------------------------------------
0.4.3 14 Apr 2002 Bug fix one-off error message to go to sys.stderr
rather than sys.stdout.
logrecv.py fix TCP for busy network.
Thread safety - added locking to Handler and for shared
data in module, and log_test16.py to test it.
Added socket listener to allow on-the-fly configuration
and added log_test17.py to test it.
-----------------------------------------------------------------------------
0.4.2 11 Apr 2002 Bug fix fileConfig() - setup of MemoryHandler target
and errors when loggers have no handlers set or
handlers have no formatters set
logconf.py - seems to hang if window closed when combo
dropdown is showing - added code to close popup on exit
Some tweaks to _srcfile computation (normpath added)
findCaller() optimized, now a lot faster!
Logger.removeHandler now closes the handler before
removing it
fileConfig() removes existing handlers before adding
the new set, to avoid memory leakage when repeated
calls are made
Fixed logrecv.py bug which hogged CPU time when TCP
connection was closed from the client
Added log_test14.py to demonstrate/test a DBHandler
which writes logging records into an RDBMS using the
Python Database API 2.0 (to run, you need something
which supports this already installed - I tested with
mxODBC)
Made getLogger name argument optional - returns root
logger if omitted
Altered Filter to take a string initializer, filtering
a sub-hierarchy rooted at a particular point (idea from
Denis S. Otkidach).
Added log_test15.py to test Filter initializer
Minor docstring changes
-----------------------------------------------------------------------------
0.4.1 03 Apr 2002 Bug fix SMTPHandler - extra \r\n needed (Oleg Orlov)
Added BufferingHandler, BufferingFormatter
Renamed getChainedPriority to getEffectiveLevel
Removed Logger.getRoot as it is redundant
Added log_test9.py to test Buffering classes and
to show an XMLFormatter example.
Added setLoggerClass.
Added log_test10.py to test setLoggerClass, using an
example Logger-derived class which outputs exception
info even for DEBUG level logging calls
Added log_test11.py to test a buffering implementation
of SMTPHandler
Changed logging call implementation to allow keyword
arguments (Kevin Butler and others)
Changed default SysLogHandler implementation.
Renamed "additive" to "propagate" as it better
describes the attribute.
Added HTTPHandler.
Modified logrecv.py to remove "both" option and to add
"HTTP" and "SOAP" options (SOAP option needs you to
have PyXML-0.6.6 and ZSI installed - for logrecv.py
only, and not for the core logging module itself).
Added log_test12.py to test HTTPHandler.
Added log_test13.py to test SOAPHandler.
Formatted to Python source guidelines (spaces, indent
of 4, within 80 columns).
More method renamings (result of feedback) - _handle()
renamed to emit(), _logRecord() renamed to handle().
Renamed FATAL to CRITICAL (David Goodger), but left
fatal() and FATAL in (until PEP is changed)
Changed configuration file format to ConfigParser
format.
Factored filter application functionality out to a new
Filterer class. The isLoggable() method is renamed to
filter() in both Filter and Filterer classes.
Altered SMTPHandler __init__ to accept (host, port)
for the mail internet address.
Added GUI configurator which uses Tkinter and the new
configuration file format. (See logconf.py and an
example configuration file in logconf.ini)
Altered log_test3.py to test with the new file format.
-----------------------------------------------------------------------------
0.4 21 Mar 2002 Incorporated comments/patches from Ollie Rutherfurd:
-Added level filtering for handlers.
-Return root logger if no name specified in getLogger.
Incorporated comments from Greg Ward:
-Added distutils setup.py script.
Added formatter initialization in Handler.__init__.
Tidied up docstrings.
Added removeHandler to Logger.
Added removeFilter to Logger and Handler.
logrecv.py modified to keep connection alive until
client closes it.
SocketHandler modified to not reset connection after
each logging event.
Added shutdown function which closes open sockets
Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT
Added DEFAULT_UDP_LOGGING_PORT
Added log_test4.py (example of arbitrary levels)
Added addLevelName, changed behaviour of getLevelName
Fixed bugs in DatagramHandler
Added SMTPHandler implementation
Added log_test5.py to test SMTPHandler
Added SysLogHandler (contribution from Nicolas Untz
based on Sam Rushing's syslog.py)
Modified log_test1.py to add a SysLogHandler
Added rollover functionality to FileHandler
Added NTEventLogHandler (based on Win32 extensions)
Added MemoryHandler implementation
Added log_test7.py to test MemoryHandler
Added log_test8.py to test FileHandler rollover
Added logException method to Logger
Added formatException method to Formatter
Added log_test6.py to test NTEventHandler and
logException
Numerous internal method renamings (sorry - but better
to do this now, rather than when we enter beta status).
-----------------------------------------------------------------------------
0.3 14 Mar 2002 First public release, for early feedback
-----------------------------------------------------------------------------
0.2 Consolidated into single file (for internal use only)
-----------------------------------------------------------------------------
0.1 Initial implementation (for internal use only)
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
COPYRIGHT
-----------------------------------------------------------------------------
Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Vinay Sajip
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,32 @@
BODY, P, UL, OL {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; background: white; color: black; font-size: 10pt; }
CODE {font-family: "Courier New", Courier, Monaco, monospace ; }
PRE {font-family: "Courier New", Courier, Monaco, monospace ; }
.program { color: navy; font-family: "Courier New", Courier, Monaco, monospace }
.output { color: maroon }
HR {color: gray ; }
.navbar { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; background: #FFFF66 ; border-style: none none solid none; border-width: thin; padding: 2px;}
.navarea { background: #FFFF66 ; }
TR { font-size: 10pt }
.red { color: #FF0000 }
.maroon { color: #800000 }
.comment { color: green }
.optional { color: silver }
.strong { font-weight: bold }
TR.tblheading { background: silver ; }
.notrecommended {color: #666666 ; }
.deemphasized {color: #666666 ; }
TABLE.densetable {font-size: 80% ; }
TH { text-align: left; background: silver }
TR.summaryrow { font-size: 90%; background: #00FFFF ; }
CAPTION {font-size: 100% ; }
.embeddedfloat {float: right; margin-left: 3em}
.bigtd { font-size: 18pt }
TD, .normaltd { vertical-align: top; background: #EEEEEE; font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt }
H1, H2, H3, H4, H5, H6 {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; }
H4 {margin-bottom: 0.5em }
H5, H6 {margin-bottom: 0.1em }
A:link {color: blue ; }
A:visited {color: purple ; }
A:active {color: red ; }
A { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt }
.warning { color: red }
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,301 @@
# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""
Configuration functions for the logging package for Python. The core package
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
by Apache's log4j system.
Should work under Python versions >= 1.5.2, except that source line
information is not available unless 'sys._getframe()' is.
Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
To use, simply 'import logging' and log away!
"""
import sys, logging, logging.handlers, string, thread, threading, socket, struct, os
from SocketServer import ThreadingTCPServer, StreamRequestHandler
DEFAULT_LOGGING_CONFIG_PORT = 9030
if sys.platform == "win32":
RESET_ERROR = 10054 #WSAECONNRESET
else:
RESET_ERROR = 104 #ECONNRESET
#
# The following code implements a socket listener for on-the-fly
# reconfiguration of logging.
#
# _listener holds the server object doing the listening
_listener = None
def fileConfig(fname, defaults=None):
"""
Read the logging configuration from a ConfigParser-format file.
This can be called several times from an application, allowing an end user
the ability to select from various pre-canned configurations (if the
developer provides a mechanism to present the choices and load the chosen
configuration).
In versions of ConfigParser which have the readfp method [typically
shipped in 2.x versions of Python], you can pass in a file-like object
rather than a filename, in which case the file-like object will be read
using readfp.
"""
import ConfigParser
cp = ConfigParser.ConfigParser(defaults)
if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
cp.readfp(fname)
else:
cp.read(fname)
#first, do the formatters...
flist = cp.get("formatters", "keys")
if len(flist):
flist = string.split(flist, ",")
formatters = {}
for form in flist:
sectname = "formatter_%s" % form
opts = cp.options(sectname)
if "format" in opts:
fs = cp.get(sectname, "format", 1)
else:
fs = None
if "datefmt" in opts:
dfs = cp.get(sectname, "datefmt", 1)
else:
dfs = None
f = logging.Formatter(fs, dfs)
formatters[form] = f
#next, do the handlers...
#critical section...
logging._acquireLock()
try:
try:
#first, lose the existing handlers...
logging._handlers.clear()
#now set up the new ones...
hlist = cp.get("handlers", "keys")
if len(hlist):
hlist = string.split(hlist, ",")
handlers = {}
fixups = [] #for inter-handler references
for hand in hlist:
sectname = "handler_%s" % hand
klass = cp.get(sectname, "class")
opts = cp.options(sectname)
if "formatter" in opts:
fmt = cp.get(sectname, "formatter")
else:
fmt = ""
klass = eval(klass, vars(logging))
args = cp.get(sectname, "args")
args = eval(args, vars(logging))
h = apply(klass, args)
if "level" in opts:
level = cp.get(sectname, "level")
h.setLevel(logging._levelNames[level])
if len(fmt):
h.setFormatter(formatters[fmt])
#temporary hack for FileHandler and MemoryHandler.
if klass == logging.handlers.MemoryHandler:
if "target" in opts:
target = cp.get(sectname,"target")
else:
target = ""
if len(target): #the target handler may not be loaded yet, so keep for later...
fixups.append((h, target))
handlers[hand] = h
#now all handlers are loaded, fixup inter-handler references...
for fixup in fixups:
h = fixup[0]
t = fixup[1]
h.setTarget(handlers[t])
#at last, the loggers...first the root...
llist = cp.get("loggers", "keys")
llist = string.split(llist, ",")
llist.remove("root")
sectname = "logger_root"
root = logging.root
log = root
opts = cp.options(sectname)
if "level" in opts:
level = cp.get(sectname, "level")
log.setLevel(logging._levelNames[level])
for h in root.handlers[:]:
root.removeHandler(h)
hlist = cp.get(sectname, "handlers")
if len(hlist):
hlist = string.split(hlist, ",")
for hand in hlist:
log.addHandler(handlers[hand])
#and now the others...
#we don't want to lose the existing loggers,
#since other threads may have pointers to them.
#existing is set to contain all existing loggers,
#and as we go through the new configuration we
#remove any which are configured. At the end,
#what's left in existing is the set of loggers
#which were in the previous configuration but
#which are not in the new configuration.
existing = root.manager.loggerDict.keys()
#now set up the new ones...
for log in llist:
sectname = "logger_%s" % log
qn = cp.get(sectname, "qualname")
opts = cp.options(sectname)
if "propagate" in opts:
propagate = cp.getint(sectname, "propagate")
else:
propagate = 1
logger = logging.getLogger(qn)
if qn in existing:
existing.remove(qn)
if "level" in opts:
level = cp.get(sectname, "level")
logger.setLevel(logging._levelNames[level])
for h in logger.handlers[:]:
logger.removeHandler(h)
logger.propagate = propagate
logger.disabled = 0
hlist = cp.get(sectname, "handlers")
if len(hlist):
hlist = string.split(hlist, ",")
for hand in hlist:
logger.addHandler(handlers[hand])
#Disable any old loggers. There's no point deleting
#them as other threads may continue to hold references
#and by disabling them, you stop them doing any logging.
for log in existing:
root.manager.loggerDict[log].disabled = 1
except:
import traceback
ei = sys.exc_info()
traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
del ei
finally:
logging._releaseLock()
def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
"""
Start up a socket server on the specified port, and listen for new
configurations.
These will be sent as a file suitable for processing by fileConfig().
Returns a Thread object on which you can call start() to start the server,
and which you can join() when appropriate. To stop the server, call
stopListening().
"""
if not thread:
raise NotImplementedError, "listen() needs threading to work"
class ConfigStreamHandler(StreamRequestHandler):
"""
Handler for a logging configuration request.
It expects a completely new logging configuration and uses fileConfig
to install it.
"""
def handle(self):
"""
Handle a request.
Each request is expected to be a 4-byte length,
followed by the config file. Uses fileConfig() to do the
grunt work.
"""
import tempfile
try:
conn = self.connection
chunk = conn.recv(4)
if len(chunk) == 4:
slen = struct.unpack(">L", chunk)[0]
chunk = self.connection.recv(slen)
while len(chunk) < slen:
chunk = chunk + conn.recv(slen - len(chunk))
#Apply new configuration. We'd like to be able to
#create a StringIO and pass that in, but unfortunately
#1.5.2 ConfigParser does not support reading file
#objects, only actual files. So we create a temporary
#file and remove it later.
file = tempfile.mktemp(".ini")
f = open(file, "w")
f.write(chunk)
f.close()
fileConfig(file)
os.remove(file)
except socket.error, e:
if type(e.args) != types.TupleType:
raise
else:
errcode = e.args[0]
if errcode != RESET_ERROR:
raise
class ConfigSocketReceiver(ThreadingTCPServer):
"""
A simple TCP socket-based logging config receiver.
"""
allow_reuse_address = 1
def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
handler=None):
ThreadingTCPServer.__init__(self, (host, port), handler)
logging._acquireLock()
self.abort = 0
logging._releaseLock()
self.timeout = 1
def serve_until_stopped(self):
import select
abort = 0
while not abort:
rd, wr, ex = select.select([self.socket.fileno()],
[], [],
self.timeout)
if rd:
self.handle_request()
logging._acquireLock()
abort = self.abort
logging._releaseLock()
def serve(rcvr, hdlr, port):
server = rcvr(port=port, handler=hdlr)
global _listener
logging._acquireLock()
_listener = server
logging._releaseLock()
server.serve_until_stopped()
return threading.Thread(target=serve,
args=(ConfigSocketReceiver,
ConfigStreamHandler, port))
def stopListening():
"""
Stop the listening server which was created with a call to listen().
"""
global _listener
if _listener:
logging._acquireLock()
_listener.abort = 1
_listener = None
logging._releaseLock()
@@ -0,0 +1,787 @@
# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""
Additional handlers for the logging package for Python. The core package is
based on PEP 282 and comments thereto in comp.lang.python, and influenced by
Apache's log4j system.
Should work under Python versions >= 1.5.2, except that source line
information is not available unless 'sys._getframe()' is.
Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
To use, simply 'import logging' and log away!
"""
import sys, logging, socket, types, os, string, cPickle, struct, time
from SocketServer import ThreadingTCPServer, StreamRequestHandler
#
# Some constants...
#
DEFAULT_TCP_LOGGING_PORT = 9020
DEFAULT_UDP_LOGGING_PORT = 9021
DEFAULT_HTTP_LOGGING_PORT = 9022
DEFAULT_SOAP_LOGGING_PORT = 9023
SYSLOG_UDP_PORT = 514
class RotatingFileHandler(logging.FileHandler):
def __init__(self, filename, mode="a", maxBytes=0, backupCount=0):
"""
Open the specified file and use it as the stream for logging.
By default, the file grows indefinitely. You can specify particular
values of maxBytes and backupCount to allow the file to rollover at
a predetermined size.
Rollover occurs whenever the current log file is nearly maxBytes in
length. If backupCount is >= 1, the system will successively create
new files with the same pathname as the base file, but with extensions
".1", ".2" etc. appended to it. For example, with a backupCount of 5
and a base file name of "app.log", you would get "app.log",
"app.log.1", "app.log.2", ... through to "app.log.5". The file being
written to is always "app.log" - when it gets filled up, it is closed
and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc.
exist, then they are renamed to "app.log.2", "app.log.3" etc.
respectively.
If maxBytes is zero, rollover never occurs.
"""
logging.FileHandler.__init__(self, filename, mode)
self.maxBytes = maxBytes
self.backupCount = backupCount
if maxBytes > 0:
self.mode = "a"
def doRollover(self):
"""
Do a rollover, as described in __init__().
"""
self.stream.close()
if self.backupCount > 0:
for i in range(self.backupCount - 1, 0, -1):
sfn = "%s.%d" % (self.baseFilename, i)
dfn = "%s.%d" % (self.baseFilename, i + 1)
if os.path.exists(sfn):
#print "%s -> %s" % (sfn, dfn)
if os.path.exists(dfn):
os.remove(dfn)
os.rename(sfn, dfn)
dfn = self.baseFilename + ".1"
if os.path.exists(dfn):
os.remove(dfn)
os.rename(self.baseFilename, dfn)
#print "%s -> %s" % (self.baseFilename, dfn)
self.stream = open(self.baseFilename, "w")
def emit(self, record):
"""
Emit a record.
Output the record to the file, catering for rollover as described
in doRollover().
"""
if self.maxBytes > 0: # are we rolling over?
msg = "%s\n" % self.format(record)
self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
if self.stream.tell() + len(msg) >= self.maxBytes:
self.doRollover()
logging.FileHandler.emit(self, record)
class SocketHandler(logging.Handler):
"""
A handler class which writes logging records, in pickle format, to
a streaming socket. The socket is kept open across logging calls.
If the peer resets it, an attempt is made to reconnect on the next call.
The pickle which is sent is that of the LogRecord's attribute dictionary
(__dict__), so that the receiver does not need to have the logging module
installed in order to process the logging event.
To unpickle the record at the receiving end into a LogRecord, use the
makeLogRecord function.
"""
def __init__(self, host, port):
"""
Initializes the handler with a specific host address and port.
The attribute 'closeOnError' is set to 1 - which means that if
a socket error occurs, the socket is silently closed and then
reopened on the next logging call.
"""
logging.Handler.__init__(self)
self.host = host
self.port = port
self.sock = None
self.closeOnError = 0
self.retryTime = None
#
# Exponential backoff parameters.
#
self.retryStart = 1.0
self.retryMax = 30.0
self.retryFactor = 2.0
def makeSocket(self):
"""
A factory method which allows subclasses to define the precise
type of socket they want.
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.host, self.port))
return s
def createSocket(self):
"""
Try to create a socket, using an exponential backoff with
a max retry time. Thanks to Robert Olson for the original patch
(SF #815911) which has been slightly refactored.
"""
now = time.time()
# Either retryTime is None, in which case this
# is the first time back after a disconnect, or
# we've waited long enough.
if self.retryTime is None:
attempt = 1
else:
attempt = (now >= self.retryTime)
if attempt:
try:
self.sock = self.makeSocket()
self.retryTime = None # next time, no delay before trying
except:
#Creation failed, so set the retry time and return.
if self.retryTime is None:
self.retryPeriod = self.retryStart
else:
self.retryPeriod = self.retryPeriod * self.retryFactor
if self.retryPeriod > self.retryMax:
self.retryPeriod = self.retryMax
self.retryTime = now + self.retryPeriod
def send(self, s):
"""
Send a pickled string to the socket.
This function allows for partial sends which can happen when the
network is busy.
"""
if self.sock is None:
self.createSocket()
#self.sock can be None either because we haven't reached the retry
#time yet, or because we have reached the retry time and retried,
#but are still unable to connect.
if self.sock:
try:
if hasattr(self.sock, "sendall"):
self.sock.sendall(s)
else:
sentsofar = 0
left = len(s)
while left > 0:
sent = self.sock.send(s[sentsofar:])
sentsofar = sentsofar + sent
left = left - sent
except socket.error:
self.sock.close()
self.sock = None # so we can call createSocket next time
def makePickle(self, record):
"""
Pickles the record in binary format with a length prefix, and
returns it ready for transmission across the socket.
"""
ei = record.exc_info
if ei:
dummy = self.format(record) # just to get traceback text into record.exc_text
record.exc_info = None # to avoid Unpickleable error
s = cPickle.dumps(record.__dict__, 1)
if ei:
record.exc_info = ei # for next handler
slen = struct.pack(">L", len(s))
return slen + s
def handleError(self, record):
"""
Handle an error during logging.
An error has occurred during logging. Most likely cause -
connection lost. Close the socket so that we can retry on the
next event.
"""
if self.closeOnError and self.sock:
self.sock.close()
self.sock = None #try to reconnect next time
else:
logging.Handler.handleError(self, record)
def emit(self, record):
"""
Emit a record.
Pickles the record and writes it to the socket in binary format.
If there is an error with the socket, silently drop the packet.
If there was a problem with the socket, re-establishes the
socket.
"""
try:
s = self.makePickle(record)
self.send(s)
except:
self.handleError(record)
def close(self):
"""
Closes the socket.
"""
if self.sock:
self.sock.close()
self.sock = None
logging.Handler.close(self)
class DatagramHandler(SocketHandler):
"""
A handler class which writes logging records, in pickle format, to
a datagram socket. The pickle which is sent is that of the LogRecord's
attribute dictionary (__dict__), so that the receiver does not need to
have the logging module installed in order to process the logging event.
To unpickle the record at the receiving end into a LogRecord, use the
makeLogRecord function.
"""
def __init__(self, host, port):
"""
Initializes the handler with a specific host address and port.
"""
SocketHandler.__init__(self, host, port)
self.closeOnError = 0
def makeSocket(self):
"""
The factory method of SocketHandler is here overridden to create
a UDP socket (SOCK_DGRAM).
"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return s
def send(self, s):
"""
Send a pickled string to a socket.
This function no longer allows for partial sends which can happen
when the network is busy - UDP does not guarantee delivery and
can deliver packets out of sequence.
"""
self.sock.sendto(s, (self.host, self.port))
class SysLogHandler(logging.Handler):
"""
A handler class which sends formatted logging records to a syslog
server. Based on Sam Rushing's syslog module:
http://www.nightmare.com/squirl/python-ext/misc/syslog.py
Contributed by Nicolas Untz (after which minor refactoring changes
have been made).
"""
# from <linux/sys/syslog.h>:
# ======================================================================
# priorities/facilities are encoded into a single 32-bit quantity, where
# the bottom 3 bits are the priority (0-7) and the top 28 bits are the
# facility (0-big number). Both the priorities and the facilities map
# roughly one-to-one to strings in the syslogd(8) source code. This
# mapping is included in this file.
#
# priorities (these are ordered)
LOG_EMERG = 0 # system is unusable
LOG_ALERT = 1 # action must be taken immediately
LOG_CRIT = 2 # critical conditions
LOG_ERR = 3 # error conditions
LOG_WARNING = 4 # warning conditions
LOG_NOTICE = 5 # normal but significant condition
LOG_INFO = 6 # informational
LOG_DEBUG = 7 # debug-level messages
# facility codes
LOG_KERN = 0 # kernel messages
LOG_USER = 1 # random user-level messages
LOG_MAIL = 2 # mail system
LOG_DAEMON = 3 # system daemons
LOG_AUTH = 4 # security/authorization messages
LOG_SYSLOG = 5 # messages generated internally by syslogd
LOG_LPR = 6 # line printer subsystem
LOG_NEWS = 7 # network news subsystem
LOG_UUCP = 8 # UUCP subsystem
LOG_CRON = 9 # clock daemon
LOG_AUTHPRIV = 10 # security/authorization messages (private)
# other codes through 15 reserved for system use
LOG_LOCAL0 = 16 # reserved for local use
LOG_LOCAL1 = 17 # reserved for local use
LOG_LOCAL2 = 18 # reserved for local use
LOG_LOCAL3 = 19 # reserved for local use
LOG_LOCAL4 = 20 # reserved for local use
LOG_LOCAL5 = 21 # reserved for local use
LOG_LOCAL6 = 22 # reserved for local use
LOG_LOCAL7 = 23 # reserved for local use
priority_names = {
"alert": LOG_ALERT,
"crit": LOG_CRIT,
"critical": LOG_CRIT,
"debug": LOG_DEBUG,
"emerg": LOG_EMERG,
"err": LOG_ERR,
"error": LOG_ERR, # DEPRECATED
"info": LOG_INFO,
"notice": LOG_NOTICE,
"panic": LOG_EMERG, # DEPRECATED
"warn": LOG_WARNING, # DEPRECATED
"warning": LOG_WARNING,
}
facility_names = {
"auth": LOG_AUTH,
"authpriv": LOG_AUTHPRIV,
"cron": LOG_CRON,
"daemon": LOG_DAEMON,
"kern": LOG_KERN,
"lpr": LOG_LPR,
"mail": LOG_MAIL,
"news": LOG_NEWS,
"security": LOG_AUTH, # DEPRECATED
"syslog": LOG_SYSLOG,
"user": LOG_USER,
"uucp": LOG_UUCP,
"local0": LOG_LOCAL0,
"local1": LOG_LOCAL1,
"local2": LOG_LOCAL2,
"local3": LOG_LOCAL3,
"local4": LOG_LOCAL4,
"local5": LOG_LOCAL5,
"local6": LOG_LOCAL6,
"local7": LOG_LOCAL7,
}
def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
"""
Initialize a handler.
If address is specified as a string, UNIX socket is used.
If facility is not specified, LOG_USER is used.
"""
logging.Handler.__init__(self)
self.address = address
self.facility = facility
if type(address) == types.StringType:
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
# syslog may require either DGRAM or STREAM sockets
try:
self.socket.connect(address)
except socket.error:
self.socket.close()
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.socket.connect(address)
self.unixsocket = 1
else:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.unixsocket = 0
self.formatter = None
# curious: when talking to the unix-domain '/dev/log' socket, a
# zero-terminator seems to be required. this string is placed
# into a class variable so that it can be overridden if
# necessary.
log_format_string = '<%d>%s\000'
def encodePriority (self, facility, priority):
"""
Encode the facility and priority. You can pass in strings or
integers - if strings are passed, the facility_names and
priority_names mapping dictionaries are used to convert them to
integers.
"""
if type(facility) == types.StringType:
facility = self.facility_names[facility]
if type(priority) == types.StringType:
priority = self.priority_names[priority]
return (facility << 3) | priority
def close (self):
"""
Closes the socket.
"""
if self.unixsocket:
self.socket.close()
logging.Handler.close(self)
def emit(self, record):
"""
Emit a record.
The record is formatted, and then sent to the syslog server. If
exception information is present, it is NOT sent to the server.
"""
msg = self.format(record)
"""
We need to convert record level to lowercase, maybe this will
change in the future.
"""
msg = self.log_format_string % (
self.encodePriority(self.facility,
string.lower(record.levelname)),
msg)
try:
if self.unixsocket:
self.socket.send(msg)
else:
self.socket.sendto(msg, self.address)
except:
self.handleError(record)
class SMTPHandler(logging.Handler):
"""
A handler class which sends an SMTP email for each logging event.
"""
def __init__(self, mailhost, fromaddr, toaddrs, subject):
"""
Initialize the handler.
Initialize the instance with the from and to addresses and subject
line of the email. To specify a non-standard SMTP port, use the
(host, port) tuple format for the mailhost argument.
"""
logging.Handler.__init__(self)
if type(mailhost) == types.TupleType:
host, port = mailhost
self.mailhost = host
self.mailport = port
else:
self.mailhost = mailhost
self.mailport = None
self.fromaddr = fromaddr
if type(toaddrs) == types.StringType:
toaddrs = [toaddrs]
self.toaddrs = toaddrs
self.subject = subject
def getSubject(self, record):
"""
Determine the subject for the email.
If you want to specify a subject line which is record-dependent,
override this method.
"""
return self.subject
weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
monthname = [None,
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def date_time(self):
"""Return the current date and time formatted for a MIME header."""
year, month, day, hh, mm, ss, wd, y, z = time.gmtime(time.time())
s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
self.weekdayname[wd],
day, self.monthname[month], year,
hh, mm, ss)
return s
def emit(self, record):
"""
Emit a record.
Format the record and send it to the specified addressees.
"""
try:
import smtplib
port = self.mailport
if not port:
port = smtplib.SMTP_PORT
smtp = smtplib.SMTP(self.mailhost, port)
msg = self.format(record)
msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
self.fromaddr,
string.join(self.toaddrs, ","),
self.getSubject(record),
self.date_time(), msg)
smtp.sendmail(self.fromaddr, self.toaddrs, msg)
smtp.quit()
except:
self.handleError(record)
class NTEventLogHandler(logging.Handler):
"""
A handler class which sends events to the NT Event Log. Adds a
registry entry for the specified application name. If no dllname is
provided, win32service.pyd (which contains some basic message
placeholders) is used. Note that use of these placeholders will make
your event logs big, as the entire message source is held in the log.
If you want slimmer logs, you have to pass in the name of your own DLL
which contains the message definitions you want to use in the event log.
"""
def __init__(self, appname, dllname=None, logtype="Application"):
logging.Handler.__init__(self)
try:
import win32evtlogutil, win32evtlog
self.appname = appname
self._welu = win32evtlogutil
if not dllname:
dllname = os.path.split(self._welu.__file__)
dllname = os.path.split(dllname[0])
dllname = os.path.join(dllname[0], r'win32service.pyd')
self.dllname = dllname
self.logtype = logtype
self._welu.AddSourceToRegistry(appname, dllname, logtype)
self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE
self.typemap = {
logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE,
logging.INFO : win32evtlog.EVENTLOG_INFORMATION_TYPE,
logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE,
logging.ERROR : win32evtlog.EVENTLOG_ERROR_TYPE,
logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
}
except ImportError:
print "The Python Win32 extensions for NT (service, event "\
"logging) appear not to be available."
self._welu = None
def getMessageID(self, record):
"""
Return the message ID for the event record. If you are using your
own messages, you could do this by having the msg passed to the
logger being an ID rather than a formatting string. Then, in here,
you could use a dictionary lookup to get the message ID. This
version returns 1, which is the base message ID in win32service.pyd.
"""
return 1
def getEventCategory(self, record):
"""
Return the event category for the record.
Override this if you want to specify your own categories. This version
returns 0.
"""
return 0
def getEventType(self, record):
"""
Return the event type for the record.
Override this if you want to specify your own types. This version does
a mapping using the handler's typemap attribute, which is set up in
__init__() to a dictionary which contains mappings for DEBUG, INFO,
WARNING, ERROR and CRITICAL. If you are using your own levels you will
either need to override this method or place a suitable dictionary in
the handler's typemap attribute.
"""
return self.typemap.get(record.levelno, self.deftype)
def emit(self, record):
"""
Emit a record.
Determine the message ID, event category and event type. Then
log the message in the NT event log.
"""
if self._welu:
try:
id = self.getMessageID(record)
cat = self.getEventCategory(record)
type = self.getEventType(record)
msg = self.format(record)
self._welu.ReportEvent(self.appname, id, cat, type, [msg])
except:
self.handleError(record)
def close(self):
"""
Clean up this handler.
You can remove the application name from the registry as a
source of event log entries. However, if you do this, you will
not be able to see the events as you intended in the Event Log
Viewer - it needs to be able to access the registry to get the
DLL name.
"""
#self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
logging.Handler.close(self)
class HTTPHandler(logging.Handler):
"""
A class which sends records to a Web server, using either GET or
POST semantics.
"""
def __init__(self, host, url, method="GET"):
"""
Initialize the instance with the host, the request URL, and the method
("GET" or "POST")
"""
logging.Handler.__init__(self)
method = string.upper(method)
if method not in ["GET", "POST"]:
raise ValueError, "method must be GET or POST"
self.host = host
self.url = url
self.method = method
def mapLogRecord(self, record):
"""
Default implementation of mapping the log record into a dict
that is sent as the CGI data. Overwrite in your class.
Contributed by Franz Glasner.
"""
return record.__dict__
def emit(self, record):
"""
Emit a record.
Send the record to the Web server as an URL-encoded dictionary
"""
try:
import httplib, urllib
h = httplib.HTTP(self.host)
url = self.url
data = urllib.urlencode(self.mapLogRecord(record))
if self.method == "GET":
if (string.find(url, '?') >= 0):
sep = '&'
else:
sep = '?'
url = url + "%c%s" % (sep, data)
h.putrequest(self.method, url)
if self.method == "POST":
h.putheader("Content-length", str(len(data)))
h.endheaders()
if self.method == "POST":
h.send(data)
h.getreply() #can't do anything with the result
except:
self.handleError(record)
class BufferingHandler(logging.Handler):
"""
A handler class which buffers logging records in memory. Whenever each
record is added to the buffer, a check is made to see if the buffer should
be flushed. If it should, then flush() is expected to do what's needed.
"""
def __init__(self, capacity):
"""
Initialize the handler with the buffer size.
"""
logging.Handler.__init__(self)
self.capacity = capacity
self.buffer = []
def shouldFlush(self, record):
"""
Should the handler flush its buffer?
Returns true if the buffer is up to capacity. This method can be
overridden to implement custom flushing strategies.
"""
return (len(self.buffer) >= self.capacity)
def emit(self, record):
"""
Emit a record.
Append the record. If shouldFlush() tells us to, call flush() to process
the buffer.
"""
self.buffer.append(record)
if self.shouldFlush(record):
self.flush()
def flush(self):
"""
Override to implement custom flushing behaviour.
This version just zaps the buffer to empty.
"""
self.buffer = []
def close(self):
"""
Close the handler.
This version just flushes and chains to the parent class' close().
"""
self.flush()
logging.Handler.close(self)
class MemoryHandler(BufferingHandler):
"""
A handler class which buffers logging records in memory, periodically
flushing them to a target handler. Flushing occurs whenever the buffer
is full, or when an event of a certain severity or greater is seen.
"""
def __init__(self, capacity, flushLevel=logging.ERROR, target=None):
"""
Initialize the handler with the buffer size, the level at which
flushing should occur and an optional target.
Note that without a target being set either here or via setTarget(),
a MemoryHandler is no use to anyone!
"""
BufferingHandler.__init__(self, capacity)
self.flushLevel = flushLevel
self.target = target
def shouldFlush(self, record):
"""
Check for buffer full or a record at the flushLevel or higher.
"""
return (len(self.buffer) >= self.capacity) or \
(record.levelno >= self.flushLevel)
def setTarget(self, target):
"""
Set the target handler for this handler.
"""
self.target = target
def flush(self):
"""
For a MemoryHandler, flushing means just sending the buffered
records to the target, if there is one. Override if you want
different behaviour.
"""
if self.target:
for record in self.buffer:
self.target.handle(record)
self.buffer = []
def close(self):
"""
Flush, set the target to None and lose the buffer.
"""
self.flush()
self.target = None
BufferingHandler.close(self)
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,29 @@
from distutils.core import setup
setup(name = "logging",
description="A logging module for Python",
long_description = """This module is intended to provide a standard error logging mechanism in Python as per PEP 282.""",
license="""Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Vinay Sajip
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""",
version = "0.4.9.2",
author = "Vinay Sajip",
author_email = "vinay_sajip@red-dove.com",
maintainer = "Vinay Sajip",
maintainer_email = "vinay_sajip@red-dove.com",
url = "http://www.red-dove.com/python_logging.html",
packages = ["logging"],
)
@@ -0,0 +1,5 @@
import logging
logging.warning("Hello")
logging.error("Still here...")
logging.warning("Goodbye")
@@ -0,0 +1,60 @@
[loggers]
keys=root,log02,log03,log04,log05
[handlers]
keys=hand01
[formatters]
keys=form01
[logger_root]
level=WARN
propagate=1
channel=
parent=
qualname=(root)
handlers=hand01
[logger_log02]
level=CRITICAL
propagate=1
channel=A
parent=(root)
qualname=A
handlers=
[logger_log03]
level=CRITICAL
propagate=1
channel=B
parent=log02
qualname=A.B
handlers=
[logger_log04]
level=CRITICAL
propagate=1
channel=C
parent=log03
qualname=A.B.C
handlers=
[logger_log05]
level=CRITICAL
propagate=1
channel=D
parent=log04
qualname=A.B.C.D
handlers=
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
stream=sys.stderr
args=(sys.stderr,)
[formatter_form01]
format=critical.ini %(name)s %(levelname)s %(message)s
datefmt=
@@ -0,0 +1,60 @@
[loggers]
keys=root,log02,log03,log04,log05
[handlers]
keys=hand01
[formatters]
keys=form01
[logger_root]
level=WARN
propagate=1
channel=
parent=
qualname=(root)
handlers=hand01
[logger_log02]
level=DEBUG
propagate=1
channel=A
parent=(root)
qualname=A
handlers=
[logger_log03]
level=DEBUG
propagate=1
channel=B
parent=log02
qualname=A.B
handlers=
[logger_log04]
level=DEBUG
propagate=1
channel=C
parent=log03
qualname=A.B.C
handlers=
[logger_log05]
level=DEBUG
propagate=1
channel=D
parent=log04
qualname=A.B.C.D
handlers=
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
stream=sys.stderr
args=(sys.stderr,)
[formatter_form01]
format=debug.ini %(name)s %(levelname)s %(message)s
datefmt=
@@ -0,0 +1,60 @@
[loggers]
keys=root,log02,log03,log04,log05
[handlers]
keys=hand01
[formatters]
keys=form01
[logger_root]
level=WARN
propagate=1
channel=
parent=
qualname=(root)
handlers=hand01
[logger_log02]
level=ERROR
propagate=1
channel=A
parent=(root)
qualname=A
handlers=
[logger_log03]
level=ERROR
propagate=1
channel=B
parent=log02
qualname=A.B
handlers=
[logger_log04]
level=ERROR
propagate=1
channel=C
parent=log03
qualname=A.B.C
handlers=
[logger_log05]
level=ERROR
propagate=1
channel=D
parent=log04
qualname=A.B.C.D
handlers=
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
stream=sys.stderr
args=(sys.stderr,)
[formatter_form01]
format=error.ini %(name)s %(levelname)s %(message)s
datefmt=
@@ -0,0 +1,31 @@
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 90</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 91</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 92</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 93</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 94</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 95</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 96</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 97</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 98</message>
</event>
<event name="root" level="20" filename="log_test9.py" lineno="66">
<message>Info index = 99</message>
</event>
+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. Run all tests.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import os, sys, logging, threading, time
BANNER = "-- %-10s %-6s --------------------------------------------------------\n"
def banner(nm, typ):
sep = BANNER % (nm, typ)
sys.stdout.write(sep)
sys.stdout.flush()
sys.stderr.write(sep)
sys.stderr.flush()
def main():
oldout = sys.stdout
olderr = sys.stderr
sys.stdout = open("stdout.log", "w")
sys.stderr = open("stderr.log", "w")
logging.basicConfig()
root = logging.getLogger("")
hdlr0 = root.handlers[0]
#Set up servers
import logrecv
threads = []
tcpserver = logrecv.LogRecordSocketReceiver()
tcpserver.logname = ""
threads.append(threading.Thread(target=logrecv.runTCP, args=(tcpserver,)))
udpserver = logrecv.LogRecordDatagramReceiver()
udpserver.logname = ""
threads.append(threading.Thread(target=logrecv.runUDP, args=(udpserver,)))
httpserver = logrecv.LogRecordHTTPReceiver()
httpserver.logname = ""
threads.append(threading.Thread(target=logrecv.runHTTP, args=(httpserver,)))
soapserver = None
if logrecv.SOAPServer:
soapserver = logrecv.SOAPServer()
soapserver.modules = (sys.modules["logrecv"],)
soapserver.logname = ""
threads.append(threading.Thread(target=logrecv.runSOAP, args=(soapserver,)))
for thread in threads:
thread.start()
try:
import log_test0
banner("log_test0", "begin")
log_test0.main()
banner("log_test0", "end")
try:
import log_test1
banner("log_test1", "begin")
log_test1.main()
banner("log_test1", "end")
except ImportError:
pass
import log_test2
banner("log_test2", "begin")
log_test2.main()
banner("log_test2", "end")
time.sleep(3)
#Skip 3 as it tests fileConfig
banner("log_test4", "begin")
import log_test4
banner("log_test4", "end")
#Skip 5 as it tests SMTPHandler, can't easily check results automatically
#Skip 6 as it tests NTEventLogHandler, can't easily check results automatically
banner("log_test7", "begin")
root.removeHandler(hdlr0)
import log_test7
root.addHandler(hdlr0)
banner("log_test7", "end")
banner("log_test8", "begin")
import log_test8
root.removeHandler(hdlr0)
log_test8.main()
root.addHandler(hdlr0)
banner("log_test8", "end")
banner("log_test9", "begin")
import log_test9
root.removeHandler(hdlr0)
log_test9.main()
root.addHandler(hdlr0)
banner("log_test9", "end")
banner("log_test10", "begin")
import log_test10
log_test10.main()
banner("log_test10", "end")
#Skip 11 as it tests SMTPHandler, can't easily check results automatically
import log_test12
banner("log_test12", "begin")
log_test12.main()
banner("log_test12", "end")
import log_test13
banner("log_test13", "begin")
log_test13.main()
banner("log_test13", "end")
import log_test15
banner("log_test15", "begin")
log_test15.test(log_test15.FILTER)
banner("log_test15", "end")
time.sleep(3)
finally:
#shut down servers
olderr.write("Tidying up...")
tcpserver.abort = 1
udpserver.abort = 1
httpserver.abort = 1
if soapserver:
soapserver.abort = 1
for thread in threads:
thread.join()
sys.stdout.close()
sys.stdout = oldout
#don't close this, as hdlr0 references it. hdlr0 will be closed at application exit
#sys.stderr.close()
sys.stderr = olderr
print "Test run completed."
if __name__ == "__main__":
main()
+118
View File
@@ -0,0 +1,118 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. A basic test of levels.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging
msgcount = 0
def nextmessage():
global msgcount
rv = "Message %d" % msgcount
msgcount = msgcount + 1
return rv
def main():
logging.basicConfig()
logging.getLogger("").setLevel(logging.DEBUG)
ERR = logging.getLogger("ERR")
ERR.setLevel(logging.ERROR)
INF = logging.getLogger("INF")
INF.setLevel(logging.INFO)
INF_ERR = logging.getLogger("INF.ERR")
INF_ERR.setLevel(logging.ERROR)
DEB = logging.getLogger("DEB")
DEB.setLevel(logging.DEBUG)
INF_UNDEF = logging.getLogger("INF.UNDEF")
INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
UNDEF = logging.getLogger("UNDEF")
GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
CHILD = logging.getLogger("INF.BADPARENT")
#These should log
ERR.log(logging.CRITICAL, nextmessage())
ERR.error(nextmessage())
INF.log(logging.CRITICAL, nextmessage())
INF.error(nextmessage())
INF.warning(nextmessage())
INF.info(nextmessage())
INF_UNDEF.log(logging.CRITICAL, nextmessage())
INF_UNDEF.error(nextmessage())
INF_UNDEF.warning(nextmessage())
INF_UNDEF.info(nextmessage())
INF_ERR.log(logging.CRITICAL, nextmessage())
INF_ERR.error(nextmessage())
INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage())
INF_ERR_UNDEF.error(nextmessage())
DEB.log(logging.CRITICAL, nextmessage())
DEB.error(nextmessage())
DEB.warning(nextmessage())
DEB.info(nextmessage())
DEB.debug(nextmessage())
UNDEF.log(logging.CRITICAL, nextmessage())
UNDEF.error(nextmessage())
UNDEF.warning(nextmessage())
UNDEF.info(nextmessage())
GRANDCHILD.log(logging.CRITICAL, nextmessage())
CHILD.log(logging.CRITICAL, nextmessage())
#These should not log
ERR.warning(nextmessage())
ERR.info(nextmessage())
ERR.debug(nextmessage())
INF.debug(nextmessage())
INF_UNDEF.debug(nextmessage())
INF_ERR.warning(nextmessage())
INF_ERR.info(nextmessage())
INF_ERR.debug(nextmessage())
INF_ERR_UNDEF.warning(nextmessage())
INF_ERR_UNDEF.info(nextmessage())
INF_ERR_UNDEF.debug(nextmessage())
INF.info("Messages should bear numbers 0 through 24.")
if __name__ == "__main__":
import sys
#print sys.argv[0]
args = sys.argv[1:]
if "-profile" in args:
import profile, pstats
args.remove("-profile")
statf = "log_test0.pro"
profile.run("main()", statf)
stats = pstats.Stats(statf)
stats.strip_dirs().sort_stats('time').print_stats()
else:
main()
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. A test showing exception handling and use of SysLogHandler.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys, logging
import syslog
class SLHandler(logging.Handler):
def __init__(self, ident, logopt=0, facility=syslog.LOG_USER):
logging.Handler.__init__(self)
self.ident = ident
self.logopt = logopt
self.facility = facility
self.mappings = {
logging.DEBUG: syslog.LOG_DEBUG,
logging.INFO: syslog.LOG_INFO,
logging.WARNING: syslog.LOG_WARNING,
logging.ERROR: syslog.LOG_ERR,
logging.CRITICAL: syslog.LOG_CRIT,
}
def encodeLevel(self, level):
return self.mappings.get(level, syslog.LOG_INFO)
def emit(self, record):
syslog.openlog(self.ident, self.logopt, self.facility)
msg = self.format(record)
prio = self.encodeLevel(record.levelno)
syslog.syslog(prio, msg)
syslog.closelog()
def config():
logging.basicConfig()
logging.getLogger("").setLevel(logging.DEBUG)
if __name__ == "__main__":
fmt = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s")
hdlr = logging.FileHandler("tmp.tmp")
hdlr.setFormatter(fmt)
logging.getLogger("").addHandler(hdlr)
else:
fmt = None
hdlr = SLHandler("log_test1")
if fmt:
hdlr.setFormatter(fmt)
logging.getLogger("").addHandler(hdlr)
return hdlr
def run():
logging.info("Starting...")
try:
print "7" + 4
except Exception, e:
logging.error("Problem %s (%d)", "ERROR", logging.ERROR, exc_info=1)
logging.debug("Problem %s (%d)", "DEBUG", logging.DEBUG, exc_info=1)
logging.info("Done.")
def main():
hdlr = config()
run()
logging.getLogger("").removeHandler(hdlr)
if __name__ == "__main__":
main()
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. Shows use of a user-defined Logger subclass.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys
import locale
locale.setlocale(locale.LC_ALL, '')
from logging import *
LOG_FORMAT = "%(asctime)s %(levelname)-5s %(message)s"
DATE_FORMAT = "%x %X"
class MyLogger(Logger):
"""
A simple example of a logger extension.
"""
def debug(self, msg, *args, **kwargs):
"""
This overridden method passes exception information for DEBUG level calls
"""
if self.manager.disable >= DEBUG:
return
if DEBUG >= self.getEffectiveLevel():
exc_info = kwargs.get("exc_info", 0)
ei = None
if exc_info:
ei = sys.exc_info()
if not ei[1]:
ei = None
self._log(DEBUG, msg, args, ei)
del ei
class NotALogger:
pass
def config():
try:
setLoggerClass(NotALogger)
except Exception, e:
sys.stderr.write("%s\n" % e)
setLoggerClass(MyLogger)
if __name__ == "__main__":
basicConfig()
if __name__ == "__main__":
getLogger("").handlers[0].setFormatter(Formatter(LOG_FORMAT, DATE_FORMAT))
def run():
getLogger("").setLevel(DEBUG)
logger = getLogger("mylogger")
logger.info("Starting...")
logger.debug("Debug message not in exception handler (no traceback)")
logger.info("About to throw exception...")
try:
print "7" + 4
except Exception, e:
logger.debug("Debug message inside exception handler (traceback)",exc_info=1)
logger.info("Done.")
def main():
config()
run()
if __name__ == "__main__":
main()
+72
View File
@@ -0,0 +1,72 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. Tests BufferingSMTPHandler, an alternative implementation
of SMTPHandler.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import string, logging, logging.handlers
MAILHOST = 'beta'
FROM = 'log_test11@red-dove.com'
TO = ['arkadi_renko']
SUBJECT = 'Test Logging email from Python logging module (buffering)'
class BufferingSMTPHandler(logging.handlers.BufferingHandler):
def __init__(self, mailhost, fromaddr, toaddrs, subject, capacity):
logging.handlers.BufferingHandler.__init__(self, capacity)
self.mailhost = mailhost
self.mailport = None
self.fromaddr = fromaddr
self.toaddrs = toaddrs
self.subject = subject
self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
def flush(self):
if len(self.buffer) > 0:
try:
import smtplib
port = self.mailport
if not port:
port = smtplib.SMTP_PORT
smtp = smtplib.SMTP(self.mailhost, port)
msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, string.join(self.toaddrs, ","), self.subject)
for record in self.buffer:
s = self.format(record)
print s
msg = msg + s + "\r\n"
smtp.sendmail(self.fromaddr, self.toaddrs, msg)
smtp.quit()
except:
self.handleError(None) # no particular record
self.buffer = []
def test():
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
logger.addHandler(BufferingSMTPHandler(MAILHOST, FROM, TO, SUBJECT, 10))
for i in xrange(102):
logger.info("Info index = %d", i)
logging.shutdown()
if __name__ == "__main__":
test()
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests HTTPHandler.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys, string, logging, logging.handlers
def main():
import pdb
host = "localhost:%d" % logging.handlers.DEFAULT_HTTP_LOGGING_PORT
gh = logging.handlers.HTTPHandler(host, '/log', 'GET')
ph = logging.handlers.HTTPHandler(host, '/log', 'POST')
logger = logging.getLogger("log_test12")
logger.propagate = 0
logger.addHandler(gh)
logger.addHandler(ph)
logging.getLogger("").setLevel(logging.DEBUG)
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
logger.debug("Pack my %s with twelve dozen %s", "box", "liquor jugs")
gh.close()
ph.close()
logger.removeHandler(gh)
logger.removeHandler(ph)
if __name__ == "__main__":
main()
+106
View File
@@ -0,0 +1,106 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Implements a SOAPHandler class which
can be used to form the basis of extended SOAP functionality.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import string, logging, logging.handlers, types
SOAP_MESSAGE = """<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:logging="http://www.red-dove.com/logging"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
>
<SOAP-ENV:Body>
<logging:log>
%s
</logging:log>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"""
class SOAPHandler(logging.Handler):
"""
A class which sends records to a SOAP server.
"""
def __init__(self, host, url):
"""
Initialize the instance with the host and the request URL
"""
logging.Handler.__init__(self)
self.host = host
self.url = url
def emit(self, record):
"""
Send the record to the Web server as a SOAP message
"""
try:
import httplib
h = httplib.HTTP(self.host)
h.putrequest("POST", self.url)
keys = record.__dict__.keys()
keys.sort()
args = ""
for key in keys:
v = record.__dict__[key]
if type(v) == types.StringType:
t = "string"
elif (type(v) == types.IntType) or (type(v) == types.LongType):
t = "integer"
elif type(v) == types.FloatType:
t = "float"
else:
t = "string"
args = args + "%12s<logging:%s xsi:type=\"xsd:%s\">%s</logging:%s>\n" % ("",
key, t, str(v), key)
data = SOAP_MESSAGE % args[:-1]
h.putheader("Content-type", "text/plain; charset=\"utf-8\"")
h.putheader("Content-length", str(len(data)))
h.endheaders()
#print data
h.send(data)
r = h.getreply() #can't do anything with the result
f = h.getfile()
if f:
#print f.read()
f.close()
except:
self.handleError(record)
def main():
sh = SOAPHandler('localhost:%d' % logging.handlers.DEFAULT_SOAP_LOGGING_PORT, '/log')
logger = logging.getLogger("log_test13")
logging.getLogger("").setLevel(logging.DEBUG)
logger.propagate = 0
logger.addHandler(sh)
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
logger.removeHandler(sh)
if __name__ == "__main__":
main()
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. An example handler - DBHandler -
which writes to an Python DB API 2.0 data source. You'll need to set this
source up before you run the test.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys, string, time, logging
class DBHandler(logging.Handler):
def __init__(self, dsn, uid='', pwd=''):
logging.Handler.__init__(self)
import mx.ODBC.Windows
self.dsn = dsn
self.uid = uid
self.pwd = pwd
self.conn = mx.ODBC.Windows.connect(self.dsn, self.uid, self.pwd)
self.SQL = """INSERT INTO Events (
Created,
RelativeCreated,
Name,
LogLevel,
LevelText,
Message,
Filename,
Pathname,
Lineno,
Milliseconds,
Exception,
Thread
)
VALUES (
%(dbtime)s,
%(relativeCreated)d,
'%(name)s',
%(levelno)d,
'%(levelname)s',
'%(message)s',
'%(filename)s',
'%(pathname)s',
%(lineno)d,
%(msecs)d,
'%(exc_text)s',
'%(thread)s'
);
"""
self.cursor = self.conn.cursor()
def formatDBTime(self, record):
record.dbtime = time.strftime("#%m/%d/%Y#", time.localtime(record.created))
def emit(self, record):
try:
#use default formatting
self.format(record)
#now set the database time up
self.formatDBTime(record)
if record.exc_info:
record.exc_text = logging._defaultFormatter.formatException(record.exc_info)
else:
record.exc_text = ""
sql = self.SQL % record.__dict__
self.cursor.execute(sql)
self.conn.commit()
except:
import traceback
ei = sys.exc_info()
traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
del ei
def close(self):
self.cursor.close()
self.conn.close()
logging.Handler.close(self)
dh = DBHandler('Logging')
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
logger.addHandler(dh)
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
try:
import math
math.exp(1000)
except:
logger.exception("Problem with %s", "math.exp")
logging.shutdown()
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests Filter.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys, logging
FILTER = "a.b"
def message(s):
sys.stderr.write("%s\n" % s)
def doLog():
logging.getLogger("a").info("Info 1")
logging.getLogger("a.b").info("Info 2")
logging.getLogger("a.c").info("Info 3")
logging.getLogger("a.b.c").info("Info 4")
logging.getLogger("a.b.c.d").info("Info 5")
logging.getLogger("a.bb.c").info("Info 6")
logging.getLogger("b").info("Info 7")
logging.getLogger("b.a").info("Info 8")
logging.getLogger("c.a.b").info("Info 9")
logging.getLogger("a.bb").info("Info 10")
def test(fs):
root = logging.getLogger()
root.setLevel(logging.DEBUG)
if __name__ == "__main__":
hand = logging.StreamHandler()
hand.setFormatter(logging.Formatter("%(name)-10s %(message)s"))
root.addHandler(hand)
else:
hand = root.handlers[0]
message("Unfiltered...")
doLog()
message("Filtered with '%s'..." % fs)
filt = logging.Filter(fs)
hand.addFilter(filt)
doLog()
hand.removeFilter(filt)
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
fs = sys.argv[1]
else:
fs = FILTER
test(fs)
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests thread safety.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.handlers, thread, threading, random
logging.raiseExceptions = 1
NUM_THREADS = 10
LOOP_COUNT = 10000
LOG_MESSAGES = [
(logging.DEBUG, "%3d This is a %s message", "debug"),
(logging.INFO, "%3d This is an %s message", "informational"),
(logging.WARNING, "%3d This is a %s message", "warning"),
(logging.ERROR, "%3d This is an %s message", "error"),
(logging.CRITICAL, "%3d This is a %s message", "critical"),
]
LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"]
def doLog(num):
logger = logging.getLogger('')
logger.info("*** thread %s started (%d)", thread.get_ident(), num)
for i in xrange(LOOP_COUNT):
logger = logging.getLogger(random.choice(LOG_NAMES))
a = random.choice(LOG_MESSAGES)
args = a[0:2] + (num,) + a[2:]
apply(logger.log, args)
def test():
f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s")
root = logging.getLogger('')
root.setLevel(logging.DEBUG)
h = logging.FileHandler('thread.log', 'w')
root.addHandler(h)
h.setFormatter(f)
h = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
#h = logging.handlers.DatagramHandler('localhost', logging.handlers.DEFAULT_UDP_LOGGING_PORT)
root.addHandler(h)
threads = []
for i in xrange(NUM_THREADS):
threads.append(threading.Thread(target=doLog, args=(len(threads),)))
for t in threads:
t.start()
for t in threads:
t.join()
if __name__ == "__main__":
test()
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests thread safety.
To use as a server, run with no arguments in one process.
To use as a client, run with arguments "-client <filename>" where <filename>
is the name of a file containing a logging configuration.
The example files debug.ini, warn.ini, error.ini and critical.ini are
provided to use in the test. They each have a customized message format
(prefixed with their name) and the loggers have their levels set to the
value implied by their name.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys, logging, logging.config, thread, threading, random, time, struct
NUM_THREADS = 10
LOOP_COUNT = 10
CONFIG_PORT = 9077
logging.raiseExceptions = 1
LOG_MESSAGES = [
(logging.DEBUG, "%3d This is a %s message", "debug"),
(logging.INFO, "%3d This is an %s message", "informational"),
(logging.WARNING, "%3d This is a %s message", "warning"),
(logging.ERROR, "%3d This is an %s message", "error"),
(logging.CRITICAL, "%3d This is a %s message", "critical"),
]
LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"]
def doLog(num):
logger = logging.getLogger('')
logger.setLevel(logging.DEBUG)
logger.info("*** thread %s started (%d)", thread.get_ident(), num)
for i in xrange(LOOP_COUNT):
logger = logging.getLogger(random.choice(LOG_NAMES))
a = random.choice(LOG_MESSAGES)
args = a[0:2] + (num,) + a[2:]
time.sleep(random.random() * 3)
apply(logger.log, args)
def runserver():
f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s")
root = logging.getLogger('')
h = logging.StreamHandler()
root.addHandler(h)
h.setFormatter(f)
threads = []
for i in xrange(NUM_THREADS):
threads.append(threading.Thread(target=doLog, args=(len(threads),)))
threads.append(logging.config.listen(CONFIG_PORT)) #don't use default port
for t in threads:
t.start()
for t in threads[:-1]:
t.join()
logging.config.stopListening()
threads[-1].join()
def runclient(fname):
import socket
print "configuring with '%s'" % fname
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', CONFIG_PORT))
f = open(fname, "r")
s = f.read()
f.close()
slen = struct.pack(">L", len(s))
s = slen + s
sentsofar = 0
left = len(s)
while left > 0:
sent = sock.send(s[sentsofar:])
sentsofar = sentsofar + sent
left = left - sent
sock.close()
if __name__ == "__main__":
if "-client" not in sys.argv:
runserver()
else:
sys.argv.remove("-client")
if len(sys.argv) > 1:
fname = sys.argv[1]
else:
fname = "warn.ini"
runclient(fname)
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests MatchFilter.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, types, string
class MatchFilter(logging.Filter):
def __init__(self, **kwargs):
self.dict = kwargs
def matchOne(self, key, value, record):
rv = getattr(record, key)
if key != "name":
if key not in ["message", "msg"]:
return rv == value
else:
return string.find(str(rv), value) >= 0
else:
if rv == value:
return 1
nlen = len(value)
if string.find(rv, value, 0, nlen) != 0:
return 0
if rv[nlen] == ".":
return 1
def matchValue(self, key, record):
vl = self.dict [key]
if type(vl) != types.ListType:
rv = self.matchOne(key, vl, record)
else:
for v in vl:
rv = self.matchOne(key, v, record)
if rv:
break
return rv
def filter(self, record):
rv = 1
for k in self.dict.keys():
if self.matchValue(k, record):
rv = 0
break
return rv
def doLog(logger, n):
logger.debug("Debug %d" % n)
logger.info("Info %d" % n)
logger.warning("Warning %d" % n)
logger.error("Error %d" % n)
logger.critical("Critical %d" % n)
def test():
fmt = logging.Formatter("%(name)-10s %(levelname)-9s %(message)s")
hand = logging.StreamHandler()
hand.setFormatter(fmt)
root = logging.getLogger("")
root.setLevel(logging.DEBUG)
root.addHandler(hand)
loggers = ['A',
'A.B',
'A.BB',
'A.C',
'AA.B',
'A.B.C',
'A.B.C.D',
'A.B.C.D.E',
'Z.A.B',
]
filt = MatchFilter(name = ['A.C', 'A.B.C'], #reject these loggers and their children
levelno = [logging.WARNING, logging.CRITICAL], #reject these levels,
msg = 'bug 2' #reject if this in message
)
hand.addFilter(filt)
for log in loggers:
doLog(logging.getLogger(log), loggers.index(log))
if __name__ == "__main__":
test()
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. A basic test of parents.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging
def main():
logging.basicConfig()
root = logging.getLogger("")
ab = logging.getLogger("a.b")
abc = logging.getLogger("a.b.c")
root.setLevel(logging.ERROR)
ab.setLevel(logging.INFO)
abc.info("Info")
abc.warning("Warning")
abc.error("Error")
print "abc = %s" % abc
print "abc.parent = %s" % abc.parent
print "ab = %s" % ab
print "ab.parent = %s" % ab.parent
print "root = %s" % root
if __name__ == "__main__":
import sys
print sys.argv[0]
args = sys.argv[1:]
if "-profile" in args:
import profile, pstats
args.remove("-profile")
statf = "log_test19.pro"
profile.run("main()", statf)
stats = pstats.Stats(statf)
stats.strip_dirs().sort_stats('time').print_stats()
else:
main()
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests logger levels and basic Formatter, and logging to
sockets.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.handlers, socket
msgcount = 0
def nextmessage():
global msgcount
rv = "Message %d" % msgcount
msgcount = msgcount + 1
return rv
def main():
logging.basicConfig()
logging.getLogger("").setLevel(logging.DEBUG)
hdlr = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
if __name__ == "__main__":
hdlr.setFormatter(logging.Formatter("%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"))
logging.getLogger("").addHandler(hdlr)
ERR = logging.getLogger("ERR")
ERR.setLevel(logging.ERROR)
INF = logging.getLogger("INF")
INF.setLevel(logging.INFO)
INF_ERR = logging.getLogger("INF.ERR")
INF_ERR.setLevel(logging.ERROR)
DEB = logging.getLogger("DEB")
DEB.setLevel(logging.DEBUG)
INF_UNDEF = logging.getLogger("INF.UNDEF")
INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
UNDEF = logging.getLogger("UNDEF")
GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
CHILD = logging.getLogger("INF.BADPARENT")
#These should log
ERR.log(logging.CRITICAL, nextmessage())
ERR.error(nextmessage())
INF.log(logging.CRITICAL, nextmessage())
INF.error(nextmessage())
INF.warning(nextmessage())
INF.info(nextmessage())
INF_UNDEF.log(logging.CRITICAL, nextmessage())
INF_UNDEF.error(nextmessage())
INF_UNDEF.warning(nextmessage())
INF_UNDEF.info(nextmessage())
INF_ERR.log(logging.CRITICAL, nextmessage())
INF_ERR.error(nextmessage())
INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage())
INF_ERR_UNDEF.error(nextmessage())
DEB.log(logging.CRITICAL, nextmessage())
DEB.error(nextmessage())
DEB.warning(nextmessage())
DEB.info(nextmessage())
DEB.debug(nextmessage())
UNDEF.log(logging.CRITICAL, nextmessage())
UNDEF.error(nextmessage())
UNDEF.warning(nextmessage())
UNDEF.info(nextmessage())
GRANDCHILD.log(logging.CRITICAL, nextmessage())
CHILD.log(logging.CRITICAL, nextmessage())
#These should not log
ERR.warning(nextmessage())
ERR.info(nextmessage())
ERR.debug(nextmessage())
INF.debug(nextmessage())
INF_UNDEF.debug(nextmessage())
INF_ERR.warning(nextmessage())
INF_ERR.info(nextmessage())
INF_ERR.debug(nextmessage())
INF_ERR_UNDEF.warning(nextmessage())
INF_ERR_UNDEF.info(nextmessage())
INF_ERR_UNDEF.debug(nextmessage())
INF.info("Messages should bear numbers 0 through 24.")
hdlr.close()
logging.getLogger("").removeHandler(hdlr)
if __name__ == "__main__":
try:
main()
except socket.error:
print "\nA socket error occurred. Ensure that logrecv.py is running to receive logging requests from this script."
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. Demonstrates the use of custom class
instances for messages and filtering based on classes.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging
class MyClass:
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2
def __str__(self):
return "%s, %s" % (self.arg1, self.arg2)
class MyChildClass(MyClass):
pass
class ClassFilter(logging.Filter):
def __init__(self, klass):
self.klass = klass
def filter(self, record):
return isinstance(record.msg, self.klass)
class MyClassFilter(ClassFilter):
def __init__(self, arg):
ClassFilter.__init__(self, MyClass)
self.arg = arg
def filter(self, record):
return ClassFilter.filter(self, record) and (record.msg.arg2 == self.arg)
def main():
handler = logging.StreamHandler()
root = logging.getLogger("")
root.setLevel(logging.DEBUG)
root.addHandler(handler)
root.addFilter(MyClassFilter("world"))
#Not logged, as it's not a MyClass instance
root.info("%s, %s", "Hello", "world")
#Logged, as it's an appropriate instance which matches the filter criteria
root.info(MyClass("Hello", "world"))
#Not logged, as it's an appropriate class but doesn't match the filter criteria
root.info(MyClass("Hello", "world!"))
#Logged, as it's an appropriate instance which matches the filter criteria
root.info(MyClass("Goodbye", "world"))
#Logged, as it's an appropriate class which matches the filter criteria
root.info(MyChildClass("Hello again", "world"))
if __name__ == "__main__":
import sys
args = sys.argv[1:]
if "-profile" in args:
import profile, pstats
args.remove("-profile")
statf = "log_test20.pro"
profile.run("main()", statf)
stats = pstats.Stats(statf)
stats.strip_dirs().sort_stats('time').print_stats()
else:
main()
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. Demonstrates the use of a wildcard
name-space filter with and without custom message classes.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, re, string, types
class TaggedEvent:
def __init__(self, tag, msg):
self.tag = tag
self.msg = msg
def __str__(self):
return "%s: %s" % (self.tag, self.msg)
class WildcardFilter(logging.Filter):
def __init__(self, wildcards):
self.setWildcards(wildcards)
def setWildcard(self, wildcard):
arr = string.split(wildcard, ".")
for i in xrange(len(arr)):
s = arr[i]
if s == "*":
arr[i] = r'[\w.]*'
elif string.find(s, "*") > 0:
arr[i] = string.replace(s, "*", r'[\w]*')
s = "^%s$" % string.join(arr, r'\.')
self.patterns.append(re.compile(s))
def setWildcards(self, wildcards):
if type(wildcards) != types.ListType:
wildcards = [wildcards]
self.patterns = []
for wildcard in wildcards:
self.setWildcard(wildcard)
def filter(self, record):
rv = 0
for pat in self.patterns:
m = pat.match(record.name)
if m is not None:
rv = 1
break
return rv
class TagFilter(WildcardFilter):
def filter(self, record):
rv = 0
if isinstance(record.msg, TaggedEvent):
tag = record.msg.tag
else:
tag = record.name
for pat in self.patterns:
m = pat.match(tag)
if m is not None:
rv = 1
break
return rv
def main():
handler = logging.StreamHandler()
root = logging.getLogger("")
root.setLevel(logging.DEBUG)
ab = logging.getLogger("a.b")
abc = logging.getLogger("a.b.c")
root.addHandler(handler)
filter = WildcardFilter("*.b")
handler.addFilter(filter)
ab.info("#1 from a.b") #logged
abc.info("#1 from a.b.c") #not logged
filter.setWildcards("*.b.c")
ab.info("#2 from a.b") #not logged
abc.info("#2 from a.b.c") #logged
filter.setWildcards("*.b*")
ab.info("#3 from a.b") #logged
abc.info("#3 from a.b.c") #not logged
filter.setWildcards("*")
ab.info("#4 from a.b") #logged
abc.info("#4 from a.b.c") #logged
filter.setWildcards("a*")
ab.info("#5 from a.b") #not logged
abc.info("#5 from a.b.c") #not logged
filter.setWildcards("a.*")
ab.info("#6 from a.b") #logged
abc.info("#6 from a.b.c") #logged
filter.setWildcards("*.b.*")
ab.info("#7 from a.b") #not logged
abc.info("#7 from a.b.c") #logged
filter.setWildcards(["*.b", "*.b.*"])
ab.info("#8 from a.b") #logged
abc.info("#8 from a.b.c") #logged
filter.setWildcards(["a.*.c"])
ab.info("#9 from a.b") #not logged
abc.info("#9 from a.b.c") #logged
#Now test filtering with a tagged class
handler.removeFilter(filter)
tagfilter = TagFilter(["*.b", "*.b.*"])
root.addFilter(tagfilter)
root.info(TaggedEvent("a.b", "#10")) #logged
root.info(TaggedEvent("a.c", "#10")) #not logged
root.info(TaggedEvent("a.b.c", "#10")) #logged
root.info(TaggedEvent("a.b.d", "#10")) #logged
if __name__ == "__main__":
import sys
args = sys.argv[1:]
if "-profile" in args:
import profile, pstats
args.remove("-profile")
statf = "log_test21.pro"
profile.run("main()", statf)
stats = pstats.Stats(statf)
stats.strip_dirs().sort_stats('time').print_stats()
else:
main()
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""Test harness for the logging module. Demonstrates the use of different
converters for time(secs) -> time(tuple).
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, time
def main():
handler = logging.StreamHandler()
f1 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S")
f2 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S")
f2.converter = time.gmtime
handler.setFormatter(f1)
root = logging.getLogger("")
root.setLevel(logging.DEBUG)
root.addHandler(handler)
root.info("Something happened! [should be in local time]")
handler.setFormatter(f2)
root.info("Something else happened! [should be in GMT]")
handler.setFormatter(f1)
root.info("Something happened again! [should be in local time]")
logging.Formatter.converter = time.gmtime
root.info("Something else happened again! [should be in GMT]")
logging.Formatter.converter = time.localtime
root.info("Something else happened yet again! [should be in local time]")
if __name__ == "__main__":
main()
@@ -0,0 +1,95 @@
[loggers]
keys=root,area1,area11,area111,area1111,area11111,area111111
[handlers]
keys=console,file,socket,datagram,syslog,NT,SMTP
[formatters]
keys=short,medium,long
[logger_root]
handlers=console
level=DEBUG
[logger_area1]
level=DEBUG
qualname=log02
handlers=file
[logger_area11]
level=INFO
qualname=log02.log03
handlers=socket
[logger_area111]
level=WARN
propagate=0
qualname=log02.log03.log04
handlers=datagram
[logger_area1111]
level=ERROR
qualname=log02.log03.log04.log05
handlers=syslog
[logger_area11111]
level=CRITICAL
qualname=log02.log03.log04.log05.log06
handlers=NT
[logger_area111111]
level=WARN
qualname=log02.log03.log04.log05.log06.log07
handlers=SMTP
[handler_console]
class=StreamHandler
formatter=medium
stream=sys.stdout
args=(sys.stdout,)
[handler_file]
class=FileHandler
level=DEBUG
formatter=long
args=('python.log', 'w')
[handler_socket]
class=handlers.SocketHandler
level=INFO
formatter=medium
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
[handler_datagram]
class=handlers.DatagramHandler
level=WARN
formatter=medium
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
[handler_syslog]
class=handlers.SysLogHandler
level=ERROR
formatter=short
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
[handler_NT]
class=handlers.NTEventLogHandler
level=CRITICAL
formatter=medium
args=('Python Application', '', 'Application')
[handler_SMTP]
class=handlers.SMTPHandler
level=WARN
formatter=long
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
[formatter_short]
format=%(message)s
[formatter_long]
format=%(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
[formatter_medium]
format=%(asctime)s %(levelname)s %(message)s
datefmt=%m-%d-%Y
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests new fileConfig (not yet a complete test).
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.config
def doLog(logger):
logger.debug("Debug")
logger.info("Info")
logger.warning("Warning")
logger.error("Error")
logger.critical("Critical")
def main():
logging.config.fileConfig("log_test3.ini")
logger = logging.getLogger(None)
print "---------------------------------------------------"
print "-- Logging to root; messages appear on console only"
print "---------------------------------------------------"
doLog(logger)
print "----------------------------------------------------------------------"
print "-- Logging to log02; messages appear on console and in file python.log"
print "----------------------------------------------------------------------"
logger = logging.getLogger("log02")
doLog(logger)
print "--------------------------------------------------------------------------"
print "-- Logging to log02.log03; messages appear on console, in file python.log,"
print "-- and at logrecv.py tcp (if running. <= DEBUG messages will not appear)."
print "--------------------------------------------------------------------------"
logger = logging.getLogger("log02.log03")
doLog(logger)
print "-----------------------------------------------------------------------"
print "-- Logging to log02.log03.log04; messages appear only at logrecv.py udp"
print "-- (if running. <= INFO messages will not appear)."
print "-----------------------------------------------------------------------"
logger = logging.getLogger("log02.log03.log04")
doLog(logger)
print "--------------------------------------------------------------------"
print "-- Logging to log02.log03.log04.log05.log06; messages appear at"
print "-- logrecv.py udp (if running. < CRITICAL messages will not appear)."
print "--------------------------------------------------------------------"
logger = logging.getLogger("log02.log03.log04.log05.log06")
doLog(logger)
print "-- All done."
logging.shutdown()
if __name__ == "__main__":
main()
+168
View File
@@ -0,0 +1,168 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests arbitrary logging levels, filtering, and
use of strftime formatting.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging
import locale, sys
locale.setlocale(locale.LC_ALL, '')
def message(s):
sys.stderr.write("%s\n" % s)
#
# First, we define our levels. There can be as many as you want - the only limitations are that
# they should be integers, the lowest should be > 0 and larger values mean less information being
# logged. If you need specific level values which do not fit into these limitations, you can use
# a mapping dictionary to convert between your application levels and the logging system.
#
SILENT = 10
TACITURN = 9
TERSE = 8
EFFUSIVE = 7
SOCIABLE = 6
VERBOSE = 5
TALKATIVE = 4
GARRULOUS = 3
CHATTERBOX = 2
BORING = 1
LEVEL_RANGE = range(BORING, SILENT + 1)
#
# Next, we define names for our levels. You don't need to do this - in which case the system will
# use "Level n" to denote the text for the level.
#
my_logging_levels = {
SILENT : 'Silent',
TACITURN : 'Taciturn',
TERSE : 'Terse',
EFFUSIVE : 'Effusive',
SOCIABLE : 'Sociable',
VERBOSE : 'Verbose',
TALKATIVE : 'Talkative',
GARRULOUS : 'Garrulous',
CHATTERBOX: 'Chatterbox',
BORING : 'Boring',
}
#
# Now, tell the logging system to associate names with our levels.
#
for lvl in my_logging_levels.keys():
logging.addLevelName(lvl, my_logging_levels[lvl])
#
# Now, define a test function which logs an event at each of our levels.
#
def doLog(log):
for lvl in LEVEL_RANGE:
log.log(lvl, "This should only be seen at the '%s' logging level (or lower)", logging.getLevelName(lvl))
#
# Get the root logger and add a console hander to it, when run as a script.
#
log = logging.getLogger("")
if __name__ == "__main__":
hdlr = logging.StreamHandler()
hdlr.setFormatter(logging.Formatter("%(asctime)s %(message)s", "%X")) #date format is as per the locale
log.addHandler(hdlr)
else:
hdlr = log.handlers[0]
#
# Set the logging level to each different value and call the utility function to log events.
# In the output, you should see that each time round the loop, the logging events actually output
# decreases.
#
for lvl in LEVEL_RANGE:
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
log.setLevel(lvl)
doLog(log)
#
# Now, we demonstrate level filtering at the handler level. Tell the handler defined above
# to filter at level 'SOCIABLE', and repeat the above loop. Compare the output from the two runs.
#
hdlr.setLevel(SOCIABLE)
message("-- Filtering at handler level to SOCIABLE --")
for lvl in LEVEL_RANGE:
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
log.setLevel(lvl)
doLog(log)
hdlr.setLevel(0) #turn off level filtering at the handler
#
# Now, let's demonstrate filtering. Suppose for some perverse reason we only want to print out
# all except GARRULOUS messages. Let's create a filter for this purpose...
#
class SpecificLevelFilter(logging.Filter):
def __init__(self, lvl):
self.level = lvl
def filter(self, record):
return self.level != record.levelno
class GarrulousFilter(SpecificLevelFilter):
def __init__(self):
SpecificLevelFilter.__init__(self, GARRULOUS)
garr = GarrulousFilter()
hdlr.addFilter(garr)
message("-- Filtering using GARRULOUS filter --")
for lvl in LEVEL_RANGE:
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
log.setLevel(lvl)
doLog(log)
#
# Now, let's demonstrate filtering at the logger. This time, use a filter which excludes SOCIABLE
# and TACITURN messages. Note that GARRULOUS events are still excluded.
#
class VerySpecificFilter(logging.Filter):
def filter(self, record):
return record.levelno not in [SOCIABLE, TACITURN]
spec = VerySpecificFilter()
log.addFilter(spec)
message("-- Filtering using specific filter for SOCIABLE, TACITURN --")
for lvl in LEVEL_RANGE:
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
log.setLevel(lvl)
doLog(log)
log.removeFilter(spec)
hdlr.removeFilter(garr)
#Undo the one level which clashes...for regression tests
logging.addLevelName(logging.DEBUG, "DEBUG")
#
# Er...that's it for now
#
if __name__ == "__main__":
print "All done."
logging.shutdown()
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests SMTPHandler.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.handlers
MAILHOST = 'beta'
FROM = 'log_test5@yourdomain.com'
TO = ['arkadi_renko']
SUBJECT = 'Test Logging email from Python logging module (non-buffering)'
def main():
log = logging.getLogger("")
log.setLevel(logging.DEBUG)
hdlr = logging.handlers.SMTPHandler(MAILHOST, FROM, TO, SUBJECT)
hdlr.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
log.addHandler(hdlr)
log.info("Test email contents")
log.removeHandler(hdlr)
if __name__ == "__main__":
main()
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests NTEventLogHandler.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.handlers
def main():
ntl = logging.handlers.NTEventLogHandler("Python Logging Test")
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
logger.addHandler(ntl)
logger.debug("This is a '%s' message", "Debug")
logger.info("This is a '%s' message", "Info")
logger.warning("This is a '%s' message", "Warning")
logger.error("This is a '%s' message", "Error")
logger.critical("This is a '%s' message", "Critical")
try:
x = 4 / 0
except:
logger.info("This is an %s (or should that be %s?)", "informational exception", "exceptional information", exc_info=1)
logger.exception("This is the same stuff, via a %s", "exception() call")
logger.removeHandler(ntl)
if __name__ == "__main__":
main()
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests MemoryHandler.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import sys, logging, logging.handlers
def message(s):
sys.stderr.write("%s\n" % s)
sh = logging.StreamHandler()
mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh)
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
logger.addHandler(mh)
message("-- logging at DEBUG, nothing should be seen yet --")
logger.debug("Debug message")
message("-- logging at INFO, nothing should be seen yet --")
logger.info("Info message")
message("-- logging at WARNING, 3 messages should be seen --")
logger.warning("Warning message")
for i in xrange(102):
message("-- logging %d at level INFO, messages should be seen every 10 events --" % i)
logger.info("Info index = %d", i)
sh.close()
mh.close()
logger.removeHandler(mh)
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests FileHandler rollover.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.handlers
import locale
locale.setlocale(locale.LC_ALL, '')
sequence = 0
def doLog(logger):
global sequence
sequence = sequence + 1
logger.debug("%6d This message should be at level %d - %s", sequence,\
logging.DEBUG, logging.getLevelName(logging.DEBUG))
sequence = sequence + 1
logger.info("%6d This message should be at level %d - %s", sequence,
logging.INFO, logging.getLevelName(logging.INFO))
sequence = sequence + 1
logger.warning("%6d This message should be at level %d - %s", sequence,\
logging.WARNING, logging.getLevelName(logging.WARNING))
sequence = sequence + 1
logger.error("%6d This message should be at level %d - %s", sequence,\
logging.ERROR, logging.getLevelName(logging.ERROR))
sequence = sequence + 1
logger.critical("%6d This message should be at level %d - %s", sequence,\
logging.CRITICAL, logging.getLevelName(logging.CRITICAL))
def main():
logger = logging.getLogger("") #root logger
logger.setLevel(logging.DEBUG)
if __name__ == "__main__":
logname = "rollover.log"
else:
logname = "log_test_rollover.log"
hdlr = logging.handlers.RotatingFileHandler(logname, "a", 5000, 3)
if __name__ == "__main__":
fmt = logging.Formatter("%(asctime)s %(levelname)-5s %(message)s", "%x %X")
hdlr.setFormatter(fmt)
logger.addHandler(hdlr)
for i in xrange(100):
doLog(logger)
logger.removeHandler(hdlr)
if __name__ == "__main__":
main()
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. Tests BufferingHandler, BufferingFormatter.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
import logging, logging.handlers
class XMLFormatter(logging.BufferingFormatter):
"""
A formatter which formats a set of records using XML, using an example DTD called "logging.dtd".
"""
def __init__(self):
fmtstr = """
<event name="%(name)s" level="%(levelno)d" filename="%(filename)s" lineno="%(lineno)d">
<message>%(message)s</message>
</event>"""
logging.BufferingFormatter.__init__(self, logging.Formatter(fmtstr))
# def formatHeader(self, records):
# return """
#<?xml version="1.0" ?><!DOCTYPE eventSet SYSTEM "logging.dtd">
#<eventSet xmlns="http://www.red-dove.com/logging">"""
#
# def formatFooter(self, records):
# return "</eventSet>"
class XMLHandler(logging.handlers.BufferingHandler):
def __init__(self, capacity):
logging.handlers.BufferingHandler.__init__(self, capacity)
self.setFormatter(XMLFormatter())
def flush(self):
if len(self.buffer) > 0:
file = open("events.xml","w")
file.write(self.formatter.format(self.buffer))
file.close()
self.buffer = []
def main():
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
xh = XMLHandler(10)
logger.addHandler(xh)
for i in xrange(100):
logger.info("Info index = %d", i)
xh.close()
logger.removeHandler(xh)
if __name__ == "__main__":
main()
@@ -0,0 +1,180 @@
[loggers]
keys=root,log02,log03,log04,log05,log06,log07
[handlers]
keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
[formatters]
keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
[logger_root]
level=NOTSET
propagate=1
channel=
parent=
qualname=(root)
handlers=hand01
[logger_log02]
level=DEBUG
propagate=1
channel=log02
parent=(root)
qualname=log02
handlers=hand02
[logger_log03]
level=INFO
propagate=1
channel=log03
parent=log02
qualname=log02.log03
handlers=hand03
[logger_log04]
level=WARN
propagate=0
channel=log04
parent=log03
qualname=log02.log03.log04
handlers=hand04
[logger_log05]
level=ERROR
propagate=1
channel=log05
parent=log04
qualname=log02.log03.log04.log05
handlers=hand05
[logger_log06]
level=CRITICAL
propagate=1
channel=log06
parent=log05
qualname=log02.log03.log04.log05.log06
handlers=hand06
[logger_log07]
level=WARN
propagate=1
channel=log07
parent=log06
qualname=log02.log03.log04.log05.log06.log07
handlers=hand07
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
stream=sys.stdout
args=(sys.stdout,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form02
filename=python.log
mode=w
args=('python.log', 'w')
[handler_hand03]
class=handlers.SocketHandler
level=INFO
formatter=form03
host=localhost
port=handlers.DEFAULT_TCP_LOGGING_PORT
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
[handler_hand04]
class=handlers.DatagramHandler
level=WARN
formatter=form04
host=localhost
port=handlers.DEFAULT_UDP_LOGGING_PORT
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
[handler_hand05]
class=handlers.SysLogHandler
level=ERROR
formatter=form05
host=localhost
port=handlers.SYSLOG_UDP_PORT
facility=LOG_USER
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
[handler_hand06]
class=handlers.NTEventLogHandler
level=CRITICAL
formatter=form06
appname=Python Application
dllname=
logtype=Application
args=('Python Application', '', 'Application')
[handler_hand07]
class=handlers.SMTPHandler
level=WARN
formatter=form07
host=localhost
port=25
from=from@abc
to=user1@abc,user2@xyz
subject=Logger Subject
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
[handler_hand08]
class=handlers.MemoryHandler
level=NOTSET
formatter=form08
capacity=10
flushlevel=ERROR
target=
args=(10, ERROR)
[handler_hand09]
class=handlers.HTTPHandler
level=NOTSET
formatter=form09
host=localhost
port=9022
url=/log
method=GET
args=('localhost:9022', '/log', 'GET')
[formatter_form01]
format=F1 %(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form02]
format=F2 %(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
datefmt=
[formatter_form03]
format=F3 %(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form04]
format=%(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form05]
format=F5 %(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form06]
format=F6 %(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form07]
format=F7 %(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form08]
format=F8 %(asctime)s %(levelname)s %(message)s
datefmt=
[formatter_form09]
format=F9 %(asctime)s %(levelname)s %(message)s
datefmt=
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Author: Vinay Sajip, Red Dove Consultants Ltd. http://www.red-dove.com/ -->
<!-- THIS IS ONLY A VERY SIMPLE EXAMPLE -->
<!ELEMENT logging:events (logging:event*)>
<!ELEMENT logging:event (logging:message)>
<!ATTLIST logging:event
name CDATA #REQUIRED
level CDATA #REQUIRED
created CDATA #IMPLIED
filename CDATA #IMPLIED
lineno CDATA #IMPLIED
>
<!ELEMENT logging:message (#PCDATA)>
@@ -0,0 +1,5 @@
<?xml version="1.0" ?>
<!DOCTYPE events SYSTEM "logging.dtd" [<!ENTITY data SYSTEM "events.xml">]>
<events xmlns="http://www.red-dove.com/logging">
&data;
</events>
@@ -0,0 +1,36 @@
[loggers]
keys=root
[handlers]
keys=hand01,hand02
[formatters]
keys=form01
[logger_root]
level=NOTSET
propagate=1
channel=
parent=
qualname=(root)
handlers=hand01,hand02
[handler_hand01]
class=FileHandler
level=NOTSET
formatter=form01
filename=logrecv.log
mode=w
args=('logrecv.log', 'w')
[handler_hand02]
class=StreamHandler
level=NOTSET
formatter=form01
stream=sys.stderr
args=(sys.stderr,)
[formatter_form01]
format=%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s
datefmt=
+443
View File
@@ -0,0 +1,443 @@
#! /usr/bin/env python
#
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
"""
Simple socket-based logging event receiver for use with "logging.py" logging
module.
Should work under Python versions >= 1.5.2, except that source line information
is not available unless 'inspect' is.
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
"""
from select import select
import sys, string, struct, types, cPickle, socket
import logging, logging.handlers, logging.config
TIMEOUT = 10
if sys.platform == "win32":
RESET_ERROR = 10054
else:
RESET_ERROR = 0 #FIXME get correct value for Unix...
logging.raiseExceptions = 1
#
# TCP receiver
#
from SocketServer import ThreadingTCPServer, StreamRequestHandler
class LogRecordStreamHandler(StreamRequestHandler):
"""
Handler for a streaming logging request. It basically logs the record
using whatever logging policy is configured locally.
"""
def handle(self):
"""
Handle multiple requests - each expected to be a 4-byte length,
followed by the LogRecord in pickle format. Logs the record
according to whatever policy is configured locally.
"""
while 1:
try:
chunk = self.connection.recv(4)
if len(chunk) < 4:
break
slen = struct.unpack(">L", chunk)[0]
chunk = self.connection.recv(slen)
while len(chunk) < slen:
chunk = chunk + self.connection.recv(slen - len(chunk))
obj = self.unPickle(chunk)
record = logging.makeLogRecord(obj)
self.handleLogRecord(record)
except socket.error, e:
if type(e.args) != types.TupleType:
raise
else:
errcode = e.args[0]
if errcode != RESET_ERROR:
raise
break
def unPickle(self, data):
return cPickle.loads(data)
def handleLogRecord(self, record):
#if a name is specified, we use the named logger rather than the one
#implied by the record. This is so test harnesses don't get into
#endless loops (particularly log_test.py, which has this code and the
#client code in the same Python instance)
if self.server.logname is not None:
name = self.server.logname
else:
name = record.name
logger = logging.getLogger(name)
logger.handle(record)
class LogRecordSocketReceiver(ThreadingTCPServer):
"""
A simple-minded TCP socket-based logging receiver suitable for test
purposes.
"""
allow_reuse_address = 1
def __init__(self, host='localhost', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
handler=LogRecordStreamHandler):
ThreadingTCPServer.__init__(self, (host, port), handler)
self.abort = 0
self.timeout = 1
self.logname = None
def serve_until_stopped(self):
import select
abort = 0
while not abort:
rd, wr, ex = select.select([self.socket.fileno()],
[], [],
self.timeout)
if rd:
self.handle_request()
abort = self.abort
#
# UDP receiver
#
from SocketServer import ThreadingUDPServer, DatagramRequestHandler
class LogRecordDatagramHandler(DatagramRequestHandler):
"""
Handler for a datagram logging request. It basically logs the record using
whatever logging policy is configured locally.
"""
def handle(self):
chunk = self.packet
slen = struct.unpack(">L", chunk[:4])[0]
chunk = chunk[4:]
assert len(chunk) == slen
obj = self.unPickle(chunk)
record = logging.LogRecord(None, None, "", 0, "", (), None)
record.__dict__.update(obj)
self.handleLogRecord(record)
def unPickle(self, data):
return cPickle.loads(data)
def handleLogRecord(self, record):
#if a name is specified, we use the named logger rather than the one
#implied by the record. This is so test harnesses don't get into
#endless loops (particularly log_test.py, which has this code and the
#client code in the same Python instance)
if self.server.logname is not None:
name = self.server.logname
else:
name = record.name
logger = logging.getLogger(name)
logger.handle(record)
def finish(self):
pass
class LogRecordDatagramReceiver(ThreadingUDPServer):
"""
A simple-minded UDP datagram-based logging receiver suitable for test
purposes.
"""
allow_reuse_address = 1
def __init__(self, host='localhost', port=logging.handlers.DEFAULT_UDP_LOGGING_PORT,
handler=LogRecordDatagramHandler):
ThreadingUDPServer.__init__(self, (host, port), handler)
self.abort = 0
self.timeout = 1
self.logname = None
def serve_until_stopped(self):
import select
abort = 0
while not abort:
rd, wr, ex = select.select([self.socket.fileno()],
[], [],
self.timeout)
if rd:
self.handle_request()
abort = self.abort
#
# HTTP receiver
#
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import cgi
class LogRecordHTTPHandler(BaseHTTPRequestHandler):
def makeDict(self, fs):
dict = {}
for mfs in fs.list:
dict[mfs.name] = mfs.value
for key in ["args", "exc_info", "exc_text", "lineno", "msecs", "created",
"thread", "levelno", "relativeCreated"]:
if dict.has_key(key):
dict[key] = eval(dict[key])
return dict
def do_GET(self):
"""Serve a GET request."""
sts = "OK"
env = { 'REQUEST_METHOD' : 'GET'}
try:
i = string.find(self.path, '?')
if i >= 0:
env['QUERY_STRING'] = self.path[i + 1:]
fs = cgi.FieldStorage(environ=env)
dict = self.makeDict(fs)
record = logging.LogRecord(None, None, "", 0, "", (), None)
record.__dict__.update(dict)
self.handleLogRecord(record)
except Exception, e:
sts = "ERROR"
raise
self.send_head()
self.wfile.write("GET %s" % sts)
def handleLogRecord(self, record):
#if a name is specified, we use the named logger rather than the one
#implied by the record. This is so test harnesses don't get into
#endless loops (particularly log_test.py, which has this code and the
#client code in the same Python instance)
if self.server.logname is not None:
name = self.server.logname
else:
name = record.name
logger = logging.getLogger(name)
logger.handle(record)
def do_HEAD(self):
"""Serve a HEAD request."""
self.send_head()
def do_POST(self):
"""Serve a POST request."""
sts = "OK"
env = { 'REQUEST_METHOD' : 'POST'}
try:
length = self.headers.getheader('content-length')
if length:
env['CONTENT_LENGTH'] = length
#print self.headers
i = string.find(self.path, '?')
if i >= 0:
env['QUERY_STRING'] = self.path[i + 1:]
fs = cgi.FieldStorage(fp=self.rfile, environ=env)
dict = self.makeDict(fs)
record = logging.LogRecord(None, None, "", 0, "", (), None)
record.__dict__.update(dict)
self.handleLogRecord(record)
except Exception, e:
print e
sys.stdout.flush()
sts = "ERROR"
raise
self.send_head()
self.wfile.write("POST %s" % sts)
def send_head(self):
"""Common code for GET and HEAD commands.
This sends the response code and MIME headers.
Return value is either a file object (which has to be copied
to the outputfile by the caller unless the command was HEAD,
and must be closed by the caller under all circumstances), or
None, in which case the caller has nothing further to do.
"""
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
def log_message(self, *args):
#comment out the following line if you don't want to show requests
#apply(BaseHTTPRequestHandler.log_message, (self,) + args)
pass
class LogRecordHTTPReceiver(HTTPServer):
def __init__(self, host='localhost', port=logging.handlers.DEFAULT_HTTP_LOGGING_PORT,
handler=LogRecordHTTPHandler):
HTTPServer.__init__(self, (host, port), handler)
self.abort = 0
self.timeout = 1
self.logname = None
def serve_until_stopped(self):
import select
abort = 0
while not abort:
rd, wr, ex = select.select([self.socket.fileno()],
[], [],
self.timeout)
if rd:
self.handle_request()
abort = self.abort
#
# SOAP receiver
#
try:
from ZSI import dispatch
logname = None
def log(args, created, exc_info, exc_text, filename, levelname, levelno, lineno, module, msecs, msg, name, pathname, process, relativeCreated, thread):
record = logging.LogRecord(None, None, "", 0, "", (), None)
record.args = eval(args)
record.exc_info = eval(exc_info)
record.exc_text = eval(exc_text)
record.created = created
record.filename = filename
record.module = module
record.levelname = levelname
record.lineno = lineno
record.levelno = levelno
record.msecs = msecs
record.msg = msg
record.name = name
record.pathname = pathname
record.process = process
record.relativeCreated = relativeCreated
record.thread = thread
#if a name is specified, we use the named logger rather than the one
#implied by the record. This is so test harnesses don't get into
#endless loops (particularly log_test.py, which has this code and the
#client code in the same Python instance)
if logname is not None:
lname = logname
else:
lname = name
logger = logging.getLogger(lname)
logger.handle(record)
class MySOAPRequestHandler(dispatch.SOAPRequestHandler):
def log_message(self, *args):
#comment out the following line if you don't want to show requests
#apply(BaseHTTPRequestHandler.log_message, (self,) + args)
pass
class SOAPServer(HTTPServer):
def __init__(self, port=logging.handlers.DEFAULT_SOAP_LOGGING_PORT):
address = ('', port)
HTTPServer.__init__(self, address, MySOAPRequestHandler)
self.abort = 0
self.timeout = 1
self.logname = None
self.docstyle = 0
self.nsdict = {}
self.typesmodule = None
self.rpc = 1
self.modules = (sys.modules["__main__"],)
def serve_until_stopped(self):
import select
abort = 0
while not abort:
rd, wr, ex = select.select([self.socket.fileno()],
[], [],
self.timeout)
if rd:
global logname
logname = self.logname
self.handle_request()
abort = self.abort
except ImportError:
"Import failed"
SOAPServer = None
def runTCP(tcpserver=None):
if not tcpserver:
tcpserver = LogRecordSocketReceiver()
print "About to start TCP server..."
tcpserver.serve_until_stopped()
def runUDP(udpserver=None):
if not udpserver:
udpserver = LogRecordDatagramReceiver()
print "About to start UDP server..."
udpserver.serve_until_stopped()
def runHTTP(httpserver=None):
if not httpserver:
httpserver = LogRecordHTTPReceiver()
print "About to start HTTP server..."
httpserver.serve_until_stopped()
def runSOAP(soapserver=None):
if not SOAPServer:
print "Sorry, ZSI is not available. Install PyXML-0.6.6 and ZSI first."
print "See README.txt and python_logging.html for more information."
else:
if not soapserver:
soapserver = SOAPServer()
print "About to start SOAP server..."
soapserver.serve_until_stopped()
FORMAT_STR = "%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"
if __name__ == "__main__":
if (len(sys.argv) < 2) or not (string.lower(sys.argv[1]) in \
["udp", "tcp", "http", "soap"]):
print "usage: logrecv.py [UDP|TCP|HTTP|SOAP]"
else:
#logging.basicConfig()
logging.config.fileConfig("logrecv.ini")
# both = string.lower(sys.argv[1]) == "both"
# hdlr = logging.FileHandler("test.log")
# hdlr.setFormatter(logging.Formatter(FORMAT_STR))
# logging.getLogger("").addHandler(hdlr)
# if both:
# import threading
# tcpthread = threading.Thread(target=runTCP)
# udpthread = threading.Thread(target=runUDP)
# tcpthread.start()
# udpthread.start()
# tcpthread.join()
# udpthread.join()
# else:
# tcp = string.lower(sys.argv[1]) == "tcp"
# if tcp:
# runTCP()
# else:
# runUDP()
arg = string.lower(sys.argv[1])
if arg == "tcp":
runTCP()
elif arg == "udp":
runUDP()
elif arg == "http":
runHTTP()
elif arg == "soap":
runSOAP()
@@ -0,0 +1,13 @@
import logging, mymodule
logging.basicConfig()
log = logging.getLogger("MyApp")
log.setLevel(logging.DEBUG) #set verbosity to show all messages of severity >= DEBUG
log.info("Starting my app")
try:
mymodule.doIt()
except Exception, e:
log.exception("There was a problem.")
log.info("Ending my app")
@@ -0,0 +1,8 @@
import logging
log = logging.getLogger("MyModule")
def doIt():
log.debug("Doin' stuff...")
#do stuff...
raise TypeError, "Bogus type error for testing"
@@ -0,0 +1,566 @@
-- log_test0 begin --------------------------------------------------------
CRITICAL:ERR:Message 0
ERROR:ERR:Message 1
CRITICAL:INF:Message 2
ERROR:INF:Message 3
WARNING:INF:Message 4
INFO:INF:Message 5
CRITICAL:INF.UNDEF:Message 6
ERROR:INF.UNDEF:Message 7
WARNING:INF.UNDEF:Message 8
INFO:INF.UNDEF:Message 9
CRITICAL:INF.ERR:Message 10
ERROR:INF.ERR:Message 11
CRITICAL:INF.ERR.UNDEF:Message 12
ERROR:INF.ERR.UNDEF:Message 13
CRITICAL:DEB:Message 14
ERROR:DEB:Message 15
WARNING:DEB:Message 16
INFO:DEB:Message 17
DEBUG:DEB:Message 18
CRITICAL:UNDEF:Message 19
ERROR:UNDEF:Message 20
WARNING:UNDEF:Message 21
INFO:UNDEF:Message 22
CRITICAL:INF.BADPARENT.UNDEF:Message 23
CRITICAL:INF.BADPARENT:Message 24
INFO:INF:Messages should bear numbers 0 through 24.
-- log_test0 end --------------------------------------------------------
-- log_test2 begin --------------------------------------------------------
CRITICAL:ERR:Message 0
ERROR:ERR:Message 1
CRITICAL:INF:Message 2
ERROR:INF:Message 3
WARNING:INF:Message 4
INFO:INF:Message 5
CRITICAL:INF.UNDEF:Message 6
ERROR:INF.UNDEF:Message 7
WARNING:INF.UNDEF:Message 8
INFO:INF.UNDEF:Message 9
CRITICAL:INF.ERR:Message 10
ERROR:INF.ERR:Message 11
CRITICAL:INF.ERR.UNDEF:Message 12
ERROR:INF.ERR.UNDEF:Message 13
CRITICAL:DEB:Message 14
ERROR:DEB:Message 15
WARNING:DEB:Message 16
INFO:DEB:Message 17
DEBUG:DEB:Message 18
CRITICAL:UNDEF:Message 19
ERROR:UNDEF:Message 20
WARNING:UNDEF:Message 21
INFO:UNDEF:Message 22
CRITICAL:INF.BADPARENT.UNDEF:Message 23
CRITICAL:INF.BADPARENT:Message 24
INFO:INF:Messages should bear numbers 0 through 24.
-- log_test2 end --------------------------------------------------------
CRITICAL:ERR:Message 0
ERROR:ERR:Message 1
CRITICAL:INF:Message 2
ERROR:INF:Message 3
WARNING:INF:Message 4
INFO:INF:Message 5
CRITICAL:INF.UNDEF:Message 6
ERROR:INF.UNDEF:Message 7
WARNING:INF.UNDEF:Message 8
INFO:INF.UNDEF:Message 9
CRITICAL:INF.ERR:Message 10
ERROR:INF.ERR:Message 11
CRITICAL:INF.ERR.UNDEF:Message 12
ERROR:INF.ERR.UNDEF:Message 13
CRITICAL:DEB:Message 14
ERROR:DEB:Message 15
WARNING:DEB:Message 16
INFO:DEB:Message 17
DEBUG:DEB:Message 18
CRITICAL:UNDEF:Message 19
ERROR:UNDEF:Message 20
WARNING:UNDEF:Message 21
INFO:UNDEF:Message 22
CRITICAL:INF.BADPARENT.UNDEF:Message 23
CRITICAL:INF.BADPARENT:Message 24
INFO:INF:Messages should bear numbers 0 through 24.
-- log_test4 begin --------------------------------------------------------
-- setting logging level to 'Boring' -----
Boring:root:This should only be seen at the 'Boring' logging level (or lower)
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Chatterbox' -----
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Garrulous' -----
Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Talkative' -----
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Verbose' -----
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Sociable' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Effusive' -----
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Terse' -----
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Taciturn' -----
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Silent' -----
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- Filtering at handler level to SOCIABLE --
-- setting logging level to 'Boring' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Chatterbox' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Garrulous' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Talkative' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Verbose' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Sociable' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Effusive' -----
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Terse' -----
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Taciturn' -----
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Silent' -----
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- Filtering using GARRULOUS filter --
-- setting logging level to 'Boring' -----
Boring:root:This should only be seen at the 'Boring' logging level (or lower)
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Chatterbox' -----
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Garrulous' -----
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Talkative' -----
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Verbose' -----
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Sociable' -----
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Effusive' -----
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Terse' -----
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Taciturn' -----
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Silent' -----
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- Filtering using specific filter for SOCIABLE, TACITURN --
-- setting logging level to 'Boring' -----
Boring:root:This should only be seen at the 'Boring' logging level (or lower)
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Chatterbox' -----
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Garrulous' -----
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Talkative' -----
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Verbose' -----
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Sociable' -----
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Effusive' -----
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Terse' -----
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Taciturn' -----
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- setting logging level to 'Silent' -----
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
-- log_test4 end --------------------------------------------------------
-- log_test7 begin --------------------------------------------------------
-- logging at DEBUG, nothing should be seen yet --
-- logging at INFO, nothing should be seen yet --
-- logging at WARNING, 3 messages should be seen --
Debug message
Info message
Warning message
-- logging 0 at level INFO, messages should be seen every 10 events --
-- logging 1 at level INFO, messages should be seen every 10 events --
-- logging 2 at level INFO, messages should be seen every 10 events --
-- logging 3 at level INFO, messages should be seen every 10 events --
-- logging 4 at level INFO, messages should be seen every 10 events --
-- logging 5 at level INFO, messages should be seen every 10 events --
-- logging 6 at level INFO, messages should be seen every 10 events --
-- logging 7 at level INFO, messages should be seen every 10 events --
-- logging 8 at level INFO, messages should be seen every 10 events --
-- logging 9 at level INFO, messages should be seen every 10 events --
Info index = 0
Info index = 1
Info index = 2
Info index = 3
Info index = 4
Info index = 5
Info index = 6
Info index = 7
Info index = 8
Info index = 9
-- logging 10 at level INFO, messages should be seen every 10 events --
-- logging 11 at level INFO, messages should be seen every 10 events --
-- logging 12 at level INFO, messages should be seen every 10 events --
-- logging 13 at level INFO, messages should be seen every 10 events --
-- logging 14 at level INFO, messages should be seen every 10 events --
-- logging 15 at level INFO, messages should be seen every 10 events --
-- logging 16 at level INFO, messages should be seen every 10 events --
-- logging 17 at level INFO, messages should be seen every 10 events --
-- logging 18 at level INFO, messages should be seen every 10 events --
-- logging 19 at level INFO, messages should be seen every 10 events --
Info index = 10
Info index = 11
Info index = 12
Info index = 13
Info index = 14
Info index = 15
Info index = 16
Info index = 17
Info index = 18
Info index = 19
-- logging 20 at level INFO, messages should be seen every 10 events --
-- logging 21 at level INFO, messages should be seen every 10 events --
-- logging 22 at level INFO, messages should be seen every 10 events --
-- logging 23 at level INFO, messages should be seen every 10 events --
-- logging 24 at level INFO, messages should be seen every 10 events --
-- logging 25 at level INFO, messages should be seen every 10 events --
-- logging 26 at level INFO, messages should be seen every 10 events --
-- logging 27 at level INFO, messages should be seen every 10 events --
-- logging 28 at level INFO, messages should be seen every 10 events --
-- logging 29 at level INFO, messages should be seen every 10 events --
Info index = 20
Info index = 21
Info index = 22
Info index = 23
Info index = 24
Info index = 25
Info index = 26
Info index = 27
Info index = 28
Info index = 29
-- logging 30 at level INFO, messages should be seen every 10 events --
-- logging 31 at level INFO, messages should be seen every 10 events --
-- logging 32 at level INFO, messages should be seen every 10 events --
-- logging 33 at level INFO, messages should be seen every 10 events --
-- logging 34 at level INFO, messages should be seen every 10 events --
-- logging 35 at level INFO, messages should be seen every 10 events --
-- logging 36 at level INFO, messages should be seen every 10 events --
-- logging 37 at level INFO, messages should be seen every 10 events --
-- logging 38 at level INFO, messages should be seen every 10 events --
-- logging 39 at level INFO, messages should be seen every 10 events --
Info index = 30
Info index = 31
Info index = 32
Info index = 33
Info index = 34
Info index = 35
Info index = 36
Info index = 37
Info index = 38
Info index = 39
-- logging 40 at level INFO, messages should be seen every 10 events --
-- logging 41 at level INFO, messages should be seen every 10 events --
-- logging 42 at level INFO, messages should be seen every 10 events --
-- logging 43 at level INFO, messages should be seen every 10 events --
-- logging 44 at level INFO, messages should be seen every 10 events --
-- logging 45 at level INFO, messages should be seen every 10 events --
-- logging 46 at level INFO, messages should be seen every 10 events --
-- logging 47 at level INFO, messages should be seen every 10 events --
-- logging 48 at level INFO, messages should be seen every 10 events --
-- logging 49 at level INFO, messages should be seen every 10 events --
Info index = 40
Info index = 41
Info index = 42
Info index = 43
Info index = 44
Info index = 45
Info index = 46
Info index = 47
Info index = 48
Info index = 49
-- logging 50 at level INFO, messages should be seen every 10 events --
-- logging 51 at level INFO, messages should be seen every 10 events --
-- logging 52 at level INFO, messages should be seen every 10 events --
-- logging 53 at level INFO, messages should be seen every 10 events --
-- logging 54 at level INFO, messages should be seen every 10 events --
-- logging 55 at level INFO, messages should be seen every 10 events --
-- logging 56 at level INFO, messages should be seen every 10 events --
-- logging 57 at level INFO, messages should be seen every 10 events --
-- logging 58 at level INFO, messages should be seen every 10 events --
-- logging 59 at level INFO, messages should be seen every 10 events --
Info index = 50
Info index = 51
Info index = 52
Info index = 53
Info index = 54
Info index = 55
Info index = 56
Info index = 57
Info index = 58
Info index = 59
-- logging 60 at level INFO, messages should be seen every 10 events --
-- logging 61 at level INFO, messages should be seen every 10 events --
-- logging 62 at level INFO, messages should be seen every 10 events --
-- logging 63 at level INFO, messages should be seen every 10 events --
-- logging 64 at level INFO, messages should be seen every 10 events --
-- logging 65 at level INFO, messages should be seen every 10 events --
-- logging 66 at level INFO, messages should be seen every 10 events --
-- logging 67 at level INFO, messages should be seen every 10 events --
-- logging 68 at level INFO, messages should be seen every 10 events --
-- logging 69 at level INFO, messages should be seen every 10 events --
Info index = 60
Info index = 61
Info index = 62
Info index = 63
Info index = 64
Info index = 65
Info index = 66
Info index = 67
Info index = 68
Info index = 69
-- logging 70 at level INFO, messages should be seen every 10 events --
-- logging 71 at level INFO, messages should be seen every 10 events --
-- logging 72 at level INFO, messages should be seen every 10 events --
-- logging 73 at level INFO, messages should be seen every 10 events --
-- logging 74 at level INFO, messages should be seen every 10 events --
-- logging 75 at level INFO, messages should be seen every 10 events --
-- logging 76 at level INFO, messages should be seen every 10 events --
-- logging 77 at level INFO, messages should be seen every 10 events --
-- logging 78 at level INFO, messages should be seen every 10 events --
-- logging 79 at level INFO, messages should be seen every 10 events --
Info index = 70
Info index = 71
Info index = 72
Info index = 73
Info index = 74
Info index = 75
Info index = 76
Info index = 77
Info index = 78
Info index = 79
-- logging 80 at level INFO, messages should be seen every 10 events --
-- logging 81 at level INFO, messages should be seen every 10 events --
-- logging 82 at level INFO, messages should be seen every 10 events --
-- logging 83 at level INFO, messages should be seen every 10 events --
-- logging 84 at level INFO, messages should be seen every 10 events --
-- logging 85 at level INFO, messages should be seen every 10 events --
-- logging 86 at level INFO, messages should be seen every 10 events --
-- logging 87 at level INFO, messages should be seen every 10 events --
-- logging 88 at level INFO, messages should be seen every 10 events --
-- logging 89 at level INFO, messages should be seen every 10 events --
Info index = 80
Info index = 81
Info index = 82
Info index = 83
Info index = 84
Info index = 85
Info index = 86
Info index = 87
Info index = 88
Info index = 89
-- logging 90 at level INFO, messages should be seen every 10 events --
-- logging 91 at level INFO, messages should be seen every 10 events --
-- logging 92 at level INFO, messages should be seen every 10 events --
-- logging 93 at level INFO, messages should be seen every 10 events --
-- logging 94 at level INFO, messages should be seen every 10 events --
-- logging 95 at level INFO, messages should be seen every 10 events --
-- logging 96 at level INFO, messages should be seen every 10 events --
-- logging 97 at level INFO, messages should be seen every 10 events --
-- logging 98 at level INFO, messages should be seen every 10 events --
-- logging 99 at level INFO, messages should be seen every 10 events --
Info index = 90
Info index = 91
Info index = 92
Info index = 93
Info index = 94
Info index = 95
Info index = 96
Info index = 97
Info index = 98
Info index = 99
-- logging 100 at level INFO, messages should be seen every 10 events --
-- logging 101 at level INFO, messages should be seen every 10 events --
Info index = 100
Info index = 101
-- log_test7 end --------------------------------------------------------
-- log_test8 begin --------------------------------------------------------
-- log_test8 end --------------------------------------------------------
-- log_test9 begin --------------------------------------------------------
-- log_test9 end --------------------------------------------------------
-- log_test10 begin --------------------------------------------------------
logger not derived from logging.Logger: NotALogger
INFO:mylogger:Starting...
DEBUG:mylogger:Debug message not in exception handler (no traceback)
INFO:mylogger:About to throw exception...
DEBUG:mylogger:Debug message inside exception handler (traceback)
Traceback (most recent call last):
File "C:\Projects\RDC\Python\packages\logging\test\log_test10.py", line 77, in run
print "7" + 4
TypeError: cannot concatenate 'str' and 'int' objects
INFO:mylogger:Done.
-- log_test10 end --------------------------------------------------------
-- log_test12 begin --------------------------------------------------------
INFO:log_test12:Jackdaws love my big sphinx of quartz
INFO:log_test12:Jackdaws love my big sphinx of quartz
DEBUG:log_test12:Pack my box with twelve dozen liquor jugs
DEBUG:log_test12:Pack my box with twelve dozen liquor jugs
-- log_test12 end --------------------------------------------------------
-- log_test13 begin --------------------------------------------------------
INFO:log_test13:Jackdaws love my big sphinx of quartz
DEBUG:log_test13:Pack my box with five dozen liquor jugs
-- log_test13 end --------------------------------------------------------
-- log_test15 begin --------------------------------------------------------
Unfiltered...
INFO:a:Info 1
INFO:a.b:Info 2
INFO:a.c:Info 3
INFO:a.b.c:Info 4
INFO:a.b.c.d:Info 5
INFO:a.bb.c:Info 6
INFO:b:Info 7
INFO:b.a:Info 8
INFO:c.a.b:Info 9
INFO:a.bb:Info 10
Filtered with 'a.b'...
INFO:a.b:Info 2
INFO:a.b.c:Info 4
INFO:a.b.c.d:Info 5
-- log_test15 end --------------------------------------------------------
@@ -0,0 +1,24 @@
About to start TCP server...
About to start UDP server...
About to start HTTP server...
About to start SOAP server...
-- log_test0 begin --------------------------------------------------------
-- log_test0 end --------------------------------------------------------
-- log_test2 begin --------------------------------------------------------
-- log_test2 end --------------------------------------------------------
-- log_test4 begin --------------------------------------------------------
-- log_test4 end --------------------------------------------------------
-- log_test7 begin --------------------------------------------------------
-- log_test7 end --------------------------------------------------------
-- log_test8 begin --------------------------------------------------------
-- log_test8 end --------------------------------------------------------
-- log_test9 begin --------------------------------------------------------
-- log_test9 end --------------------------------------------------------
-- log_test10 begin --------------------------------------------------------
-- log_test10 end --------------------------------------------------------
-- log_test12 begin --------------------------------------------------------
-- log_test12 end --------------------------------------------------------
-- log_test13 begin --------------------------------------------------------
-- log_test13 end --------------------------------------------------------
-- log_test15 begin --------------------------------------------------------
-- log_test15 end --------------------------------------------------------
@@ -0,0 +1,60 @@
[loggers]
keys=root,log02,log03,log04,log05
[handlers]
keys=hand01
[formatters]
keys=form01
[logger_root]
level=WARN
propagate=1
channel=
parent=
qualname=(root)
handlers=hand01
[logger_log02]
level=WARN
propagate=1
channel=A
parent=(root)
qualname=A
handlers=
[logger_log03]
level=WARN
propagate=1
channel=B
parent=log02
qualname=A.B
handlers=
[logger_log04]
level=WARN
propagate=1
channel=C
parent=log03
qualname=A.B.C
handlers=
[logger_log05]
level=WARN
propagate=1
channel=D
parent=log04
qualname=A.B.C.D
handlers=
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
stream=sys.stderr
args=(sys.stderr,)
[formatter_form01]
format=warn.ini %(name)s %(levelname)s %(message)s
datefmt=
+11
View File
@@ -0,0 +1,11 @@
#============================================================================
# Install the logging package from python 2.3 if not present.
#============================================================================
import os
try:
import logging
except ImportError:
print 'logging package not found: installing'
os.chdir('logging-0.4.9.2')
execfile('setup.py')
+4
View File
@@ -1,5 +1,6 @@
from distutils.core import setup, Extension
import os
XEN_ROOT = "../.."
@@ -47,3 +48,6 @@ setup(name = 'xen',
ext_package = "xen.lowlevel",
ext_modules = [ xc, xu ]
)
os.chdir('logging')
execfile('setup.py')
+14 -12
View File
@@ -22,6 +22,8 @@ import XendConsole
import XendMigrate
import EventServer
from XendError import XendError
from XendLogging import log
from xen.xend.server import SrvDaemon
xend = SrvDaemon.instance()
@@ -52,7 +54,7 @@ class XendDomain:
self.db = XendDB.XendDB(self.dbpath)
self.domain_db = self.db.fetchall("")
if xroot.get_rebooted():
print 'XendDomain> rebooted: removing all domain info'
log.info('XendDomain> rebooted: removing all domain info')
self.rm_all()
eserver.subscribe('xend.virq', self.onVirq)
self.initial_refresh()
@@ -226,10 +228,10 @@ class XendDomain:
casualties.append(d)
for d in casualties:
id = str(d['dom'])
print 'XendDomain>reap> died id=', id, d
log.debug('XendDomain>reap> domain died id=%s', id)
if d['shutdown']:
reason = XendDomainInfo.shutdown_reason(d['shutdown_reason'])
print 'XendDomain>reap> shutdown id=', id, reason
log.debug('XendDomain>reap> shutdown id=%s reason=%s', id, reason)
if reason in ['poweroff', 'reboot']:
self.domain_restart_schedule(id, reason)
self.final_domain_destroy(id)
@@ -283,7 +285,7 @@ class XendDomain:
try:
self._delete_domain(id)
except:
print 'refresh_domain: error'
log.exception('refresh_domain> error')
raise
pass
else:
@@ -328,7 +330,7 @@ class XendDomain:
@param config: configuration
@return: deferred
"""
print 'domain_configure>', id, config
log.debug('domain_configure> id=%s config=%s', id, str(config))
dom = int(id)
dominfo = self.domain_get(dom)
if not dominfo:
@@ -417,7 +419,7 @@ class XendDomain:
@param id: domain id
@param reason: shutdown reason
"""
print 'domain_restart_schedule>', id, reason, set
log.debug('domain_restart_schedule> %s %s %d', id, reason, set)
dominfo = self.domain.get(id)
if not dominfo:
return
@@ -430,7 +432,7 @@ class XendDomain:
# Avoid multiple restarts.
dominfo.restart_mode = XendDomainInfo.RESTART_NEVER
self.restarts[id] = dominfo.config
print 'Scheduling restart for domain:', id, dominfo.name
log.info('Scheduling restart for domain: id=%s name=%s', id, dominfo.name)
self.domain_restarts_schedule()
def domain_restart_cancel(self, id):
@@ -456,18 +458,17 @@ class XendDomain:
# Remove it from the restarts.
del self.restarts[id]
try:
print 'domain_restarts> restart:', id, config
log.info('domain_restarts> restart: id=%s config=%s', id, str(config))
def cbok(dominfo):
print 'Restarted domain', id, 'as', dominfo.id
log.info('Restarted domain %s as %s', id, dominfo.id)
self.domain_unpause(dominfo.id)
def cberr(err):
print >>sys.stderr, "Delayed exception restarting domain: ", err
log.exception("Delayed exception restarting domain")
deferred = self.domain_create(config)
deferred.addCallback(cbok)
deferred.addErrback(cberr)
except:
print >>sys.stderr, "XendDomain> Exception restarting domain"
traceback.print_exc(sys.stderr)
log.exception("Exception restarting domain")
if len(self.restarts):
self.refresh_schedule(delay=5)
@@ -479,6 +480,7 @@ class XendDomain:
dom = int(id)
if dom <= 0:
return 0
log.info('Destroying domain %s', str(id))
eserver.inject('xend.domain.destroy', id)
dominfo = self.domain.get(id)
if dominfo:
+26 -5
View File
@@ -26,6 +26,7 @@ import sxp
import XendConsole
xendConsole = XendConsole.instance()
from XendLogging import log
import server.SrvDaemon
xend = server.SrvDaemon.instance()
@@ -537,6 +538,7 @@ class XendDomainInfo:
if self.dom is None: return 0
chan = xend.getDomChannel(self.dom)
if chan:
log.debug("Closing channel to domain %d", self.dom)
chan.close()
return xc.domain_destroy(dom=self.dom)
@@ -564,6 +566,7 @@ class XendDomainInfo:
if self.dom is None: return
ctrl = xend.netif_get(self.dom)
if ctrl:
log.debug("Destroying vifs for domain %d", self.dom)
ctrl.destroy()
def release_vbds(self):
@@ -572,6 +575,7 @@ class XendDomainInfo:
if self.dom is None: return
ctrl = xend.blkif_get(self.dom)
if ctrl:
log.debug("Destroying vbds for domain %d", self.dom)
ctrl.destroy()
def show(self):
@@ -599,11 +603,11 @@ class XendDomainInfo:
memory = self.memory
name = self.name
cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
#print 'init_domain>', memory, name, cpu
dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
if dom <= 0:
raise VmError('Creating domain failed: name=%s memory=%d'
% (name, memory))
log.debug('init_domain> Created domain=%d name=%s memory=%d', dom, name, memory)
self.setdom(dom)
if self.startTime is None:
@@ -614,7 +618,7 @@ class XendDomainInfo:
"""
if self.recreate: return
if len(cmdline) >= 256:
print 'Warning: kernel cmdline too long'
log.warning('kernel cmdline too long, domain %d', self.dom)
dom = self.dom
buildfn = getattr(xc, '%s_build' % ostype)
#print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
@@ -803,6 +807,8 @@ class XendDomainInfo:
if field_handler:
v = field_handler(self, self.config, field, field_index)
append_deferred(dlist, v)
else:
log.warning("Unknown config field %s", field_name)
index[field_name] = field_index + 1
d = defer.DeferredList(dlist, fireOnOneErrback=1)
return d
@@ -872,6 +878,7 @@ def vm_dev_vif(vm, val, index):
vif = index #todo
vmac = sxp.child_value(val, "mac")
xend.netif_create(vm.dom, recreate=vm.recreate)
log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac))
defer = xend.netif_dev_create(vm.dom, vif, val, recreate=vm.recreate)
def fn(id):
dev = xend.netif_dev(vm.dom, vif)
@@ -898,6 +905,7 @@ def vm_dev_vbd(vm, val, index):
if not dev:
raise VmError('vbd: Missing dev')
mode = sxp.child_value(val, 'mode', 'r')
log.debug("Creating vbd dom=%d uname=%s dev=%s", vm.dom, uname, dev)
defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
def fn(vbd):
dev = xend.blkif_dev(vm.dom, vdev)
@@ -932,6 +940,7 @@ def vm_dev_pci(vm, val, index):
func = parse_pci(func)
except:
raise VmError('pci: invalid parameter')
log.debug("Creating pci device dom=%d bus=%x dev=%x func=%x", vm.dom, bus, dev, func)
rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
func=func, enable=1)
if rc < 0:
@@ -974,13 +983,13 @@ def vnet_bridge(vnet, vmac, dom, idx):
vif = "vif%d.%d" % (dom, idx)
try:
cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
print "*** vnet_bridge>", cmd
log.debug("vnet_bridge> %s", cmd)
out = file("/proc/vnet/policy", "wb")
out.write(cmd)
err = out.close()
print "vnet_bridge>", "err=", err
log.debug("vnet_bridge> err=%d", err)
except IOError, ex:
print "vnet_bridge>", ex
log.exception("vnet_bridge>")
def vm_field_vnet(vm, config, val, index):
"""Handle a vnet field in a config.
@@ -1005,6 +1014,9 @@ def vm_field_vnet(vm, config, val, index):
#vnet_bridge(vnet, mac, vm.dom, 0)
#vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
def vm_field_ignore(vm, config, val, index):
pass
# Register image handlers for linux and bsd.
add_image_handler('linux', vm_image_linux)
add_image_handler('netbsd', vm_image_netbsd)
@@ -1014,6 +1026,15 @@ add_device_handler('vif', vm_dev_vif)
add_device_handler('vbd', vm_dev_vbd)
add_device_handler('pci', vm_dev_pci)
# Ignore the fields we already handle.
add_config_handler('name', vm_field_ignore)
add_config_handler('memory', vm_field_ignore)
add_config_handler('cpu', vm_field_ignore)
add_config_handler('console', vm_field_ignore)
add_config_handler('image', vm_field_ignore)
add_config_handler('device', vm_field_ignore)
add_config_handler('backend', vm_field_ignore)
# Register config handlers for vfr and vnet.
add_config_handler('vfr', vm_field_vfr)
add_config_handler('vnet', vm_field_vnet)
+63
View File
@@ -0,0 +1,63 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
import types
import logging
from logging import Formatter, StreamHandler
from logging.handlers import RotatingFileHandler
class XendLogging:
KB = 1024
MB = 1024 * KB
maxBytes = 1 * MB
backupCount = 5
logStderrFormat = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
logFileFormat = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
dateFormat = "%Y-%m-%d %H:%M:%S"
def __init__(self, filename, level=logging.INFO, maxBytes=None, backupCount=None):
self.setLevel(level)
if maxBytes:
self.maxBytes = maxBytes
if backupCount:
self.backupCount = backupCount
self.initLogFile(filename)
self.initLogStderr()
pass
def setLevel(self, level):
if isinstance(level, types.StringType):
level = logging._levelNames[level]
self.getLogger().setLevel(level)
self.level = level
def getLevel(self, level):
return logging.getLevelName(self.level)
def getLogger(self):
return logging.getLogger("xend")
def initLogFile(self, filename):
self.logfile = RotatingFileHandler(filename,
mode='a',
maxBytes=self.maxBytes,
backupCount=self.backupCount)
self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
log = self.getLogger()
log.addHandler(self.logfile)
def getLogFile(self):
return self.logfile
def initLogStderr(self):
self.logstderr = StreamHandler()
self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
self.getLogger().addHandler(self.logstderr)
def getLogStderr(self):
return self.logstderr
log = logging.getLogger("xend")
+21
View File
@@ -7,7 +7,9 @@ Creates the event server and handles configuration.
import os
import os.path
import sys
import EventServer
from XendLogging import XendLogging
# Initial create of the event server.
eserver = EventServer.instance()
@@ -44,6 +46,10 @@ class XendRoot:
"""Where network control scripts live."""
network_script_dir = "/etc/xen"
logfile_default = "/var/log/xend.log"
loglevel_default = 'DEBUG'
def __init__(self):
self.rebooted = 0
self.last_reboot = None
@@ -104,9 +110,21 @@ class XendRoot:
def configure(self):
print 'XendRoot>configure>'
self.set_config()
self.configure_logger()
self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
def configure_logger(self):
logfile = self.get_config_value("logfile", self.logfile_default)
loglevel = self.get_config_value("loglevel", self.loglevel_default)
self.logging = XendLogging(logfile, level=loglevel)
def get_logging(self):
return self.logging
def get_logger(self):
return self.logging.getLogger()
def get_dbroot(self):
"""Get the path to the database root.
"""
@@ -181,3 +199,6 @@ def instance():
except:
inst = XendRoot()
return inst
def logger():
return instance().get_logger()
+4 -28
View File
@@ -32,8 +32,9 @@ from xen.xend import PrettyPrint
from xen.xend import EventServer
eserver = EventServer.instance()
from xen.xend.XendError import XendError
from xen.xend.server import SrvServer
from xen.xend import XendRoot
from xen.xend.XendLogging import log
import channel
import blkif
@@ -514,11 +515,7 @@ class Daemon:
pidfile.close()
return 0
# Child
logfile = self.open_logfile()
self.redirect_output(logfile)
self.tracing(trace)
self.run()
return 0
@@ -590,16 +587,6 @@ class Daemon:
#del tb
return self.trace
def open_logfile(self):
if not os.path.exists(CONTROL_DIR):
os.makedirs(CONTROL_DIR)
# Open log file. Truncate it if non-empty, and request line buffering.
if os.path.isfile(LOG_FILE):
os.rename(LOG_FILE, LOG_FILE+'.old')
logfile = open(LOG_FILE, 'w+', 1)
return logfile
def set_user(self):
# Set the UID.
try:
@@ -609,22 +596,12 @@ class Daemon:
print "Error: no such user '%s'" % USER
return 1
def redirect_output(self, logfile):
if DEBUG: return
# Close down standard file handles
try:
os.close(0) # stdin
os.close(1) # stdout
os.close(2) # stderr
except:
pass
# Redirect output to log file.
sys.stdout = sys.stderr = logfile
def stop(self):
return self.cleanup(kill=True)
def run(self):
xroot = XendRoot.instance()
log.info("Xend Daemon started")
self.createFactories()
self.listenMgmt()
self.listenEvent()
@@ -709,7 +686,6 @@ class Daemon:
ctrl = self.blkifCF.getInstanceByDom(dom)
if not ctrl:
raise XendError('No blkif controller: %d' % dom)
print 'blkif_dev_create>', dom, vdev, mode, segment
d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
return d
+8 -12
View File
@@ -4,7 +4,7 @@ from twisted.internet import defer
#defer.Deferred.debug = 1
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend.XendLogging import log
import channel
import controller
@@ -143,7 +143,6 @@ class BlkifControllerFactory(controller.ControllerFactory):
@param d: deferred to call
@type d: Deferred
"""
print 'respond_be_create>'
val = unpackMsg('blkif_be_create_t', msg)
blkif = self.getInstanceByDom(val['domid'])
d.callback(blkif)
@@ -154,7 +153,6 @@ class BlkifControllerFactory(controller.ControllerFactory):
@param msg: message
@type msg: xu message
"""
print 'respond_be_connect>', self
val = unpackMsg('blkif_be_connect_t', msg)
blkif = self.getInstanceByDom(val['domid'])
if blkif:
@@ -172,7 +170,6 @@ class BlkifControllerFactory(controller.ControllerFactory):
@param d: deferred to call
@type d: Deferred
"""
print 'recv_be_vbd_create>', self
val = unpackMsg('blkif_be_vbd_create_t', msg)
blkif = self.getInstanceByDom(val['domid'])
if blkif:
@@ -191,7 +188,6 @@ class BlkifControllerFactory(controller.ControllerFactory):
@param d: deferred to call
@type d: Deferred or None
"""
print 'recv_be_vbd_grow>', self
val = unpackMsg('blkif_be_vbd_grow_t', msg)
# Check status?
if self.attached:
@@ -208,7 +204,6 @@ class BlkifControllerFactory(controller.ControllerFactory):
@param req: request flag (true if the msg is a request)
@type req: bool
"""
print 'recv_be_driver_status_changed>', self, req
val = unpackMsg('blkif_be_driver_status_changed_t', msg)
status = val['status']
if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
@@ -236,6 +231,7 @@ class BlkDev(controller.Dev):
return val
def destroy(self):
log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev)
self.controller.send_be_vbd_destroy(self.vdev)
class BlkifController(controller.Controller):
@@ -319,6 +315,7 @@ class BlkifController(controller.Controller):
def destroy(self):
def cb_destroy(val):
self.send_be_destroy()
log.debug("Destroying blkif domain=%d", self.dom)
d = defer.Deferred()
d.addCallback(cb_destroy)
self.send_be_disconnect(response=d)
@@ -369,8 +366,8 @@ class BlkifController(controller.Controller):
def recv_fe_interface_connect(self, msg, req):
val = unpackMsg('blkif_fe_interface_connect_t', msg)
self.evtchn = channel.eventChannel(0, self.dom)
print 'recv_fe_interface_connect>'
PrettyPrint.prettyprint(self.sxpr())
log.debug("Connecting blkif to event channel dom=%d ports=%d:%d",
self.dom, self.evtchn['port1'], self.evtchn['port2'])
msg = packMsg('blkif_be_connect_t',
{ 'domid' : self.dom,
'blkif_handle' : val['handle'],
@@ -394,14 +391,14 @@ class BlkifController(controller.Controller):
self.factory.writeRequest(msg, response=response)
def send_be_disconnect(self, response=None):
print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom)
msg = packMsg('blkif_be_disconnect_t',
{ 'domid' : self.dom,
'blkif_handle' : 0 })
self.factory.writeRequest(msg, response=response)
def send_be_destroy(self, response=None):
print '>BlkifController>send_be_destroy>', 'dom=', self.dom
log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom)
msg = packMsg('blkif_be_destroy_t',
{ 'domid' : self.dom,
'blkif_handle' : 0 })
@@ -428,8 +425,7 @@ class BlkifController(controller.Controller):
self.factory.writeRequest(msg, response=response)
def send_be_vbd_destroy(self, vdev, response=None):
print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
PrettyPrint.prettyprint(self.sxpr())
log.debug('>BlkifController>send_be_vbd_destroy> dom=%d vdev=%d', self.dom, vdev)
dev = self.devices[vdev]
msg = packMsg('blkif_be_vbd_destroy_t',
{ 'domid' : self.dom,
+8 -1
View File
@@ -2,13 +2,13 @@
from twisted.internet import reactor
from twisted.internet import protocol
from twisted.protocols import telnet
from xen.lowlevel import xu
from xen.xend.XendError import XendError
from xen.xend import EventServer
eserver = EventServer.instance()
from xen.xend.XendLogging import log
import controller
from messages import *
@@ -36,6 +36,8 @@ class ConsoleProtocol(protocol.Protocol):
# KAF: A nice quiet successful connect.
#self.transport.write("Connected to console %d on domain %d\n"
# % (self.idx, self.controller.dom))
log.info("Console connected %s %s %s",
self.idx, str(self.addr[0]), str(self.addr[1]))
eserver.inject('xend.console.connect',
[self.idx, self.addr[0], self.addr[1]])
@@ -49,6 +51,8 @@ class ConsoleProtocol(protocol.Protocol):
return len(data)
def connectionLost(self, reason=None):
log.info("Console disconnected %s %s %s",
self.idx, str(self.addr[0]), str(self.addr[1]))
eserver.inject('xend.console.disconnect',
[self.idx, self.addr[0], self.addr[1]])
self.controller.disconnect()
@@ -83,11 +87,14 @@ class ConsoleControllerFactory(controller.ControllerFactory):
raise XendError('console port in use: ' + str(console_port))
console = ConsoleController(self, dom, console_port)
self.addInstance(console)
log.info("Created console id=%s domain=%d port=%d",
console.idx, console.dom, console.console_port)
eserver.inject('xend.console.create',
[console.idx, console.dom, console.console_port])
return console
def consoleClosed(self, console):
log.info("Closed console id=%s", console.idx)
eserver.inject('xend.console.close', console.idx)
self.delInstance(console)
-1
View File
@@ -50,7 +50,6 @@ class DomainController(controller.Controller):
controller.Controller.__init__(self, factory, dom)
self.majorTypes = [ CMSG_SHUTDOWN ]
self.registerChannel()
print 'DomainController>', self, self.channel, self.idx
def shutdown(self, reason):
"""Shutdown a domain.
+3 -3
View File
@@ -6,9 +6,9 @@ from twisted.internet import defer
#defer.Deferred.debug = 1
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend import Vifctl
from xen.xend.XendError import XendError
from xen.xend.XendLogging import log
import channel
import controller
@@ -93,7 +93,7 @@ class NetifControllerFactory(controller.ControllerFactory):
if netif:
netif.send_interface_connected(vif)
else:
print "respond_be_connect> unknown vif=", vif
log.warning("respond_be_connect> unknown dom=%d vif=%d", dom, vif)
pass
def recv_be_driver_status_changed(self, msg, req):
@@ -183,6 +183,7 @@ class NetDev(controller.Dev):
"""
def cb_destroy(val):
self.controller.send_be_destroy(self.vif)
log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
self.vifctl('down')
d = defer.Deferred()
d.addCallback(cb_destroy)
@@ -328,7 +329,6 @@ class NetifController(controller.Controller):
self.factory.writeRequest(msg, response=response)
def send_be_destroy(self, vif, response=None):
PrettyPrint.prettyprint(self.sxpr())
dev = self.devices[vif]
del self.devices[vif]
msg = packMsg('netif_be_destroy_t',
-1
View File
@@ -1,6 +1,5 @@
# The following parameters could be placed in a configuration file.
PID_FILE = '/var/run/xend.pid'
LOG_FILE = '/var/log/xend.log'
USER = 'root'
CONTROL_DIR = '/var/run/xend'
MGMT_SOCK = 'xendsock' # relative to CONTROL_DIR
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.