1ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved. 2ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# 3ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# Permission to use, copy, modify, and distribute this software and its 4ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# documentation for any purpose and without fee is hereby granted, 5ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# provided that the above copyright notice appear in all copies and that 6ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# both that copyright notice and this permission notice appear in 7ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# supporting documentation, and that the name of Vinay Sajip 8ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# not be used in advertising or publicity pertaining to distribution 9ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# of the software without specific, written prior permission. 10ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 11ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 12ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 13ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 14ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 17ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot""" 18ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotAdditional handlers for the logging package for Python. The core package is 19ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotbased on PEP 282 and comments thereto in comp.lang.python. 20ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 21ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotCopyright (C) 2001-2013 Vinay Sajip. All Rights Reserved. 22ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 23ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotTo use, simply 'import logging.handlers' and log away! 24ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot""" 25ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 26ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotimport errno, logging, socket, os, cPickle, struct, time, re 27ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotfrom stat import ST_DEV, ST_INO, ST_MTIME 28ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 29ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottry: 30ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot import codecs 31ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotexcept ImportError: 32ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot codecs = None 33ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robottry: 34ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot unicode 35ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot _unicode = True 36ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotexcept NameError: 37ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot _unicode = False 38ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 39ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# 40ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# Some constants... 41ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot# 42ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 43ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotDEFAULT_TCP_LOGGING_PORT = 9020 44ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotDEFAULT_UDP_LOGGING_PORT = 9021 45ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotDEFAULT_HTTP_LOGGING_PORT = 9022 46ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotDEFAULT_SOAP_LOGGING_PORT = 9023 47ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotSYSLOG_UDP_PORT = 514 48ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team RobotSYSLOG_TCP_PORT = 514 49ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 50ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot_MIDNIGHT = 24 * 60 * 60 # number of seconds in a day 51ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 52ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass BaseRotatingHandler(logging.FileHandler): 53ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 54ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Base class for handlers that rotate log files at a certain point. 55ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Not meant to be instantiated directly. Instead, use RotatingFileHandler 56ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot or TimedRotatingFileHandler. 57ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 58ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, filename, mode, encoding=None, delay=0): 59ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 60ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Use the specified filename for streamed logging 61ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 62ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if codecs is None: 63ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot encoding = None 64ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.FileHandler.__init__(self, filename, mode, encoding, delay) 65ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.mode = mode 66ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.encoding = encoding 67ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 68ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 69ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 70ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 71ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 72ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Output the record to the file, catering for rollover as described 73ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot in doRollover(). 74ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 75ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 76ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.shouldRollover(record): 77ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.doRollover() 78ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.FileHandler.emit(self, record) 79ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except (KeyboardInterrupt, SystemExit): 80ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 81ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except: 82ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.handleError(record) 83ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 84ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass RotatingFileHandler(BaseRotatingHandler): 85ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 86ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Handler for logging to a set of files, which switches from one file 87ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot to the next when the current file reaches a certain size. 88ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 89ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0): 90ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 91ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Open the specified file and use it as the stream for logging. 92ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 93ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot By default, the file grows indefinitely. You can specify particular 94ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot values of maxBytes and backupCount to allow the file to rollover at 95ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a predetermined size. 96ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 97ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Rollover occurs whenever the current log file is nearly maxBytes in 98ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot length. If backupCount is >= 1, the system will successively create 99ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot new files with the same pathname as the base file, but with extensions 100ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ".1", ".2" etc. appended to it. For example, with a backupCount of 5 101ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot and a base file name of "app.log", you would get "app.log", 102ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "app.log.1", "app.log.2", ... through to "app.log.5". The file being 103ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot written to is always "app.log" - when it gets filled up, it is closed 104ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc. 105ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot exist, then they are renamed to "app.log.2", "app.log.3" etc. 106ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot respectively. 107ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 108ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If maxBytes is zero, rollover never occurs. 109ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 110ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # If rotation/rollover is wanted, it doesn't make sense to use another 111ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # mode. If for example 'w' were specified, then if there were multiple 112ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # runs of the calling application, the logs from previous runs would be 113ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # lost if the 'w' is respected, because the log file would be truncated 114ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # on each run. 115ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if maxBytes > 0: 116ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot mode = 'a' 117ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot BaseRotatingHandler.__init__(self, filename, mode, encoding, delay) 118ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.maxBytes = maxBytes 119ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.backupCount = backupCount 120ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 121ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def doRollover(self): 122ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 123ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Do a rollover, as described in __init__(). 124ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 125ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.stream: 126ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream.close() 127ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream = None 128ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.backupCount > 0: 129ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for i in range(self.backupCount - 1, 0, -1): 130ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sfn = "%s.%d" % (self.baseFilename, i) 131ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dfn = "%s.%d" % (self.baseFilename, i + 1) 132ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if os.path.exists(sfn): 133ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #print "%s -> %s" % (sfn, dfn) 134ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if os.path.exists(dfn): 135ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.remove(dfn) 136ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.rename(sfn, dfn) 137ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dfn = self.baseFilename + ".1" 138ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if os.path.exists(dfn): 139ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.remove(dfn) 140ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.rename(self.baseFilename, dfn) 141ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #print "%s -> %s" % (self.baseFilename, dfn) 142ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream = self._open() 143ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 144ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def shouldRollover(self, record): 145ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 146ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Determine if rollover should occur. 147ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 148ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Basically, see if the supplied record would cause the file to exceed 149ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot the size limit we have. 150ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 151ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.stream is None: # delay was set... 152ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream = self._open() 153ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.maxBytes > 0: # are we rolling over? 154ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = "%s\n" % self.format(record) 155ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream.seek(0, 2) #due to non-posix-compliant Windows feature 156ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.stream.tell() + len(msg) >= self.maxBytes: 157ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 1 158ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 0 159ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 160ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass TimedRotatingFileHandler(BaseRotatingHandler): 161ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 162ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Handler for logging to a file, rotating the log file at certain timed 163ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot intervals. 164ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 165ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If backupCount is > 0, when rollover is done, no more than backupCount 166ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot files are kept - the oldest ones are deleted. 167ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 168ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False): 169ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay) 170ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.when = when.upper() 171ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.backupCount = backupCount 172ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.utc = utc 173ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Calculate the real rollover interval, which is just the number of 174ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # seconds between rollovers. Also set the filename suffix used when 175ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # a rollover occurs. Current 'when' events supported: 176ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # S - Seconds 177ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # M - Minutes 178ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # H - Hours 179ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # D - Days 180ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # midnight - roll over at midnight 181ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # W{0-6} - roll over on a certain day; 0 - Monday 182ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # 183ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Case of the 'when' specifier is not important; lower or upper case 184ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # will work. 185ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.when == 'S': 186ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.interval = 1 # one second 187ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.suffix = "%Y-%m-%d_%H-%M-%S" 188ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$" 189ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot elif self.when == 'M': 190ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.interval = 60 # one minute 191ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.suffix = "%Y-%m-%d_%H-%M" 192ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$" 193ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot elif self.when == 'H': 194ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.interval = 60 * 60 # one hour 195ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.suffix = "%Y-%m-%d_%H" 196ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$" 197ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot elif self.when == 'D' or self.when == 'MIDNIGHT': 198ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.interval = 60 * 60 * 24 # one day 199ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.suffix = "%Y-%m-%d" 200ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.extMatch = r"^\d{4}-\d{2}-\d{2}$" 201ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot elif self.when.startswith('W'): 202ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.interval = 60 * 60 * 24 * 7 # one week 203ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if len(self.when) != 2: 204ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise ValueError("You must specify a day for weekly rollover from 0 to 6 (0 is Monday): %s" % self.when) 205ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.when[1] < '0' or self.when[1] > '6': 206ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise ValueError("Invalid day specified for weekly rollover: %s" % self.when) 207ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.dayOfWeek = int(self.when[1]) 208ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.suffix = "%Y-%m-%d" 209ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.extMatch = r"^\d{4}-\d{2}-\d{2}$" 210ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 211ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise ValueError("Invalid rollover interval specified: %s" % self.when) 212ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 213ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.extMatch = re.compile(self.extMatch) 214ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.interval = self.interval * interval # multiply by units requested 215ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if os.path.exists(filename): 216ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot t = os.stat(filename)[ST_MTIME] 217ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 218ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot t = int(time.time()) 219ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.rolloverAt = self.computeRollover(t) 220ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 221ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def computeRollover(self, currentTime): 222ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 223ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Work out the rollover time based on the specified time. 224ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 225ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result = currentTime + self.interval 226ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # If we are rolling over at midnight or weekly, then the interval is already known. 227ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # What we need to figure out is WHEN the next interval is. In other words, 228ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # if you are rolling over at midnight, then your base interval is 1 day, 229ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # but you want to start that one day clock at midnight, not now. So, we 230ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # have to fudge the rolloverAt value in order to trigger the first rollover 231ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # at the right time. After that, the regular interval will take care of 232ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # the rest. Note that this code doesn't care about leap seconds. :) 233ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.when == 'MIDNIGHT' or self.when.startswith('W'): 234ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # This could be done with less code, but I wanted it to be clear 235ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.utc: 236ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot t = time.gmtime(currentTime) 237ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 238ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot t = time.localtime(currentTime) 239ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot currentHour = t[3] 240ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot currentMinute = t[4] 241ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot currentSecond = t[5] 242ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # r is the number of seconds left between now and midnight 243ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot r = _MIDNIGHT - ((currentHour * 60 + currentMinute) * 60 + 244ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot currentSecond) 245ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result = currentTime + r 246ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # If we are rolling over on a certain day, add in the number of days until 247ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # the next rollover, but offset by 1 since we just calculated the time 248ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # until the next day starts. There are three cases: 249ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Case 1) The day to rollover is today; in this case, do nothing 250ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Case 2) The day to rollover is further in the interval (i.e., today is 251ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # day 2 (Wednesday) and rollover is on day 6 (Sunday). Days to 252ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # next rollover is simply 6 - 2 - 1, or 3. 253ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Case 3) The day to rollover is behind us in the interval (i.e., today 254ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # is day 5 (Saturday) and rollover is on day 3 (Thursday). 255ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Days to rollover is 6 - 5 + 3, or 4. In this case, it's the 256ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # number of days left in the current week (1) plus the number 257ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # of days in the next week until the rollover day (3). 258ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # The calculations described in 2) and 3) above need to have a day added. 259ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # This is because the above time calculation takes us to midnight on this 260ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # day, i.e. the start of the next day. 261ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.when.startswith('W'): 262ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot day = t[6] # 0 is Monday 263ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if day != self.dayOfWeek: 264ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if day < self.dayOfWeek: 265ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot daysToWait = self.dayOfWeek - day 266ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 267ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot daysToWait = 6 - day + self.dayOfWeek + 1 268ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot newRolloverAt = result + (daysToWait * (60 * 60 * 24)) 269ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if not self.utc: 270ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dstNow = t[-1] 271ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dstAtRollover = time.localtime(newRolloverAt)[-1] 272ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if dstNow != dstAtRollover: 273ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour 274ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot addend = -3600 275ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: # DST bows out before next rollover, so we need to add an hour 276ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot addend = 3600 277ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot newRolloverAt += addend 278ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result = newRolloverAt 279ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return result 280ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 281ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def shouldRollover(self, record): 282ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 283ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Determine if rollover should occur. 284ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 285ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot record is not used, as we are just comparing times, but it is needed so 286ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot the method signatures are the same 287ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 288ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot t = int(time.time()) 289ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if t >= self.rolloverAt: 290ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 1 291ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #print "No need to rollover: %d, %d" % (t, self.rolloverAt) 292ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 0 293ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 294ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def getFilesToDelete(self): 295ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 296ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Determine the files to delete when rolling over. 297ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 298ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot More specific than the earlier method, which just used glob.glob(). 299ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 300ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dirName, baseName = os.path.split(self.baseFilename) 301ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot fileNames = os.listdir(dirName) 302ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result = [] 303ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot prefix = baseName + "." 304ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot plen = len(prefix) 305ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for fileName in fileNames: 306ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if fileName[:plen] == prefix: 307ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot suffix = fileName[plen:] 308ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.extMatch.match(suffix): 309ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result.append(os.path.join(dirName, fileName)) 310ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result.sort() 311ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if len(result) < self.backupCount: 312ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result = [] 313ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 314ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot result = result[:len(result) - self.backupCount] 315ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return result 316ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 317ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def doRollover(self): 318ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 319ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot do a rollover; in this case, a date/time stamp is appended to the filename 320ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot when the rollover happens. However, you want the file to be named for the 321ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot start of the interval, not the current time. If there is a backup count, 322ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot then we have to get a list of matching filenames, sort them and remove 323ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot the one with the oldest suffix. 324ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 325ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.stream: 326ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream.close() 327ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream = None 328ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # get the time that this sequence started at and make it a TimeTuple 329ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot currentTime = int(time.time()) 330ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dstNow = time.localtime(currentTime)[-1] 331ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot t = self.rolloverAt - self.interval 332ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.utc: 333ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot timeTuple = time.gmtime(t) 334ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 335ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot timeTuple = time.localtime(t) 336ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dstThen = timeTuple[-1] 337ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if dstNow != dstThen: 338ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if dstNow: 339ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot addend = 3600 340ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 341ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot addend = -3600 342ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot timeTuple = time.localtime(t + addend) 343ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple) 344ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if os.path.exists(dfn): 345ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.remove(dfn) 346ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.rename(self.baseFilename, dfn) 347ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.backupCount > 0: 348ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # find the oldest log file and delete it 349ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #s = glob.glob(self.baseFilename + ".20*") 350ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #if len(s) > self.backupCount: 351ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # s.sort() 352ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # os.remove(s[0]) 353ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for s in self.getFilesToDelete(): 354ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot os.remove(s) 355ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #print "%s -> %s" % (self.baseFilename, dfn) 356ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream = self._open() 357ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot newRolloverAt = self.computeRollover(currentTime) 358ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot while newRolloverAt <= currentTime: 359ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot newRolloverAt = newRolloverAt + self.interval 360ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #If DST changes and midnight or weekly rollover, adjust for this. 361ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc: 362ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dstAtRollover = time.localtime(newRolloverAt)[-1] 363ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if dstNow != dstAtRollover: 364ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour 365ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot addend = -3600 366ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: # DST bows out before next rollover, so we need to add an hour 367ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot addend = 3600 368ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot newRolloverAt += addend 369ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.rolloverAt = newRolloverAt 370ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 371ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass WatchedFileHandler(logging.FileHandler): 372ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 373ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler for logging to a file, which watches the file 374ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot to see if it has changed while in use. This can happen because of 375ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot usage of programs such as newsyslog and logrotate which perform 376ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot log file rotation. This handler, intended for use under Unix, 377ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot watches the file to see if it has changed since the last emit. 378ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot (A file has changed if its device or inode have changed.) 379ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If it has changed, the old file stream is closed, and the file 380ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot opened to get a new stream. 381ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 382ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This handler is not appropriate for use under Windows, because 383ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot under Windows open files cannot be moved or renamed - logging 384ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot opens the files with exclusive locks - and so there is no need 385ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for such a handler. Furthermore, ST_INO is not supported under 386ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Windows; stat always returns zero for this value. 387ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 388ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This handler is based on a suggestion and patch by Chad J. 389ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Schroeder. 390ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 391ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, filename, mode='a', encoding=None, delay=0): 392ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.FileHandler.__init__(self, filename, mode, encoding, delay) 393ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.dev, self.ino = -1, -1 394ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._statstream() 395ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 396ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def _statstream(self): 397ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.stream: 398ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sres = os.fstat(self.stream.fileno()) 399ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.dev, self.ino = sres[ST_DEV], sres[ST_INO] 400ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 401ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 402ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 403ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 404ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 405ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot First check if the underlying file has changed, and if it 406ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot has, close the old stream and reopen the file to get the 407ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot current stream. 408ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 409ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Reduce the chance of race conditions by stat'ing by path only 410ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # once and then fstat'ing our new fd if we opened a new log stream. 411ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # See issue #14632: Thanks to John Mulligan for the problem report 412ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # and patch. 413ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 414ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # stat the file by path, checking for existence 415ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sres = os.stat(self.baseFilename) 416ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except OSError as err: 417ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if err.errno == errno.ENOENT: 418ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sres = None 419ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 420ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 421ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # compare file system stat with that of our stream file handle 422ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino: 423ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.stream is not None: 424ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # we have an open file handle, clean it up 425ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream.flush() 426ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream.close() 427ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # open a new file handle and get new stat info from that fd 428ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.stream = self._open() 429ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._statstream() 430ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.FileHandler.emit(self, record) 431ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 432ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass SocketHandler(logging.Handler): 433ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 434ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which writes logging records, in pickle format, to 435ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a streaming socket. The socket is kept open across logging calls. 436ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If the peer resets it, an attempt is made to reconnect on the next call. 437ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot The pickle which is sent is that of the LogRecord's attribute dictionary 438ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot (__dict__), so that the receiver does not need to have the logging module 439ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot installed in order to process the logging event. 440ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 441ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot To unpickle the record at the receiving end into a LogRecord, use the 442ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot makeLogRecord function. 443ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 444ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 445ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, host, port): 446ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 447ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initializes the handler with a specific host address and port. 448ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 449ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot The attribute 'closeOnError' is set to 1 - which means that if 450ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a socket error occurs, the socket is silently closed and then 451ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot reopened on the next logging call. 452ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 453ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.__init__(self) 454ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.host = host 455ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.port = port 456ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock = None 457ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.closeOnError = 0 458ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryTime = None 459ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # 460ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Exponential backoff parameters. 461ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # 462ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryStart = 1.0 463ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryMax = 30.0 464ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryFactor = 2.0 465ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 466ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def makeSocket(self, timeout=1): 467ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 468ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A factory method which allows subclasses to define the precise 469ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot type of socket they want. 470ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 471ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 472ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if hasattr(s, 'settimeout'): 473ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot s.settimeout(timeout) 474ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot s.connect((self.host, self.port)) 475ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return s 476ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 477ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def createSocket(self): 478ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 479ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Try to create a socket, using an exponential backoff with 480ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a max retry time. Thanks to Robert Olson for the original patch 481ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot (SF #815911) which has been slightly refactored. 482ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 483ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot now = time.time() 484ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Either retryTime is None, in which case this 485ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # is the first time back after a disconnect, or 486ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # we've waited long enough. 487ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.retryTime is None: 488ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot attempt = 1 489ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 490ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot attempt = (now >= self.retryTime) 491ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if attempt: 492ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 493ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock = self.makeSocket() 494ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryTime = None # next time, no delay before trying 495ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except socket.error: 496ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #Creation failed, so set the retry time and return. 497ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.retryTime is None: 498ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryPeriod = self.retryStart 499ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 500ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryPeriod = self.retryPeriod * self.retryFactor 501ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.retryPeriod > self.retryMax: 502ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryPeriod = self.retryMax 503ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.retryTime = now + self.retryPeriod 504ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 505ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def send(self, s): 506ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 507ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Send a pickled string to the socket. 508ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 509ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This function allows for partial sends which can happen when the 510ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot network is busy. 511ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 512ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.sock is None: 513ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.createSocket() 514ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #self.sock can be None either because we haven't reached the retry 515ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #time yet, or because we have reached the retry time and retried, 516ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #but are still unable to connect. 517ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.sock: 518ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 519ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if hasattr(self.sock, "sendall"): 520ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock.sendall(s) 521ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 522ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sentsofar = 0 523ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot left = len(s) 524ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot while left > 0: 525ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sent = self.sock.send(s[sentsofar:]) 526ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sentsofar = sentsofar + sent 527ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot left = left - sent 528ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except socket.error: 529ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock.close() 530ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock = None # so we can call createSocket next time 531ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 532ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def makePickle(self, record): 533ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 534ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Pickles the record in binary format with a length prefix, and 535ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot returns it ready for transmission across the socket. 536ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 537ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ei = record.exc_info 538ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if ei: 539ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # just to get traceback text into record.exc_text ... 540ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dummy = self.format(record) 541ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot record.exc_info = None # to avoid Unpickleable error 542ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # See issue #14436: If msg or args are objects, they may not be 543ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # available on the receiving end. So we convert the msg % args 544ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # to a string, save it as msg and zap the args. 545ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot d = dict(record.__dict__) 546ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot d['msg'] = record.getMessage() 547ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot d['args'] = None 548ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot s = cPickle.dumps(d, 1) 549ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if ei: 550ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot record.exc_info = ei # for next handler 551ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot slen = struct.pack(">L", len(s)) 552ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return slen + s 553ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 554ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def handleError(self, record): 555ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 556ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Handle an error during logging. 557ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 558ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot An error has occurred during logging. Most likely cause - 559ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot connection lost. Close the socket so that we can retry on the 560ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot next event. 561ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 562ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.closeOnError and self.sock: 563ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock.close() 564ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock = None #try to reconnect next time 565ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 566ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.handleError(self, record) 567ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 568ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 569ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 570ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 571ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 572ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Pickles the record and writes it to the socket in binary format. 573ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If there is an error with the socket, silently drop the packet. 574ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If there was a problem with the socket, re-establishes the 575ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot socket. 576ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 577ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 578ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot s = self.makePickle(record) 579ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.send(s) 580ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except (KeyboardInterrupt, SystemExit): 581ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 582ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except: 583ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.handleError(record) 584ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 585ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def close(self): 586ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 587ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Closes the socket. 588ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 589ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.acquire() 590ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 591ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.sock: 592ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock.close() 593ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock = None 594ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot finally: 595ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.release() 596ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.close(self) 597ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 598ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass DatagramHandler(SocketHandler): 599ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 600ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which writes logging records, in pickle format, to 601ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a datagram socket. The pickle which is sent is that of the LogRecord's 602ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot attribute dictionary (__dict__), so that the receiver does not need to 603ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot have the logging module installed in order to process the logging event. 604ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 605ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot To unpickle the record at the receiving end into a LogRecord, use the 606ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot makeLogRecord function. 607ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 608ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 609ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, host, port): 610ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 611ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initializes the handler with a specific host address and port. 612ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 613ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot SocketHandler.__init__(self, host, port) 614ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.closeOnError = 0 615ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 616ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def makeSocket(self): 617ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 618ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot The factory method of SocketHandler is here overridden to create 619ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a UDP socket (SOCK_DGRAM). 620ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 621ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 622ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return s 623ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 624ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def send(self, s): 625ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 626ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Send a pickled string to a socket. 627ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 628ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This function no longer allows for partial sends which can happen 629ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot when the network is busy - UDP does not guarantee delivery and 630ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot can deliver packets out of sequence. 631ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 632ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.sock is None: 633ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.createSocket() 634ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.sock.sendto(s, (self.host, self.port)) 635ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 636ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass SysLogHandler(logging.Handler): 637ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 638ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which sends formatted logging records to a syslog 639ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot server. Based on Sam Rushing's syslog module: 640ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot http://www.nightmare.com/squirl/python-ext/misc/syslog.py 641ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Contributed by Nicolas Untz (after which minor refactoring changes 642ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot have been made). 643ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 644ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 645ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # from <linux/sys/syslog.h>: 646ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # ====================================================================== 647ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # priorities/facilities are encoded into a single 32-bit quantity, where 648ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # the bottom 3 bits are the priority (0-7) and the top 28 bits are the 649ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # facility (0-big number). Both the priorities and the facilities map 650ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # roughly one-to-one to strings in the syslogd(8) source code. This 651ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # mapping is included in this file. 652ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # 653ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # priorities (these are ordered) 654ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 655ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_EMERG = 0 # system is unusable 656ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_ALERT = 1 # action must be taken immediately 657ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_CRIT = 2 # critical conditions 658ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_ERR = 3 # error conditions 659ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_WARNING = 4 # warning conditions 660ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_NOTICE = 5 # normal but significant condition 661ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_INFO = 6 # informational 662ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_DEBUG = 7 # debug-level messages 663ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 664ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # facility codes 665ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_KERN = 0 # kernel messages 666ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_USER = 1 # random user-level messages 667ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_MAIL = 2 # mail system 668ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_DAEMON = 3 # system daemons 669ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_AUTH = 4 # security/authorization messages 670ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_SYSLOG = 5 # messages generated internally by syslogd 671ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LPR = 6 # line printer subsystem 672ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_NEWS = 7 # network news subsystem 673ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_UUCP = 8 # UUCP subsystem 674ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_CRON = 9 # clock daemon 675ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_AUTHPRIV = 10 # security/authorization messages (private) 676ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_FTP = 11 # FTP daemon 677ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 678ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # other codes through 15 reserved for system use 679ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL0 = 16 # reserved for local use 680ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL1 = 17 # reserved for local use 681ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL2 = 18 # reserved for local use 682ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL3 = 19 # reserved for local use 683ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL4 = 20 # reserved for local use 684ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL5 = 21 # reserved for local use 685ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL6 = 22 # reserved for local use 686ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot LOG_LOCAL7 = 23 # reserved for local use 687ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 688ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot priority_names = { 689ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "alert": LOG_ALERT, 690ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "crit": LOG_CRIT, 691ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "critical": LOG_CRIT, 692ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "debug": LOG_DEBUG, 693ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "emerg": LOG_EMERG, 694ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "err": LOG_ERR, 695ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "error": LOG_ERR, # DEPRECATED 696ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "info": LOG_INFO, 697ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "notice": LOG_NOTICE, 698ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "panic": LOG_EMERG, # DEPRECATED 699ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "warn": LOG_WARNING, # DEPRECATED 700ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "warning": LOG_WARNING, 701ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot } 702ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 703ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot facility_names = { 704ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "auth": LOG_AUTH, 705ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "authpriv": LOG_AUTHPRIV, 706ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "cron": LOG_CRON, 707ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "daemon": LOG_DAEMON, 708ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "ftp": LOG_FTP, 709ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "kern": LOG_KERN, 710ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "lpr": LOG_LPR, 711ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "mail": LOG_MAIL, 712ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "news": LOG_NEWS, 713ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "security": LOG_AUTH, # DEPRECATED 714ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "syslog": LOG_SYSLOG, 715ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "user": LOG_USER, 716ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "uucp": LOG_UUCP, 717ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local0": LOG_LOCAL0, 718ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local1": LOG_LOCAL1, 719ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local2": LOG_LOCAL2, 720ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local3": LOG_LOCAL3, 721ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local4": LOG_LOCAL4, 722ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local5": LOG_LOCAL5, 723ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local6": LOG_LOCAL6, 724ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "local7": LOG_LOCAL7, 725ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot } 726ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 727ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #The map below appears to be trivially lowercasing the key. However, 728ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #there's more to it than meets the eye - in some locales, lowercasing 729ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #gives unexpected results. See SF #1524081: in the Turkish locale, 730ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #"INFO".lower() != "info" 731ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot priority_map = { 732ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "DEBUG" : "debug", 733ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "INFO" : "info", 734ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "WARNING" : "warning", 735ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "ERROR" : "error", 736ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "CRITICAL" : "critical" 737ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot } 738ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 739ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, address=('localhost', SYSLOG_UDP_PORT), 740ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot facility=LOG_USER, socktype=None): 741ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 742ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initialize a handler. 743ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 744ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If address is specified as a string, a UNIX socket is used. To log to a 745ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot local syslogd, "SysLogHandler(address="/dev/log")" can be used. 746ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If facility is not specified, LOG_USER is used. If socktype is 747ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific 748ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot socket type will be used. For Unix sockets, you can also specify a 749ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot socktype of None, in which case socket.SOCK_DGRAM will be used, falling 750ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot back to socket.SOCK_STREAM. 751ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 752ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.__init__(self) 753ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 754ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.address = address 755ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.facility = facility 756ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socktype = socktype 757ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 758ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if isinstance(address, basestring): 759ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.unixsocket = 1 760ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._connect_unixsocket(address) 761ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 762ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.unixsocket = 0 763ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if socktype is None: 764ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot socktype = socket.SOCK_DGRAM 765ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket = socket.socket(socket.AF_INET, socktype) 766ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if socktype == socket.SOCK_STREAM: 767ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.connect(address) 768ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socktype = socktype 769ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.formatter = None 770ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 771ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def _connect_unixsocket(self, address): 772ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot use_socktype = self.socktype 773ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if use_socktype is None: 774ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot use_socktype = socket.SOCK_DGRAM 775ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket = socket.socket(socket.AF_UNIX, use_socktype) 776ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 777ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.connect(address) 778ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # it worked, so set self.socktype to the used type 779ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socktype = use_socktype 780ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except socket.error: 781ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.close() 782ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.socktype is not None: 783ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # user didn't specify falling back, so fail 784ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 785ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot use_socktype = socket.SOCK_STREAM 786ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket = socket.socket(socket.AF_UNIX, use_socktype) 787ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 788ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.connect(address) 789ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # it worked, so set self.socktype to the used type 790ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socktype = use_socktype 791ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except socket.error: 792ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.close() 793ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 794ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 795ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # curious: when talking to the unix-domain '/dev/log' socket, a 796ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # zero-terminator seems to be required. this string is placed 797ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # into a class variable so that it can be overridden if 798ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # necessary. 799ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot log_format_string = '<%d>%s\000' 800ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 801ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def encodePriority(self, facility, priority): 802ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 803ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Encode the facility and priority. You can pass in strings or 804ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot integers - if strings are passed, the facility_names and 805ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot priority_names mapping dictionaries are used to convert them to 806ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot integers. 807ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 808ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if isinstance(facility, basestring): 809ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot facility = self.facility_names[facility] 810ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if isinstance(priority, basestring): 811ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot priority = self.priority_names[priority] 812ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return (facility << 3) | priority 813ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 814ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def close (self): 815ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 816ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Closes the socket. 817ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 818ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.acquire() 819ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 820ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.unixsocket: 821ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.close() 822ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot finally: 823ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.release() 824ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.close(self) 825ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 826ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def mapPriority(self, levelName): 827ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 828ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Map a logging level name to a key in the priority_names map. 829ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This is useful in two scenarios: when custom levels are being 830ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot used, and in the case where you can't do a straightforward 831ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot mapping by lowercasing the logging level name because of locale- 832ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot specific issues (see SF #1524081). 833ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 834ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return self.priority_map.get(levelName, "warning") 835ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 836ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 837ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 838ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 839ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 840ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot The record is formatted, and then sent to the syslog server. If 841ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot exception information is present, it is NOT sent to the server. 842ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 843ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = self.format(record) + '\000' 844ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 845ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot We need to convert record level to lowercase, maybe this will 846ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot change in the future. 847ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 848ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot prio = '<%d>' % self.encodePriority(self.facility, 849ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.mapPriority(record.levelname)) 850ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # Message is a string. Convert to bytes as required by RFC 5424 851ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if type(msg) is unicode: 852ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = msg.encode('utf-8') 853ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = prio + msg 854ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 855ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.unixsocket: 856ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 857ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.send(msg) 858ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except socket.error: 859ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._connect_unixsocket(self.address) 860ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.send(msg) 861ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot elif self.socktype == socket.SOCK_DGRAM: 862ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.sendto(msg, self.address) 863ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 864ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.socket.sendall(msg) 865ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except (KeyboardInterrupt, SystemExit): 866ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 867ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except: 868ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.handleError(record) 869ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 870ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass SMTPHandler(logging.Handler): 871ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 872ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which sends an SMTP email for each logging event. 873ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 874ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, mailhost, fromaddr, toaddrs, subject, 875ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot credentials=None, secure=None): 876ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 877ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initialize the handler. 878ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 879ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initialize the instance with the from and to addresses and subject 880ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot line of the email. To specify a non-standard SMTP port, use the 881ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot (host, port) tuple format for the mailhost argument. To specify 882ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot authentication credentials, supply a (username, password) tuple 883ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for the credentials argument. To specify the use of a secure 884ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot protocol (TLS), pass in a tuple for the secure argument. This will 885ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot only be used when authentication credentials are supplied. The tuple 886ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot will be either an empty tuple, or a single-value tuple with the name 887ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot of a keyfile, or a 2-value tuple with the names of the keyfile and 888ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot certificate file. (This tuple is passed to the `starttls` method). 889ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 890ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.__init__(self) 891ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if isinstance(mailhost, tuple): 892ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.mailhost, self.mailport = mailhost 893ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 894ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.mailhost, self.mailport = mailhost, None 895ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if isinstance(credentials, tuple): 896ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.username, self.password = credentials 897ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 898ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.username = None 899ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.fromaddr = fromaddr 900ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if isinstance(toaddrs, basestring): 901ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot toaddrs = [toaddrs] 902ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.toaddrs = toaddrs 903ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.subject = subject 904ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.secure = secure 905ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._timeout = 5.0 906ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 907ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def getSubject(self, record): 908ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 909ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Determine the subject for the email. 910ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 911ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If you want to specify a subject line which is record-dependent, 912ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot override this method. 913ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 914ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return self.subject 915ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 916ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 917ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 918ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 919ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 920ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Format the record and send it to the specified addressees. 921ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 922ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 923ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot import smtplib 924ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot from email.utils import formatdate 925ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot port = self.mailport 926ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if not port: 927ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot port = smtplib.SMTP_PORT 928ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp = smtplib.SMTP(self.mailhost, port, timeout=self._timeout) 929ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = self.format(record) 930ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % ( 931ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.fromaddr, 932ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ",".join(self.toaddrs), 933ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.getSubject(record), 934ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot formatdate(), msg) 935ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.username: 936ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.secure is not None: 937ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp.ehlo() 938ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp.starttls(*self.secure) 939ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp.ehlo() 940ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp.login(self.username, self.password) 941ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp.sendmail(self.fromaddr, self.toaddrs, msg) 942ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot smtp.quit() 943ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except (KeyboardInterrupt, SystemExit): 944ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 945ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except: 946ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.handleError(record) 947ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 948ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass NTEventLogHandler(logging.Handler): 949ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 950ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which sends events to the NT Event Log. Adds a 951ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot registry entry for the specified application name. If no dllname is 952ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot provided, win32service.pyd (which contains some basic message 953ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot placeholders) is used. Note that use of these placeholders will make 954ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot your event logs big, as the entire message source is held in the log. 955ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot If you want slimmer logs, you have to pass in the name of your own DLL 956ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot which contains the message definitions you want to use in the event log. 957ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 958ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, appname, dllname=None, logtype="Application"): 959ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.__init__(self) 960ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 961ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot import win32evtlogutil, win32evtlog 962ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.appname = appname 963ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._welu = win32evtlogutil 964ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if not dllname: 965ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dllname = os.path.split(self._welu.__file__) 966ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dllname = os.path.split(dllname[0]) 967ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot dllname = os.path.join(dllname[0], r'win32service.pyd') 968ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.dllname = dllname 969ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.logtype = logtype 970ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._welu.AddSourceToRegistry(appname, dllname, logtype) 971ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE 972ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.typemap = { 973ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE, 974ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.INFO : win32evtlog.EVENTLOG_INFORMATION_TYPE, 975ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE, 976ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.ERROR : win32evtlog.EVENTLOG_ERROR_TYPE, 977ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE, 978ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot } 979ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except ImportError: 980ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot print("The Python Win32 extensions for NT (service, event "\ 981ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "logging) appear not to be available.") 982ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._welu = None 983ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 984ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def getMessageID(self, record): 985ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 986ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Return the message ID for the event record. If you are using your 987ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot own messages, you could do this by having the msg passed to the 988ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logger being an ID rather than a formatting string. Then, in here, 989ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot you could use a dictionary lookup to get the message ID. This 990ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot version returns 1, which is the base message ID in win32service.pyd. 991ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 992ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 1 993ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 994ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def getEventCategory(self, record): 995ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 996ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Return the event category for the record. 997ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 998ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Override this if you want to specify your own categories. This version 999ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot returns 0. 1000ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1001ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return 0 1002ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1003ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def getEventType(self, record): 1004ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1005ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Return the event type for the record. 1006ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1007ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Override this if you want to specify your own types. This version does 1008ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a mapping using the handler's typemap attribute, which is set up in 1009ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot __init__() to a dictionary which contains mappings for DEBUG, INFO, 1010ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot WARNING, ERROR and CRITICAL. If you are using your own levels you will 1011ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot either need to override this method or place a suitable dictionary in 1012ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot the handler's typemap attribute. 1013ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1014ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return self.typemap.get(record.levelno, self.deftype) 1015ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1016ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 1017ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1018ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 1019ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1020ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Determine the message ID, event category and event type. Then 1021ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot log the message in the NT event log. 1022ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1023ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self._welu: 1024ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 1025ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot id = self.getMessageID(record) 1026ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot cat = self.getEventCategory(record) 1027ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot type = self.getEventType(record) 1028ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot msg = self.format(record) 1029ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self._welu.ReportEvent(self.appname, id, cat, type, [msg]) 1030ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except (KeyboardInterrupt, SystemExit): 1031ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 1032ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except: 1033ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.handleError(record) 1034ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1035ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def close(self): 1036ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1037ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Clean up this handler. 1038ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1039ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot You can remove the application name from the registry as a 1040ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot source of event log entries. However, if you do this, you will 1041ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot not be able to see the events as you intended in the Event Log 1042ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Viewer - it needs to be able to access the registry to get the 1043ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot DLL name. 1044ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1045ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype) 1046ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.close(self) 1047ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1048ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass HTTPHandler(logging.Handler): 1049ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1050ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A class which sends records to a Web server, using either GET or 1051ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot POST semantics. 1052ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1053ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, host, url, method="GET"): 1054ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1055ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initialize the instance with the host, the request URL, and the method 1056ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot ("GET" or "POST") 1057ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1058ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.__init__(self) 1059ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot method = method.upper() 1060ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if method not in ["GET", "POST"]: 1061ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise ValueError("method must be GET or POST") 1062ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.host = host 1063ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.url = url 1064ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.method = method 1065ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1066ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def mapLogRecord(self, record): 1067ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1068ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Default implementation of mapping the log record into a dict 1069ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot that is sent as the CGI data. Overwrite in your class. 1070ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Contributed by Franz Glasner. 1071ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1072ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return record.__dict__ 1073ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1074ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 1075ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1076ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 1077ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1078ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Send the record to the Web server as a percent-encoded dictionary 1079ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1080ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 1081ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot import httplib, urllib 1082ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot host = self.host 1083ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h = httplib.HTTP(host) 1084ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot url = self.url 1085ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot data = urllib.urlencode(self.mapLogRecord(record)) 1086ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.method == "GET": 1087ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if (url.find('?') >= 0): 1088ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sep = '&' 1089ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot else: 1090ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot sep = '?' 1091ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot url = url + "%c%s" % (sep, data) 1092ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h.putrequest(self.method, url) 1093ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # support multiple hosts on one IP address... 1094ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot # need to strip optional :port from host, if present 1095ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot i = host.find(":") 1096ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if i >= 0: 1097ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot host = host[:i] 1098ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h.putheader("Host", host) 1099ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.method == "POST": 1100ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h.putheader("Content-type", 1101ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot "application/x-www-form-urlencoded") 1102ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h.putheader("Content-length", str(len(data))) 1103ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h.endheaders(data if self.method == "POST" else None) 1104ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot h.getreply() #can't do anything with the result 1105ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except (KeyboardInterrupt, SystemExit): 1106ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot raise 1107ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot except: 1108ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.handleError(record) 1109ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1110ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass BufferingHandler(logging.Handler): 1111ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1112ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which buffers logging records in memory. Whenever each 1113ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot record is added to the buffer, a check is made to see if the buffer should 1114ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot be flushed. If it should, then flush() is expected to do what's needed. 1115ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1116ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, capacity): 1117ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1118ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initialize the handler with the buffer size. 1119ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1120ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.__init__(self) 1121ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.capacity = capacity 1122ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.buffer = [] 1123ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1124ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def shouldFlush(self, record): 1125ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1126ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Should the handler flush its buffer? 1127ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1128ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Returns true if the buffer is up to capacity. This method can be 1129ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot overridden to implement custom flushing strategies. 1130ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1131ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return (len(self.buffer) >= self.capacity) 1132ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1133ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def emit(self, record): 1134ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1135ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Emit a record. 1136ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1137ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Append the record. If shouldFlush() tells us to, call flush() to process 1138ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot the buffer. 1139ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1140ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.buffer.append(record) 1141ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.shouldFlush(record): 1142ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.flush() 1143ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1144ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def flush(self): 1145ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1146ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Override to implement custom flushing behaviour. 1147ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1148ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This version just zaps the buffer to empty. 1149ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1150ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.acquire() 1151ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 1152ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.buffer = [] 1153ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot finally: 1154ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.release() 1155ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1156ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def close(self): 1157ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1158ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Close the handler. 1159ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1160ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot This version just flushes and chains to the parent class' close(). 1161ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1162ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.flush() 1163ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot logging.Handler.close(self) 1164ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1165ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robotclass MemoryHandler(BufferingHandler): 1166ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1167ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot A handler class which buffers logging records in memory, periodically 1168ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot flushing them to a target handler. Flushing occurs whenever the buffer 1169ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot is full, or when an event of a certain severity or greater is seen. 1170ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1171ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def __init__(self, capacity, flushLevel=logging.ERROR, target=None): 1172ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1173ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Initialize the handler with the buffer size, the level at which 1174ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot flushing should occur and an optional target. 1175ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1176ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Note that without a target being set either here or via setTarget(), 1177ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot a MemoryHandler is no use to anyone! 1178ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1179ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot BufferingHandler.__init__(self, capacity) 1180ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.flushLevel = flushLevel 1181ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.target = target 1182ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1183ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def shouldFlush(self, record): 1184ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1185ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Check for buffer full or a record at the flushLevel or higher. 1186ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1187ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot return (len(self.buffer) >= self.capacity) or \ 1188ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot (record.levelno >= self.flushLevel) 1189ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1190ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def setTarget(self, target): 1191ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1192ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Set the target handler for this handler. 1193ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1194ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.target = target 1195ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1196ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def flush(self): 1197ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1198ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot For a MemoryHandler, flushing means just sending the buffered 1199ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot records to the target, if there is one. Override if you want 1200ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot different behaviour. 1201ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1202ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.acquire() 1203ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 1204ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot if self.target: 1205ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot for record in self.buffer: 1206ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.target.handle(record) 1207ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.buffer = [] 1208ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot finally: 1209ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.release() 1210ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot 1211ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot def close(self): 1212ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1213ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot Flush, set the target to None and lose the buffer. 1214ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot """ 1215ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.flush() 1216ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.acquire() 1217ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot try: 1218ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.target = None 1219ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot BufferingHandler.close(self) 1220ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot finally: 1221ec1a0b3abe08fb9a3952e8f48231cda1f6d9b1fandroid-build-team Robot self.release() 1222