SF patch #761519: Fixes for bugs 760703 and 757821

SF bug #760703: SocketHandler and LogRecord don't work well together
SF bug #757821: logging module docs

Applied Vinay Sajip's patch with a few minor fixups and a NEWS item.

Patched __init__.py - added new function
makeLogRecord (for bug report 760703).

Patched handlers.py - updated some docstrings and
deleted some old commented-out code.

Patched test_logging.py to make use of makeLogRecord.

Patched liblogging.tex to fill documentation gaps (both
760703 and bug 757821).
This commit is contained in:
Raymond Hettinger 2003-06-27 21:43:39 +00:00
parent 6ebe61fa80
commit 6f3eaa67e5
5 changed files with 59 additions and 32 deletions

View File

@ -52,7 +52,7 @@ use of \dfn{handlers}, which are instances of subclasses of the
\class{Handler} class. Handlers are responsible for ensuring that a logged
message (in the form of a \class{LogRecord}) ends up in a particular
location (or set of locations) which is useful for the target audience for
that message (e.g. end users, support desk staff, system administrators,
that message (such as end users, support desk staff, system administrators,
developers). Handlers are passed \class{LogRecord} instances intended for
particular destinations. Each logger can have zero, one or more handlers
associated with it (via the \method{addHandler} method of \class{Logger}).
@ -204,6 +204,13 @@ with \var{lvl} is returned. Otherwise, the string "Level \%s" \% lvl is
returned.
\end{funcdesc}
\begin{funcdesc}{makeLogRecord}{attrdict}
Creates and returns a new \class{LogRecord} instance whose attributes are
defined by \var{attrdict}. This function is useful for taking a pickled
\class{LogRecord} attribute dictionary, sent over a socket, and reconstituting
it as a \class{LogRecord} instance at the receiving end.
\end{funcdesc}
\begin{funcdesc}{basicConfig}{}
Does basic configuration for the logging system by creating a
\class{StreamHandler} with a default \class{Formatter} and adding it to
@ -266,7 +273,7 @@ determined by \method{getEffectiveLevel()}.
Indicates the effective level for this logger. If a value other than
\constant{NOTSET} has been set using \method{setLevel()}, it is returned.
Otherwise, the hierarchy is traversed towards the root until a value
other than \constant{NOTSET} is found,and that value is returned.
other than \constant{NOTSET} is found, and that value is returned.
\end{methoddesc}
\begin{methoddesc}{debug}{msg\optional{, *args\optional{, **kwargs}}}
@ -535,9 +542,11 @@ Closes the socket.
\end{methoddesc}
\begin{methoddesc}{emit}{}
Pickles the record and writes it to the socket in binary format.
If there is an error with the socket, silently drops the packet.
If the connection was previously lost, re-establishes the connection.
Pickles the record's attribute dictionary and writes it to the socket in
binary format. If there is an error with the socket, silently drops the
packet. If the connection was previously lost, re-establishes the connection.
To unpickle the record at the receiving end into a LogRecord, use the
\function{makeLogRecord} function.
\end{methoddesc}
\begin{methoddesc}{handleError}{}
@ -553,8 +562,8 @@ socket (\constant{socket.SOCK_STREAM}).
\end{methoddesc}
\begin{methoddesc}{makePickle}{record}
Pickles the record in binary format with a length prefix, and returns
it ready for transmission across the socket.
Pickles the record's attribute dictionary in binary format with a length
prefix, and returns it ready for transmission across the socket.
\end{methoddesc}
\begin{methoddesc}{send}{packet}
@ -574,8 +583,11 @@ and \var{port}.
\end{classdesc}
\begin{methoddesc}{emit}{}
Pickles the record and writes it to the socket in binary format.
If there is an error with the socket, silently drops the packet.
Pickles the record's attribute dictionary and writes it to the socket in
binary format. If there is an error with the socket, silently drops the
packet.
To unpickle the record at the receiving end into a LogRecord, use the
\function{makeLogRecord} function.
\end{methoddesc}
\begin{methoddesc}{makeSocket}{}
@ -584,8 +596,7 @@ a UDP socket (\constant{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.
Send a pickled string to a socket.
\end{methoddesc}
\subsubsection{SysLogHandler}
@ -789,8 +800,8 @@ base
supplied, the default value of "\%s(message)\\n" is used.
A Formatter can be initialized with a format string which makes use of
knowledge of the \class{LogRecord} attributes - e.g. the default value
mentioned above makes use of the fact that the user's message and
knowledge of the \class{LogRecord} attributes - such as the default value
mentioned above making use of the fact that the user's message and
arguments are pre- formatted into a LogRecord's \var{message}
attribute. Currently, the useful attributes in a LogRecord are
described by:
@ -916,7 +927,11 @@ I/O.
\subsubsection{Configuration functions}
The following functions allow the logging module to be configured.
The following functions allow the logging module to be configured. Before
they can be used, you must import \module{logging.config}. Their use is optional -
you can configure the logging module entirely by making calls to the main
API (defined in \module{logging} itself) and defining handlers which are declared
either in \module{logging} or \module{logging.handlers}.
\begin{funcdesc}{fileConfig}{fname\optional{, defaults}}
Reads the logging configuration from a ConfigParser-format file named
@ -1013,7 +1028,7 @@ entry is set to 1 to indicate that messages must propagate to handlers
higher up the logger hierarchy from this logger, or 0 to indicate that
messages are \strong{not} propagated to handlers up the hierarchy. The
\code{qualname} entry is the hierarchical channel name of the logger,
i.e. the name used by the application to get the logger.
for example, the name used by the application to get the logger.
Sections which specify handler configuration are exemplified by the
following.

View File

@ -36,8 +36,8 @@ except ImportError:
__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
__status__ = "beta"
__version__ = "0.4.8"
__date__ = "22 April 2003"
__version__ = "0.4.8.1"
__date__ = "26 June 2003"
#---------------------------------------------------------------------------
# Miscellaneous module data
@ -233,6 +233,17 @@ class LogRecord:
msg = msg % self.args
return msg
def makeLogRecord(dict):
"""
Make a LogRecord whose attributes are defined by the specified dictionary,
This function is useful for converting a logging event received over
a socket connection (which is sent as a dictionary) into a LogRecord
instance.
"""
rv = LogRecord(None, None, "", 0, "", (), None)
rv.__dict__.update(dict)
return rv
#---------------------------------------------------------------------------
# Formatter classes and functions
#---------------------------------------------------------------------------

View File

@ -111,8 +111,12 @@ 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.
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 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):
@ -208,9 +212,12 @@ class SocketHandler(logging.Handler):
class DatagramHandler(SocketHandler):
"""
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).
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):
@ -236,14 +243,6 @@ class DatagramHandler(SocketHandler):
when the network is busy - UDP does not guarantee delivery and
can deliver packets out of sequence.
"""
#old code
#sentsofar = 0
#left = len(s)
#addr = (self.host, self.port)
#while left > 0:
# sent = self.sock.sendto(s[sentsofar:], addr)
# sentsofar = sentsofar + sent
# left = left - sent
self.sock.sendto(s, (self.host, self.port))
class SysLogHandler(logging.Handler):

View File

@ -70,8 +70,7 @@ class LogRecordStreamHandler(StreamRequestHandler):
while len(chunk) < slen:
chunk = chunk + self.connection.recv(slen - len(chunk))
obj = self.unPickle(chunk)
record = logging.LogRecord(None, None, "", 0, "", (), None)
record.__dict__.update(obj)
record = logging.makeLogRecord(obj)
self.handleLogRecord(record)
except:
raise

View File

@ -83,6 +83,9 @@ Extension modules
Library
-------
- The logging module now has a new function, makeLogRecord() making
LogHandler easier to interact with DatagramHandler and SocketHandler.
- For compatibility with doctests created before 2.3, if an expected
output block consists solely of "1" and the actual output block
consists solely of "True", it's accepted as a match; similarly