mirror of
https://github.com/python/cpython.git
synced 2026-01-06 07:22:09 +00:00
Copyright year change.
Corrections to comments. Tracebacks can now be sent via SocketHandler. SocketHandler now uses exponential backoff strategy. Handlers now chain to Handler.close() from their close() methods.
This commit is contained in:
parent
326441e72e
commit
48cfe38e79
1 changed files with 67 additions and 17 deletions
|
|
@ -19,9 +19,9 @@
|
|||
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 'inspect' is.
|
||||
information is not available unless 'sys._getframe()' is.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
|
||||
|
||||
To use, simply 'import logging' and log away!
|
||||
"""
|
||||
|
|
@ -132,6 +132,13 @@ def __init__(self, host, port):
|
|||
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):
|
||||
"""
|
||||
|
|
@ -142,6 +149,34 @@ def makeSocket(self):
|
|||
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.
|
||||
|
|
@ -149,24 +184,38 @@ def send(self, s):
|
|||
This function allows for partial sends which can happen when the
|
||||
network is busy.
|
||||
"""
|
||||
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
|
||||
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)
|
||||
#n = len(s)
|
||||
#slen = "%c%c" % ((n >> 8) & 0xFF, n & 0xFF)
|
||||
if ei:
|
||||
record.exc_info = ei # for next handler
|
||||
slen = struct.pack(">L", len(s))
|
||||
return slen + s
|
||||
|
||||
|
|
@ -195,8 +244,6 @@ def emit(self, record):
|
|||
"""
|
||||
try:
|
||||
s = self.makePickle(record)
|
||||
if not self.sock:
|
||||
self.sock = self.makeSocket()
|
||||
self.send(s)
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
|
@ -208,6 +255,7 @@ def close(self):
|
|||
if self.sock:
|
||||
self.sock.close()
|
||||
self.sock = None
|
||||
logging.Handler.close(self)
|
||||
|
||||
class DatagramHandler(SocketHandler):
|
||||
"""
|
||||
|
|
@ -386,6 +434,7 @@ def close (self):
|
|||
"""
|
||||
if self.unixsocket:
|
||||
self.socket.close()
|
||||
logging.Handler.close(self)
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
|
|
@ -580,7 +629,7 @@ def close(self):
|
|||
DLL name.
|
||||
"""
|
||||
#self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
|
||||
pass
|
||||
logging.Handler.close(self)
|
||||
|
||||
class HTTPHandler(logging.Handler):
|
||||
"""
|
||||
|
|
@ -603,7 +652,7 @@ def __init__(self, host, url, method="GET"):
|
|||
def mapLogRecord(self, record):
|
||||
"""
|
||||
Default implementation of mapping the log record into a dict
|
||||
that is send as the CGI data. Overwrite in your class.
|
||||
that is sent as the CGI data. Overwrite in your class.
|
||||
Contributed by Franz Glasner.
|
||||
"""
|
||||
return record.__dict__
|
||||
|
|
@ -726,3 +775,4 @@ def close(self):
|
|||
self.flush()
|
||||
self.target = None
|
||||
self.buffer = []
|
||||
BufferingHandler.close(self)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue