diff options
author | Benjamin Peterson <benjamin@python.org> | 2008-04-02 21:49:44 +0000 |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2008-04-02 21:49:44 +0000 |
commit | 4a7d4a1336224b80a9dfd7f20e2488a0dd5c9b70 (patch) | |
tree | 7eed55054ac9444908fa492ca81986e55c323046 /Lib/logging/handlers.py | |
parent | 44029fb55106656a7e92eaa02c7e889cd3a86dbe (diff) | |
download | cpython-4a7d4a1336224b80a9dfd7f20e2488a0dd5c9b70.tar.gz |
Merged revisions 62090-62091,62096,62100,62102,62110-62114 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62090 | brett.cannon | 2008-04-01 07:37:43 -0500 (Tue, 01 Apr 2008) | 3 lines
Generalize test.test_support.test_stdout() with a base context manager so that
it is easy to capture stderr if desired.
........
r62091 | brett.cannon | 2008-04-01 07:46:02 -0500 (Tue, 01 Apr 2008) | 3 lines
Add ``if __name__ == '__main__'`` to some test files where it didn't take a lot
of effort to do so.
........
r62096 | amaury.forgeotdarc | 2008-04-01 17:52:48 -0500 (Tue, 01 Apr 2008) | 4 lines
Newly enabled test appears to leak:
it registers the same codec on each iteration.
Do it only once at load time.
........
r62100 | amaury.forgeotdarc | 2008-04-01 19:55:04 -0500 (Tue, 01 Apr 2008) | 4 lines
A DocTestSuite cannot run multiple times: it clears its globals dictionary after the first run.
Rebuild the DocTestSuite on each iteration.
........
r62102 | jeffrey.yasskin | 2008-04-01 23:07:44 -0500 (Tue, 01 Apr 2008) | 3 lines
Try to make test_signal less flaky. I still see some flakiness in
test_itimer_prof.
........
r62110 | vinay.sajip | 2008-04-02 16:09:27 -0500 (Wed, 02 Apr 2008) | 1 line
Fix: #2315, #2316, #2317: TimedRotatingFileHandler - changed logic to better handle daylight savings time, deletion of old log files, and fixed a bug in calculating rollover when no logging occurs for a longer interval than the rollover period.
........
r62111 | vinay.sajip | 2008-04-02 16:10:23 -0500 (Wed, 02 Apr 2008) | 1 line
Added updates with respect to recent changes to TimedRotatingFileHandler.
........
r62112 | vinay.sajip | 2008-04-02 16:17:25 -0500 (Wed, 02 Apr 2008) | 1 line
Added updates with respect to recent changes to TimedRotatingFileHandler.
........
r62113 | amaury.forgeotdarc | 2008-04-02 16:18:46 -0500 (Wed, 02 Apr 2008) | 2 lines
Remove debug prints; the buildbot now passes the tests
........
r62114 | benjamin.peterson | 2008-04-02 16:20:35 -0500 (Wed, 02 Apr 2008) | 2 lines
Suggested proposed changes to Python be considered on some mailing lists first
........
Diffstat (limited to 'Lib/logging/handlers.py')
-rw-r--r-- | Lib/logging/handlers.py | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 4645f3e512..9cb0e09664 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -19,12 +19,12 @@ Additional handlers for the logging package for Python. The core package is based on PEP 282 and comments thereto in comp.lang.python, and influenced by Apache's log4j system. -Copyright (C) 2001-2007 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2008 Vinay Sajip. All Rights Reserved. To use, simply 'import logging' and log away! """ -import logging, socket, os, pickle, struct, time, glob +import logging, socket, os, pickle, struct, time, re from stat import ST_DEV, ST_INO try: @@ -173,15 +173,19 @@ class TimedRotatingFileHandler(BaseRotatingHandler): if self.when == 'S': self.interval = 1 # one second self.suffix = "%Y-%m-%d_%H-%M-%S" + self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$" elif self.when == 'M': self.interval = 60 # one minute self.suffix = "%Y-%m-%d_%H-%M" + self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$" elif self.when == 'H': self.interval = 60 * 60 # one hour self.suffix = "%Y-%m-%d_%H" + self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$" elif self.when == 'D' or self.when == 'MIDNIGHT': self.interval = 60 * 60 * 24 # one day self.suffix = "%Y-%m-%d" + self.extMatch = r"^\d{4}-\d{2}-\d{2}$" elif self.when.startswith('W'): self.interval = 60 * 60 * 24 * 7 # one week if len(self.when) != 2: @@ -190,9 +194,11 @@ class TimedRotatingFileHandler(BaseRotatingHandler): raise ValueError("Invalid day specified for weekly rollover: %s" % self.when) self.dayOfWeek = int(self.when[1]) self.suffix = "%Y-%m-%d" + self.extMatch = r"^\d{4}-\d{2}-\d{2}$" else: raise ValueError("Invalid rollover interval specified: %s" % self.when) + self.extMatch = re.compile(self.extMatch) self.interval = self.interval * interval # multiply by units requested self.rolloverAt = currentTime + self.interval @@ -235,16 +241,24 @@ class TimedRotatingFileHandler(BaseRotatingHandler): daysToWait = self.dayOfWeek - day else: daysToWait = 6 - day + self.dayOfWeek + 1 - self.rolloverAt = self.rolloverAt + (daysToWait * (60 * 60 * 24)) + newRolloverAt = self.rolloverAt + (daysToWait * (60 * 60 * 24)) + dstNow = t[-1] + dstAtRollover = time.localtime(newRolloverAt)[-1] + if dstNow != dstAtRollover: + if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour + newRolloverAt = newRolloverAt - 3600 + else: # DST bows out before next rollover, so we need to add an hour + newRolloverAt = newRolloverAt + 3600 + self.rolloverAt = newRolloverAt #print "Will rollover at %d, %d seconds from now" % (self.rolloverAt, self.rolloverAt - currentTime) def shouldRollover(self, record): """ - Determine if rollover should occur + Determine if rollover should occur. record is not used, as we are just comparing times, but it is needed so - the method siguratures are the same + the method signatures are the same """ t = int(time.time()) if t >= self.rolloverAt: @@ -252,6 +266,29 @@ class TimedRotatingFileHandler(BaseRotatingHandler): #print "No need to rollover: %d, %d" % (t, self.rolloverAt) return 0 + def getFilesToDelete(self): + """ + Determine the files to delete when rolling over. + + More specific than the earlier method, which just used glob.glob(). + """ + dirName, baseName = os.path.split(self.baseFilename) + fileNames = os.listdir(dirName) + result = [] + prefix = baseName + "." + plen = len(prefix) + for fileName in fileNames: + if fileName[:plen] == prefix: + suffix = fileName[plen:] + if self.extMatch.match(suffix): + result.append(fileName) + result.sort() + if len(result) < self.backupCount: + result = [] + else: + result = result[:len(result) - self.backupCount] + return result + def doRollover(self): """ do a rollover; in this case, a date/time stamp is appended to the filename @@ -270,14 +307,29 @@ class TimedRotatingFileHandler(BaseRotatingHandler): os.rename(self.baseFilename, dfn) if self.backupCount > 0: # find the oldest log file and delete it - s = glob.glob(self.baseFilename + ".20*") - if len(s) > self.backupCount: - s.sort() - os.remove(s[0]) + #s = glob.glob(self.baseFilename + ".20*") + #if len(s) > self.backupCount: + # s.sort() + # os.remove(s[0]) + for s in self.getFilesToDelete(): + os.remove(s) #print "%s -> %s" % (self.baseFilename, dfn) self.mode = 'w' self.stream = self._open() - self.rolloverAt = self.rolloverAt + self.interval + newRolloverAt = self.rolloverAt + self.interval + currentTime = int(time.time()) + while newRolloverAt <= currentTime: + newRolloverAt = newRolloverAt + self.interval + #If DST changes and midnight or weekly rollover, adjust for this. + if self.when == 'MIDNIGHT' or self.when.startswith('W'): + dstNow = time.localtime(currentTime)[-1] + dstAtRollover = time.localtime(newRolloverAt)[-1] + if dstNow != dstAtRollover: + if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour + newRolloverAt = newRolloverAt - 3600 + else: # DST bows out before next rollover, so we need to add an hour + newRolloverAt = newRolloverAt + 3600 + self.rolloverAt = newRolloverAt class WatchedFileHandler(logging.FileHandler): """ |