summaryrefslogtreecommitdiffstats
path: root/Doc/lib/liblogging.tex
diff options
context:
space:
mode:
authorSkip Montanaro <skip@pobox.com>2002-11-14 03:57:19 (GMT)
committerSkip Montanaro <skip@pobox.com>2002-11-14 03:57:19 (GMT)
commit649698f72e1782ee23677560ec63a07c157a5760 (patch)
tree969b3861609f33ea4f82aa3a13fbba986bd658f3 /Doc/lib/liblogging.tex
parenta4864a24646185b336988196c650a85601a5e04a (diff)
downloadcpython-649698f72e1782ee23677560ec63a07c157a5760.zip
cpython-649698f72e1782ee23677560ec63a07c157a5760.tar.gz
cpython-649698f72e1782ee23677560ec63a07c157a5760.tar.bz2
initial rough cut at documentation of logging module. This is basically
just a conversion of pydoc.help(logging).
Diffstat (limited to 'Doc/lib/liblogging.tex')
-rw-r--r--Doc/lib/liblogging.tex1139
1 files changed, 1139 insertions, 0 deletions
diff --git a/Doc/lib/liblogging.tex b/Doc/lib/liblogging.tex
new file mode 100644
index 0000000..eeacd5e
--- /dev/null
+++ b/Doc/lib/liblogging.tex
@@ -0,0 +1,1139 @@
+\section{\module{logging} ---
+ Logging facility for Python}
+
+\declaremodule{standard}{logging} % standard library, in Python
+
+% These apply to all modules, and may be given more than once:
+
+\moduleauthor{Vinay Sajip}{vinay_sajip@red-dove.com}
+\sectionauthor{Skip Montanaro}{skip@pobox.com}
+
+\modulesynopsis{Logging module for Python based on PEP 282.}
+
+
+There is a need for a standard logging system in Python, as documented in
+{}\pep{282} and enthusiastically endorsed by the Guido van Rossum in the
+{}\citetitle[http://www.python.org/doc/essays/pepparade.html]{Parade of the
+PEPs}. By a happy coincidence, the package described here was already in
+development and fairly close in intent and design to the description in the
+aforementioned PEP, borrowing as it did heavily from JSR-47 (now JDK 1.4's
+java.util.logging package) and
+{}\ulink{log4j}{http://jakarta.apache.org/log4j/}. This section page
+describes it in more detail.
+
+This package owes its greatest debt to Apache
+{}\ulink{log4j}{http://jakarta.apache.org/log4j/}. Due notice was also taken
+of log4j's comprehensive
+{}\ulink{critique}{http://jakarta.apache.org/log4j/docs/critique.html} of
+JSR-47. This package bears a close resemblance to log4j, but is not a close
+translation (as, for example, {}\ulink{log4p}{http://log4p.sourceforge.net/}
+appears to be).
+
+
+
+\subsection{Functions}
+
+The \module{logging} module defines the following functions:
+
+
+\begin{funcdesc}{getLevelName}{level}
+
+Return the textual representation of logging level \var{level}.
+
+If the level is one of the predefined levels (\var{CRITICAL}, \var{ERROR},
+{}\var{WARN}, \var{INFO}, \var{DEBUG}) then you get the corresponding
+string. If you have associated levels with names using
+{}\function{addLevelName} then the name you have associated with \var{level}
+is returned. Otherwise, the string "Level \%s" \% level is returned.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{addLevelName}{level, levelName}
+
+Associate \var{levelName} with \var{level}. This is used when converting
+levels to text during message formatting.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{setLoggerClass}{klass}
+
+Set the class to be used when instantiating a logger. The class should
+define \code{__init__()} such that only a name argument is required, and the
+{}\code{__init__()} should call Logger.__init__()
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{basicConfig}{}
+
+Do basic configuration for the logging system by creating a
+{}\class{StreamHandler} with a default {}\class{Formatter} and adding it to
+the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{getLogger}{\optional{name=None}}
+
+Return a logger with the specified name, creating it if necessary. If no
+name is specified, return the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{critical}{msg, *args, **kwargs}
+
+Log a message with severity \code{CRITICAL} on the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{error}{msg, *args, **kwargs}
+
+Log a message with severity \var{ERROR} on the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{exception}{msg, *args}
+
+Log a message with severity \code{ERROR} on the root logger,
+with exception information.
+
+\end{funcdesc}
+
+\begin{funcdesc}{warn}{msg, *args, **kwargs}
+
+Log a message with severity \code{WARN} on the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{info}{msg, *args, **kwargs}
+
+Log a message with severity \code{INFO} on the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{debug}{msg, *args, **kwargs}
+
+Log a message with severity \code{DEBUG} on the root logger.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{disable}{level}
+
+Disable all logging calls less severe than \code{level}.
+
+\end{funcdesc}
+
+
+\begin{funcdesc}{shutdown}{}
+
+Perform any cleanup actions in the logging system (e.g. flushing buffers).
+Should be called at application exit.
+
+\end{funcdesc}
+
+
+
+\subsection{Data}
+
+The \module{logging} module defines the following data objects:
+
+\begin{datadesc}{root}
+
+The default logger.
+
+\end{datadesc}
+
+
+\begin{datadesc}{BASIC_FORMAT}
+
+The default message format.
+
+\end{datadesc}
+
+
+\begin{datadesc}{CRITICAL}
+
+The \code{CRITICAL} level.
+
+\end{datadesc}
+
+
+\begin{datadesc}{FATAL}
+
+The \code {FATAL} level. A synonym for \code{CRITICAL}.
+
+\end{datadesc}
+
+
+\begin{datadesc}{WARN}
+
+The \code {WARN} level.
+
+\end{datadesc}
+
+
+\begin{datadesc}{INFO}
+
+The \code{INFO} level.
+
+\end{datadesc}
+
+
+\begin{datadesc}{DEBUG}
+
+The \code{DEBUG} level.
+
+\end{datadesc}
+
+
+\begin{datadesc}{NOTSET}
+
+The \code{NOTSET} level.
+
+\end{datadesc}
+
+
+\begin{datadesc}{raiseExceptions}
+
+Indicates whether exceptions during handling should be propagated. True by
+default.
+
+\end{datadesc}
+
+
+
+\subsection{Classes}
+
+The \module{logging} module defines the following classes:
+
+
+\begin{classdesc}{Formatter}{\optional{fmt=None\optional{, datefmt=None}}}
+
+Formatters need to know how a LogRecord is constructed. They are responsible
+for converting a LogRecord to (usually) a string which can be interpreted by
+either a human or an external system. The base Formatter allows a formatting
+string to be specified. If none is supplied, the default value of
+\code{"\%s(message)\e n"} is used.
+
+The Formatter can be initialized with a format string which makes use of
+knowledge of the LogRecord attributes - e.g. the default value mentioned
+above makes use of the fact that the user's message and arguments are pre-
+formatted into a LogRecord's message attribute. Currently, the useful
+attributes in a LogRecord are described by:
+
+\begin{description}
+
+\item[\%(name)s]{Name of the logger (logging channel)}
+
+\item[\%(levelno)s]{Numeric logging level for the message (DEBUG, INFO,
+WARN, ERROR, CRITICAL)}
+
+\item[\%(levelname)s]{Text logging level for the message ("DEBUG", "INFO",
+"WARN", "ERROR", "CRITICAL")}
+
+\item[\%(pathname)s]{Full pathname of the source file where the logging
+call was issued (if available)}
+
+\item[\%(filename)s]{Filename portion of pathname}
+
+\item[\%(module)s]{Module (name portion of filename)}
+
+\item[\%(lineno)d]{Source line number where the logging call was issued
+(if available)}
+
+\item[\%(created)f]{Time when the LogRecord was created (time.time()
+return value)}
+
+\item[\%(asctime)s]{Textual time when the LogRecord was created}
+
+\item[\%(msecs)d]{Millisecond portion of the creation time}
+
+\item[\%(relativeCreated)d]{Time in milliseconds when the LogRecord was
+created, relative to the time the logging module was loaded (typically at
+application startup time)}
+
+\item[\%(thread)d]{Thread ID (if available)}
+
+\item[\%(message)s]{The result of record.getMessage(), computed just as the
+record is emitted}
+
+\end{description}
+
+\end{classdesc}
+
+\begin{methoddesc}{format}{self, record}
+
+The record's attribute dictionary is used as the operand to a string
+formatting operation which yields the returned string. Before formatting
+the dictionary, a couple of preparatory steps are carried out. The message
+attribute of the record is computed using \code{LogRecord.getMessage()}. If
+the formatting string contains "\%(asctime)", \code{formatTime()} is called
+to format the event time. If there is exception information, it is
+formatted using \code{formatException()} and appended to the message.
+
+\end{methoddesc}
+
+\begin{methoddesc}{formatException}{self, ei}
+
+Format the specified exception information as a string. This default
+implementation just uses \code{traceback.print_exception()}
+
+\end{methoddesc}
+
+\begin{methoddesc}{formatTime}{self, record\optional{, datefmt=None}}
+
+This method should be called from \code{format()} by a formatter which wants
+to make use of a formatted time. This method can be overridden in formatters
+to provide for any specific requirement, but the basic behaviour is as
+follows: if datefmt (a string) is specified, it is used with time.strftime()
+to format the creation time of the record. Otherwise, the ISO8601 format is
+used. The resulting string is returned. This function uses a
+user-configurable function to convert the creation time to a tuple. By
+default, \code{time.localtime()} is used; to change this for a particular
+formatter instance, set the 'converter' attribute to a function with the
+same signature as \code{time.localtime()} or \code{time.gmtime()}. To change
+it for all formatters, for example if you want all logging times to be shown
+in GMT, set the 'converter' attribute in the \class{Formatter} class.
+
+\end{methoddesc}
+
+
+\begin{classdesc}{Filterer}{}
+
+A base class for loggers and handlers which allows them to share common
+code.
+
+\end{classdesc}
+
+\begin{methoddesc}{addFilter}{filter}
+
+Add the specified filter to this handler.
+
+\end{methoddesc}
+
+\begin{methoddesc}{filter}{self, record}
+
+Determine if a record is loggable by consulting all the filters. The default
+is to allow the record to be logged; any filter can veto this and the record
+is then dropped. Returns a boolean value.
+
+\end{methoddesc}
+
+\begin{methoddesc}{removeFilter}{filter}
+
+Remove the specified filter from this handler.
+
+\end{methoddesc}
+
+
+\begin{classdesc}{BufferingFormatter}{\optional{linefmt=None}}
+
+A formatter suitable for formatting a number of records. Optionally specify
+a formatter which will be used to format each individual record.
+
+\end{classdesc}
+
+
+\begin{methoddesc}{format}{records}
+
+Format the specified records and return the result as a string.
+
+\end{methoddesc}
+
+\begin{methoddesc}{formatFooter}{records}
+
+Return the footer string for the specified records.
+
+\end{methoddesc}
+
+\begin{methoddesc}{formatHeader}{records}
+
+Return the header string for the specified records.
+
+\end{methoddesc}
+
+\begin{classdesc}{BufferingHandler}{capacity}
+
+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 \code{flush()} is expected to do the needful.
+The handler is initialized with the buffer size.
+
+\end{classdesc}
+
+\begin{methoddesc}{emit}{record}
+
+Append the record. If \code{shouldFlush()} tells us to, call \code{flush()}
+to process the buffer.
+
+\end{methoddesc}
+
+\begin{methoddesc}{flush}{}
+
+Override to implement custom flushing behaviour. This version just zaps the
+buffer to empty.
+
+\end{methoddesc}
+
+\begin{methoddesc}{shouldFlush}{record}
+
+Returns true if the buffer is up to capacity. This method can be overridden
+to implement custom flushing strategies.
+
+\end{methoddesc}
+
+
+\begin{classdesc}{DatagramHandler}{host,port}
+
+A handler class which writes logging records, in pickle format, to a
+datagram socket. Note that the very simple wire protocol used means that
+packet sizes are expected to be encodable within 16 bits (i.e. < 32767
+bytes).
+
+Initializes the handler with a specific \code{host} and \code{port}.
+
+\end{classdesc}
+
+\begin{methoddesc}{makeSocket}{}
+
+The factory method of SocketHandler is here overridden to create a UDP
+socket (SOCK_DGRAM).
+
+\end{methoddesc}
+
+\begin{methoddesc}{send}{s}
+
+Send a pickled string to a socket. This function allows for partial sends
+which can happen when the network is busy.
+
+\end{methoddesc}
+
+\begin{classdesc}{FileHandler}{filename\optional{, mode='a+'}}
+
+A handler class which writes formatted logging records to disk files. The
+specified file is opened and used as the stream for logging. By default,
+the file grows indefinitely. You can call \code{setRollover()} to allow the
+file to rollover at a predetermined size.
+
+\end{classdesc}
+
+\begin{methoddesc}{close}{}
+
+Closes the stream.
+
+\end{methoddesc}
+
+\begin{methoddesc}{doRollover}{}
+
+Do a rollover, as described in \code{setRollover()}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{emit}{record}
+
+Output the record to the file, catering for rollover as described
+in \code{setRollover()}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{setRollover}{maxBytes, backupCount}
+
+Set the rollover parameters so that rollover occurs whenever the current log
+file is nearly \var{maxBytes} in length. If \var{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 \var{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". When the
+last file reaches its size limit, the logging reverts to "app.log" which is
+truncated xto zero length. If maxBytes is zero, rollover never occurs.
+
+\end{methoddesc}
+
+\begin{classdesc}{Filter}{\optional{name=''}}
+
+The base filter class. \class{Logger} and \class{Handler} instances can
+optionally use \class{Filter} instances to filter records as desired. The
+base filter class only allows events which are below a certain point in the
+logger hierarchy. For example, a filter initialized with "A.B" will allow
+events logged by loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" etc. but not
+"A.BB", "B.A.B" etc. If initialized with the empty string, all events are
+passed.
+
+The instance is initialized with the name of the logger which, together with
+its children, will have its events allowed through the filter. If no name is
+specified, allow every event.
+
+\end{classdesc}
+
+\begin{methoddesc}{filter}{record}
+
+Is the specified record to be logged? Returns 0 for no, nonzero for yes. If
+deemed appropriate, the record may be modified in-place.
+
+\end{methoddesc}
+
+
+\begin{classdesc}{HTTPHandler}{host, url\optional{, method='GET'}}
+
+A class which sends records to a Web server, using either GET or POST
+semantics. The instance is initialized with the \var{host}, the request
+\var{url}, and the \var{method} ("GET" or "POST")
+
+\end{classdesc}
+
+\begin{methoddesc}{emit}{record}
+
+Send the \var{record} to the Web server as an URL-encoded dictionary
+
+\end{methoddesc}
+
+\begin{classdesc}{Handler}{\optional{level=0}}
+
+The base handler class. Acts as a placeholder which defines the Handler
+interface. \class{Handler} instances can optionally use \class{Formatter}
+instances to format records as desired. By default, no formatter is
+specified; in this case, the 'raw' message as determined by record.message
+is logged. Initializes the instance - basically setting the formatter to
+None and the filter list to empty.
+
+XXX - what does the level do?
+
+\end{classdesc}
+
+\begin{methoddesc}{acquire}{}
+
+Acquire the I/O thread lock.
+
+\end{methoddesc}
+
+\begin{methoddesc}{close}{}
+
+Tidy up any resources used by the handler. This version does nothing and is
+intended to be implemented by subclasses.
+
+\end{methoddesc}
+
+\begin{methoddesc}{createLock}{}
+
+Acquire a thread lock for serializing access to the underlying I/O.
+
+\end{methoddesc}
+
+\begin{methoddesc}{emit}{record}
+
+Do whatever it takes to actually log the specified logging record. This
+version is intended to be implemented by subclasses and so raises a
+\exception{NotImplementedError}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{flush}{}
+
+Ensure all logging output has been flushed. This version does nothing and is
+intended to be implemented by subclasses.
+
+\end{methoddesc}
+
+\begin{methoddesc}{format}{record}
+
+Do formatting for a \var{record} - if a formatter is set, use it.
+Otherwise, use the default formatter for the module.
+
+\end{methoddesc}
+
+\begin{methoddesc}{handle}{record}
+
+Conditionally emit the specified logging \var{record}, depending on filters
+which may have been added to the handler. Wrap the actual emission of the
+record with acquisition/release of the I/O thread lock.
+
+\end{methoddesc}
+
+\begin{methoddesc}{handleError}{}
+
+This method should be called from handlers when an exception is encountered
+during an \code{emit()} call. By default it does nothing, because by default
+{}\var{raiseExceptions} is false, which means that exceptions get silently
+ignored. This is what is mostly wanted for a logging system - most users
+will not care about errors in the logging system, they are more interested
+in application errors. You could, however, replace this with a custom
+handler if you wish.
+
+XXX looks to me like raiseExceptions defaults to 1.
+
+\end{methoddesc}
+
+\begin{methoddesc}{release}{}
+
+Release the I/O thread lock.
+
+\end{methoddesc}
+
+\begin{methoddesc}{setFormatter}{formatter}
+
+Set the \var{formatter} for this handler.
+
+\end{methoddesc}
+
+\begin{methoddesc}{setLevel}{level}
+
+Set the logging \var{level} of this handler.
+
+\end{methoddesc}
+
+\begin{classdesc}{LogRecord}{name,lvl,pathname,lineno,msg,args,exc_info}
+
+\class{LogRecord} instances are created every time something is logged. They
+contain all the information pertinent to the event being logged. The main
+information passed in is in msg and args, which are combined using
+\code{str(msg) \% args} to create the message field of the record. The
+record also includes information such as when the record was created, the
+source line where the logging call was made, and any exception information
+to be logged.
+
+\end{classdesc}
+
+\begin{methoddesc}{getMessage}{}
+
+Return the message for this LogRecord, merging any user-supplied arguments
+with the message.
+
+\end{methoddesc}
+
+\begin{classdesc}{Logger}{name\optional{, level=0}}
+
+Instances of the \class{Logger} class represent a single logging channel. A
+"logging channel" indicates an area of an application. Exactly how an "area"
+is defined is up to the application developer. Since an application can have
+any number of areas, logging channels are identified by a unique
+string. Application areas can be nested (e.g. an area of "input processing"
+might include sub-areas "read CSV files", "read XLS files" and "read
+Gnumeric files"). To cater for this natural nesting, channel names are
+organized into a namespace hierarchy where levels are separated by periods,
+much like the Java or Python package namespace. So in the instance given
+above, channel names might be "input" for the upper level, and "input.csv",
+"input.xls" and "input.gnu" for the sub-levels. There is no arbitrary limit
+to the depth of nesting.
+
+The logger is initialized with a \var{name} and an optional \var{level}.
+
+\end{classdesc}
+
+\begin{methoddesc}{_log}{lvl, msg, args\optional{, exc_info=None}}
+
+Low-level logging routine which creates a \class{LogRecord} and then calls
+all the handlers of this logger to handle the record.
+
+\end{methoddesc}
+
+\begin{methoddesc}{addHandler}{hdlr}
+
+Add the specified handler to this logger.
+
+\end{methoddesc}
+
+\begin{methoddesc}{callHandlers}{record}
+
+Loop through all handlers for this logger and its parents in the logger
+hierarchy. If no handler was found, output a one-off error message to
+sys.stderr. Stop searching up the hierarchy whenever a logger with the
+"propagate" attribute set to zero is found - that will be the last logger
+whose handlers are called.
+
+\end{methoddesc}
+
+\begin{methoddesc}{critical}{msg, *args, **kwargs}
+
+Log \code{msg \% args} with severity \code{CRITICAL}. To pass exception
+information, use the keyword argument \var{exc_info} with a true value,
+e.g., \code{logger.critical("Houston, we have a \%s", "major disaster",
+exc_info=1)}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{fatal}{msg, *args, **kwargs}
+
+Synonym for \method{critical}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{debug}{msg, *args, **kwargs}
+
+Log \code{msg \% args} with severity \code{DEBUG}. To pass exception
+information, use the keyword argument exc_info with a true value, e.g.,
+\code{logger.debug("Houston, we have a \%s", "thorny problem", exc_info=1)}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{error}{msg, *args, **kwargs}
+
+Log \code{msg \% args} with severity \code{ERROR}. To pass exception
+information, use the keyword argument exc_info with a true value, e.g.,
+\code{logger.error("Houston, we have a \%s", "major problem", exc_info=1)}
+
+\end{methoddesc}
+
+\begin{methoddesc}{exception}{msg, *args}
+
+Convenience method for logging an \code{ERROR} with exception information.
+
+\end{methoddesc}
+
+
+\begin{methoddesc}{findCaller}{}
+
+Find the stack frame of the caller so that we can note the source file name
+and line number.
+
+\end{methoddesc}
+
+\begin{methoddesc}{getEffectiveLevel}{}
+
+Loop through this logger and its parents in the logger hierarchy, looking
+for a non-zero logging level. Return the first one found.
+
+\end{methoddesc}
+
+\begin{methoddesc}{handle}{record}
+
+Call the handlers for the specified \var{record}. This method is used for
+unpickled records received from a socket, as well as those created
+locally. Logger-level filtering is applied.
+
+\end{methoddesc}
+
+\begin{methoddesc}{info}{msg, *args, **kwargs}
+
+Log \code{msg \% args} with severity \code{INFO}. To pass exception
+information, use the keyword argument exc_info with a true value, e.g.,
+\code{logger.info("Houston, we have a \%s", "interesting problem",
+exc_info=1)}
+
+\end{methoddesc}
+
+\begin{methoddesc}{isEnabledFor}{lvl}
+
+Is this logger enabled for level \var{lvl}?
+
+\end{methoddesc}
+
+\begin{methoddesc}{log}{lvl, msg, *args, **kwargs}
+
+Log \code{msg \% args} with the severity \var{lvl}. To pass exception
+information, use the keyword argument \var{exc_info} with a true value,
+e.g., \code{logger.log(lvl, "We have a \%s", "mysterious problem",
+exc_info=1)}
+
+\end{methoddesc}
+
+\begin{methoddesc}{makeRecord}{name, lvl, fn, lno, msg, args, exc_info}
+
+A factory method which can be overridden in subclasses to create specialized
+\code{LogRecord} instances.
+
+\end{methoddesc}
+
+\begin{methoddesc}{removeHandler}{hdlr}
+
+Remove the specified handler from this logger.
+
+\end{methoddesc}
+
+\begin{methoddesc}{setLevel}{level}
+
+Set the logging \var{level} of this logger.
+
+\end{methoddesc}
+
+\begin{methoddesc}{warn}{msg, *args, **kwargs}
+
+Log \code{msg \% args} with severity \code{WARN}. To pass exception
+information, use the keyword argument exc_info with a true value, e.g.,
+\code{logger.warn("Houston, we have a \%s", "bit of a problem", exc_info=1)}
+
+\end{methoddesc}
+
+
+\begin{classdesc}{Manager}{root}
+
+There is (under normal circumstances) just one \code{Manager} instance,
+which holds the hierarchy of loggers.
+
+The manager is initialized with the \var{root} node of the logger hierarchy.
+
+\end{classdesc}
+
+\begin{methoddesc}{_fixupChildren}{ph, logger}
+
+Ensure that children of the placeholder \var{ph} are connected to the
+specified \code{logger}.
+
+\end{methoddesc}
+
+\begin{methoddesc}{_fixupParents}{logger}
+
+Ensure that there are either loggers or placeholders all the way from the
+specified \var{logger} to the root of the logger hierarchy.
+
+\end{methoddesc}
+
+\begin{methoddesc}{getLogger}{name}
+
+Get a logger with the specified \var{name} (channel name), creating it if it
+doesn't yet exist. If a PlaceHolder existed for the specified name (i.e. the
+logger didn't exist but a child of it did), replace it with the created
+logger and fix up the parent/child references which pointed to the
+placeholder to now point to the logger.
+
+\end{methoddesc}
+
+\begin{classdesc}{MemoryHandler}{capacity\optional{,
+flushLevel=40\optional{, target=None}}}
+
+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.
+
+The handler is initialized with the buffer size (\var{capacity}), the level
+at which flushing should occur (\var{flushLevel}) and an optional
+{}\var{target}. Note that without a target being set either here or via
+\code{setTarget()}, a \class{MemoryHandler} is no use to anyone!
+
+\end{classdesc}
+
+\begin{methoddesc}{close}{}
+
+Flush, set the target to None and lose the buffer.
+
+\end{methoddesc}
+
+\begin{methoddesc}{flush}{}
+
+For a \class{MemoryHandler}, flushing means just sending the buffered
+records to the target, if there is one. Override if you want different
+behavior.
+
+\end{methoddesc}
+
+\begin{methoddesc}{setTarget}{target}
+
+Set the \var{target} handler for this handler.
+
+\end{methoddesc}
+
+\begin{methoddesc}{shouldFlush}{record}
+
+Check for buffer full or a \var{record} at the flushLevel or higher.
+
+\end{methoddesc}
+
+
+\begin{classdesc}{NTEventLogHandler}{appname\optional{,
+dllname=None\optional{, logtype='Application'}}}
+
+A handler class which sends events to the NT Event Log. Adds a registry
+entry for the specified application name. If no \var{dllname} is provided,
+\code{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.
+
+XXX what is \var{logtype}?
+
+\end{classdesc}
+
+\begin{methoddesc}{close}{}
+
+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.
+
+\end{methoddesc}
+
+\begin{methoddesc}{emit}{record}
+
+Determine the message ID, event category and event type. Then log the
+\var{record} in the NT event log.
+
+\end{methoddesc}
+
+\begin{methoddesc}{getEventCategory}{record}
+
+Return the event category for the \var{record}. Override this if you want
+to specify your own categories. This version returns 0.
+
+\end{methoddesc}
+
+\begin{methoddesc}{getEventType}{record}
+
+Return the event type for the \var{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 the constructor to a dictionary which
+contains mappings for \var{DEBUG}, \var{INFO}, \var{WARN}, \var{ERROR} and
+{}\var{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.
+
+\end{methoddesc}
+
+\begin{methoddesc}{getMessageID}{record}
+
+Return the message ID for the event \var{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 \code{win32service.pyd}.
+
+\end{methoddesc}
+
+
+\begin{classdesc}PlaceHolder{logger}
+
+\class{PlaceHolder} instances are used in the \class{Manager} logger
+hierarchy to take the place of nodes for which no loggers have been defined
+
+Initialize with the specified \var{logger} being a child of this
+\class{PlaceHolder}.
+
+\end{classdesc}
+
+\begin{methoddesc}{append}{logger}
+
+Add the specified \var{logger} as a child of this placeholder.
+
+\end{methoddesc}
+
+\begin{classdesc}RootLogger{level}
+
+A root logger is not that different to any other logger, except that it must
+have a logging \var{level} and there is only one instance of it in the
+hierarchy.
+
+\end{classdesc}
+
+
+\begin{classdesc}{SMTPHandler}{mailhost, fromaddr, toaddr, subject}
+
+A handler class which sends an SMTP email for each logging event.
+
+The instance is initialized with the from (\var{fromaddr}) and to
+(\var{toaddr}) addresses and \var{subject} line of the email. To specify a
+non-standard SMTP port, use the (host, port) tuple format for the
+\var{mailhost} argument.
+
+\end{classdesc}
+
+
+\begin{methoddesc}{emit}{record}
+
+Format the \var{record} and send it to the specified addressees.
+
+\end{methoddesc}
+
+\begin{methoddesc}{getSubject}{record}
+
+If you want to specify a subject line which is \var{record}-dependent,
+override this method.
+
+\end{methoddesc}
+
+\begin{classdesc}{SocketHandler}{host, port}
+
+A handler class which writes pickled logging records 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. Note that the very
+simple wire protocol used means that packet sizes are expected to be
+encodable within 16 bits (i.e. < 32767 bytes).
+
+The handler is initialized with a specific \var{host} address and
+{}\var{port}. The attribute \var{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.
+
+\end{classdesc}
+
+\begin{methoddesc}{close}{}
+
+Closes the socket.
+
+\end{methoddesc}
+
+\begin{methoddesc}{emit}{record}
+
+Pickles the \var{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.
+
+\end{methoddesc}
+
+\begin{methoddesc}{handleError}{}
+
+An error has occurred during logging. Most likely cause - connection lost.
+Close the socket so that we can retry on the next event.
+
+\end{methoddesc}
+
+\begin{methoddesc}{makePickle}{record}
+
+Pickles the \var{record} in binary format with a length prefix, and returns
+it ready for transmission across the socket.
+
+\end{methoddesc}
+
+\begin{methoddesc}{makeSocket}{}
+
+A factory method which allows subclasses to define the precise type of
+socket they want.
+
+\end{methoddesc}
+
+\begin{methoddesc}{send}{s}
+
+Send a pickled string (\var{s}) to the socket. This function allows for
+partial sends which can happen when the network is busy.
+
+\end{methoddesc}
+
+\begin{classdesc}{StreamHandler}{\optional{strm=None}}
+
+A handler class which writes logging records, appropriately formatted, to a
+stream. Note that this class does not close the stream, as \var{sys.stdout}
+or \var{sys.stderr} may be used.
+
+If \var{strm} is not specified, \var{sys.stderr} is used.
+
+\end{classdesc}
+
+\begin{methoddesc}{emit}{record}
+
+If a formatter is specified, it is used to format the \var{record}. The
+record is then written to the stream with a trailing newline (N.B. this may
+be removed depending on feedback). If exception information is present, it
+is formatted using \var{traceback.print_exception} and appended to the
+stream.
+
+\end{methoddesc}
+
+\begin{methoddesc}{flush}{}
+
+Flushes the stream.
+
+\end{methoddesc}
+
+\begin{classdesc}{SysLogHandler}{\optional{address=('localhost',
+514)\optional{, facility=1}}}
+
+A handler class which sends formatted logging records to a syslog
+server. Based on Sam Rushing's
+\ulink{http://www.nightmare.com/squirl/python-ext/misc/syslog.py}{syslog
+module}. Contributed by Nicolas Untz (after which minor refactoring changes
+have been made).
+
+If \var{address} is specified as a string, UNIX socket is used. If
+\var{facility} is not specified, \code{LOG_USER} is used.
+
+\end{classdesc}
+
+\begin{methoddesc}{close}{}
+
+Closes the socket.
+
+\end{methoddesc}
+
+\begin{methoddesc}{emit}{record}
+
+The \var{record} is formatted, and then sent to the syslog server. If
+exception information is present, it is not sent to the server.
+
+\end{methoddesc}
+
+\begin{methoddesc}{encodePriority}{facility, priority}
+
+Encode the \var{facility} and \var{priority}. You can pass in strings or
+integers - if strings are passed, the \var{facility_names} and
+\var{priority_names} mapping dictionaries are used to convert them to
+integers.
+
+\end{methoddesc}
+
+
+\subsection{Examples \label{logging-example}}
+
+Using the package doesn't get much simpler. It is packaged as a Python
+package. You just need to \code{import logging} and you're ready to
+go. Minimal example:
+
+\begin{verbatim}
+# -- app.py --
+import logging
+
+logging.info("Starting...")
+logging.warn("Nothing to do!")
+logging.info("Done...")
+\end{verbatim}
+
+When you run \code{app.py}, the results are:
+
+\begin{verbatim}
+2002-03-15 01:09:10,440 root INFO - Starting...
+2002-03-15 01:09:10,440 root WARN - Nothing to do!
+2002-03-15 01:09:10,440 root INFO - Done...
+\end{verbatim}
+
+
+
+Here's a
+slightly more involved example; if you've just looked at \pep{282} you will
+probably get a feeling of deją vu. (This is intentional.)
+
+\begin{verbatim}
+# -- mymodule.py --
+import logging
+log = logging.getLogger("MyModule")
+
+def doIt():
+ log.debug("doin' stuff")
+ #do stuff...but suppose an error occurs?
+ raise TypeError, "bogus type error for testing"
+\end{verbatim}
+
+\begin{verbatim}
+# -- myapp.py --
+import logging, mymodule
+
+logging.basicConfig() # basic configuration - console output
+
+log = logging.getLogger("MyApp")
+
+log.info("start my app")
+try:
+ mymodule.doIt()
+except Exception, e:
+ log.exception("There was a problem doin' stuff.")
+log.info("end my app")
+\end{verbatim}
+
+When you run \code{myapp.py}, the results are:
+
+\begin{verbatim}
+2002-03-14 23:40:49,299 MyApp INFO - start my app
+2002-03-14 23:40:49,299 MyModule DEBUG - doin' stuff
+2002-03-14 23:40:49,299 MyApp ERROR - There was a problem doin' stuff.
+Traceback (innermost last):
+ File "myapp.py", line 9, in ?
+ mymodule.doIt()
+ File "mymodule.py", line 7, in doIt
+ raise TypeError, "bogus type error for testing"
+TypeError: bogus type error for testing
+2002-03-14 23:40:49,409 MyApp INFO - end my app
+\end{verbatim}