Edit File by line
/home/barbar84/www/wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../usr/lib64/python3..../logging
File: handlers.py
# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved.
[0] Fix | Delete
#
[1] Fix | Delete
# Permission to use, copy, modify, and distribute this software and its
[2] Fix | Delete
# documentation for any purpose and without fee is hereby granted,
[3] Fix | Delete
# provided that the above copyright notice appear in all copies and that
[4] Fix | Delete
# both that copyright notice and this permission notice appear in
[5] Fix | Delete
# supporting documentation, and that the name of Vinay Sajip
[6] Fix | Delete
# not be used in advertising or publicity pertaining to distribution
[7] Fix | Delete
# of the software without specific, written prior permission.
[8] Fix | Delete
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
[9] Fix | Delete
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
[10] Fix | Delete
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
[11] Fix | Delete
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
[12] Fix | Delete
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
[13] Fix | Delete
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
[14] Fix | Delete
[15] Fix | Delete
"""
[16] Fix | Delete
Additional handlers for the logging package for Python. The core package is
[17] Fix | Delete
based on PEP 282 and comments thereto in comp.lang.python.
[18] Fix | Delete
[19] Fix | Delete
Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved.
[20] Fix | Delete
[21] Fix | Delete
To use, simply 'import logging.handlers' and log away!
[22] Fix | Delete
"""
[23] Fix | Delete
[24] Fix | Delete
import logging, socket, os, pickle, struct, time, re
[25] Fix | Delete
from stat import ST_DEV, ST_INO, ST_MTIME
[26] Fix | Delete
import queue
[27] Fix | Delete
try:
[28] Fix | Delete
import threading
[29] Fix | Delete
except ImportError: #pragma: no cover
[30] Fix | Delete
threading = None
[31] Fix | Delete
[32] Fix | Delete
#
[33] Fix | Delete
# Some constants...
[34] Fix | Delete
#
[35] Fix | Delete
[36] Fix | Delete
DEFAULT_TCP_LOGGING_PORT = 9020
[37] Fix | Delete
DEFAULT_UDP_LOGGING_PORT = 9021
[38] Fix | Delete
DEFAULT_HTTP_LOGGING_PORT = 9022
[39] Fix | Delete
DEFAULT_SOAP_LOGGING_PORT = 9023
[40] Fix | Delete
SYSLOG_UDP_PORT = 514
[41] Fix | Delete
SYSLOG_TCP_PORT = 514
[42] Fix | Delete
[43] Fix | Delete
_MIDNIGHT = 24 * 60 * 60 # number of seconds in a day
[44] Fix | Delete
[45] Fix | Delete
class BaseRotatingHandler(logging.FileHandler):
[46] Fix | Delete
"""
[47] Fix | Delete
Base class for handlers that rotate log files at a certain point.
[48] Fix | Delete
Not meant to be instantiated directly. Instead, use RotatingFileHandler
[49] Fix | Delete
or TimedRotatingFileHandler.
[50] Fix | Delete
"""
[51] Fix | Delete
def __init__(self, filename, mode, encoding=None, delay=False):
[52] Fix | Delete
"""
[53] Fix | Delete
Use the specified filename for streamed logging
[54] Fix | Delete
"""
[55] Fix | Delete
logging.FileHandler.__init__(self, filename, mode, encoding, delay)
[56] Fix | Delete
self.mode = mode
[57] Fix | Delete
self.encoding = encoding
[58] Fix | Delete
self.namer = None
[59] Fix | Delete
self.rotator = None
[60] Fix | Delete
[61] Fix | Delete
def emit(self, record):
[62] Fix | Delete
"""
[63] Fix | Delete
Emit a record.
[64] Fix | Delete
[65] Fix | Delete
Output the record to the file, catering for rollover as described
[66] Fix | Delete
in doRollover().
[67] Fix | Delete
"""
[68] Fix | Delete
try:
[69] Fix | Delete
if self.shouldRollover(record):
[70] Fix | Delete
self.doRollover()
[71] Fix | Delete
logging.FileHandler.emit(self, record)
[72] Fix | Delete
except Exception:
[73] Fix | Delete
self.handleError(record)
[74] Fix | Delete
[75] Fix | Delete
def rotation_filename(self, default_name):
[76] Fix | Delete
"""
[77] Fix | Delete
Modify the filename of a log file when rotating.
[78] Fix | Delete
[79] Fix | Delete
This is provided so that a custom filename can be provided.
[80] Fix | Delete
[81] Fix | Delete
The default implementation calls the 'namer' attribute of the
[82] Fix | Delete
handler, if it's callable, passing the default name to
[83] Fix | Delete
it. If the attribute isn't callable (the default is None), the name
[84] Fix | Delete
is returned unchanged.
[85] Fix | Delete
[86] Fix | Delete
:param default_name: The default name for the log file.
[87] Fix | Delete
"""
[88] Fix | Delete
if not callable(self.namer):
[89] Fix | Delete
result = default_name
[90] Fix | Delete
else:
[91] Fix | Delete
result = self.namer(default_name)
[92] Fix | Delete
return result
[93] Fix | Delete
[94] Fix | Delete
def rotate(self, source, dest):
[95] Fix | Delete
"""
[96] Fix | Delete
When rotating, rotate the current log.
[97] Fix | Delete
[98] Fix | Delete
The default implementation calls the 'rotator' attribute of the
[99] Fix | Delete
handler, if it's callable, passing the source and dest arguments to
[100] Fix | Delete
it. If the attribute isn't callable (the default is None), the source
[101] Fix | Delete
is simply renamed to the destination.
[102] Fix | Delete
[103] Fix | Delete
:param source: The source filename. This is normally the base
[104] Fix | Delete
filename, e.g. 'test.log'
[105] Fix | Delete
:param dest: The destination filename. This is normally
[106] Fix | Delete
what the source is rotated to, e.g. 'test.log.1'.
[107] Fix | Delete
"""
[108] Fix | Delete
if not callable(self.rotator):
[109] Fix | Delete
# Issue 18940: A file may not have been created if delay is True.
[110] Fix | Delete
if os.path.exists(source):
[111] Fix | Delete
os.rename(source, dest)
[112] Fix | Delete
else:
[113] Fix | Delete
self.rotator(source, dest)
[114] Fix | Delete
[115] Fix | Delete
class RotatingFileHandler(BaseRotatingHandler):
[116] Fix | Delete
"""
[117] Fix | Delete
Handler for logging to a set of files, which switches from one file
[118] Fix | Delete
to the next when the current file reaches a certain size.
[119] Fix | Delete
"""
[120] Fix | Delete
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False):
[121] Fix | Delete
"""
[122] Fix | Delete
Open the specified file and use it as the stream for logging.
[123] Fix | Delete
[124] Fix | Delete
By default, the file grows indefinitely. You can specify particular
[125] Fix | Delete
values of maxBytes and backupCount to allow the file to rollover at
[126] Fix | Delete
a predetermined size.
[127] Fix | Delete
[128] Fix | Delete
Rollover occurs whenever the current log file is nearly maxBytes in
[129] Fix | Delete
length. If backupCount is >= 1, the system will successively create
[130] Fix | Delete
new files with the same pathname as the base file, but with extensions
[131] Fix | Delete
".1", ".2" etc. appended to it. For example, with a backupCount of 5
[132] Fix | Delete
and a base file name of "app.log", you would get "app.log",
[133] Fix | Delete
"app.log.1", "app.log.2", ... through to "app.log.5". The file being
[134] Fix | Delete
written to is always "app.log" - when it gets filled up, it is closed
[135] Fix | Delete
and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc.
[136] Fix | Delete
exist, then they are renamed to "app.log.2", "app.log.3" etc.
[137] Fix | Delete
respectively.
[138] Fix | Delete
[139] Fix | Delete
If maxBytes is zero, rollover never occurs.
[140] Fix | Delete
"""
[141] Fix | Delete
# If rotation/rollover is wanted, it doesn't make sense to use another
[142] Fix | Delete
# mode. If for example 'w' were specified, then if there were multiple
[143] Fix | Delete
# runs of the calling application, the logs from previous runs would be
[144] Fix | Delete
# lost if the 'w' is respected, because the log file would be truncated
[145] Fix | Delete
# on each run.
[146] Fix | Delete
if maxBytes > 0:
[147] Fix | Delete
mode = 'a'
[148] Fix | Delete
BaseRotatingHandler.__init__(self, filename, mode, encoding, delay)
[149] Fix | Delete
self.maxBytes = maxBytes
[150] Fix | Delete
self.backupCount = backupCount
[151] Fix | Delete
[152] Fix | Delete
def doRollover(self):
[153] Fix | Delete
"""
[154] Fix | Delete
Do a rollover, as described in __init__().
[155] Fix | Delete
"""
[156] Fix | Delete
if self.stream:
[157] Fix | Delete
self.stream.close()
[158] Fix | Delete
self.stream = None
[159] Fix | Delete
if self.backupCount > 0:
[160] Fix | Delete
for i in range(self.backupCount - 1, 0, -1):
[161] Fix | Delete
sfn = self.rotation_filename("%s.%d" % (self.baseFilename, i))
[162] Fix | Delete
dfn = self.rotation_filename("%s.%d" % (self.baseFilename,
[163] Fix | Delete
i + 1))
[164] Fix | Delete
if os.path.exists(sfn):
[165] Fix | Delete
if os.path.exists(dfn):
[166] Fix | Delete
os.remove(dfn)
[167] Fix | Delete
os.rename(sfn, dfn)
[168] Fix | Delete
dfn = self.rotation_filename(self.baseFilename + ".1")
[169] Fix | Delete
if os.path.exists(dfn):
[170] Fix | Delete
os.remove(dfn)
[171] Fix | Delete
self.rotate(self.baseFilename, dfn)
[172] Fix | Delete
if not self.delay:
[173] Fix | Delete
self.stream = self._open()
[174] Fix | Delete
[175] Fix | Delete
def shouldRollover(self, record):
[176] Fix | Delete
"""
[177] Fix | Delete
Determine if rollover should occur.
[178] Fix | Delete
[179] Fix | Delete
Basically, see if the supplied record would cause the file to exceed
[180] Fix | Delete
the size limit we have.
[181] Fix | Delete
"""
[182] Fix | Delete
# See bpo-45401: Never rollover anything other than regular files
[183] Fix | Delete
if os.path.exists(self.baseFilename) and not os.path.isfile(self.baseFilename):
[184] Fix | Delete
return False
[185] Fix | Delete
if self.stream is None: # delay was set...
[186] Fix | Delete
self.stream = self._open()
[187] Fix | Delete
if self.maxBytes > 0: # are we rolling over?
[188] Fix | Delete
msg = "%s\n" % self.format(record)
[189] Fix | Delete
self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
[190] Fix | Delete
if self.stream.tell() + len(msg) >= self.maxBytes:
[191] Fix | Delete
return True
[192] Fix | Delete
return False
[193] Fix | Delete
[194] Fix | Delete
class TimedRotatingFileHandler(BaseRotatingHandler):
[195] Fix | Delete
"""
[196] Fix | Delete
Handler for logging to a file, rotating the log file at certain timed
[197] Fix | Delete
intervals.
[198] Fix | Delete
[199] Fix | Delete
If backupCount is > 0, when rollover is done, no more than backupCount
[200] Fix | Delete
files are kept - the oldest ones are deleted.
[201] Fix | Delete
"""
[202] Fix | Delete
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
[203] Fix | Delete
BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
[204] Fix | Delete
self.when = when.upper()
[205] Fix | Delete
self.backupCount = backupCount
[206] Fix | Delete
self.utc = utc
[207] Fix | Delete
self.atTime = atTime
[208] Fix | Delete
# Calculate the real rollover interval, which is just the number of
[209] Fix | Delete
# seconds between rollovers. Also set the filename suffix used when
[210] Fix | Delete
# a rollover occurs. Current 'when' events supported:
[211] Fix | Delete
# S - Seconds
[212] Fix | Delete
# M - Minutes
[213] Fix | Delete
# H - Hours
[214] Fix | Delete
# D - Days
[215] Fix | Delete
# midnight - roll over at midnight
[216] Fix | Delete
# W{0-6} - roll over on a certain day; 0 - Monday
[217] Fix | Delete
#
[218] Fix | Delete
# Case of the 'when' specifier is not important; lower or upper case
[219] Fix | Delete
# will work.
[220] Fix | Delete
if self.when == 'S':
[221] Fix | Delete
self.interval = 1 # one second
[222] Fix | Delete
self.suffix = "%Y-%m-%d_%H-%M-%S"
[223] Fix | Delete
self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(\.\w+)?$"
[224] Fix | Delete
elif self.when == 'M':
[225] Fix | Delete
self.interval = 60 # one minute
[226] Fix | Delete
self.suffix = "%Y-%m-%d_%H-%M"
[227] Fix | Delete
self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}(\.\w+)?$"
[228] Fix | Delete
elif self.when == 'H':
[229] Fix | Delete
self.interval = 60 * 60 # one hour
[230] Fix | Delete
self.suffix = "%Y-%m-%d_%H"
[231] Fix | Delete
self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}(\.\w+)?$"
[232] Fix | Delete
elif self.when == 'D' or self.when == 'MIDNIGHT':
[233] Fix | Delete
self.interval = 60 * 60 * 24 # one day
[234] Fix | Delete
self.suffix = "%Y-%m-%d"
[235] Fix | Delete
self.extMatch = r"^\d{4}-\d{2}-\d{2}(\.\w+)?$"
[236] Fix | Delete
elif self.when.startswith('W'):
[237] Fix | Delete
self.interval = 60 * 60 * 24 * 7 # one week
[238] Fix | Delete
if len(self.when) != 2:
[239] Fix | Delete
raise ValueError("You must specify a day for weekly rollover from 0 to 6 (0 is Monday): %s" % self.when)
[240] Fix | Delete
if self.when[1] < '0' or self.when[1] > '6':
[241] Fix | Delete
raise ValueError("Invalid day specified for weekly rollover: %s" % self.when)
[242] Fix | Delete
self.dayOfWeek = int(self.when[1])
[243] Fix | Delete
self.suffix = "%Y-%m-%d"
[244] Fix | Delete
self.extMatch = r"^\d{4}-\d{2}-\d{2}(\.\w+)?$"
[245] Fix | Delete
else:
[246] Fix | Delete
raise ValueError("Invalid rollover interval specified: %s" % self.when)
[247] Fix | Delete
[248] Fix | Delete
self.extMatch = re.compile(self.extMatch, re.ASCII)
[249] Fix | Delete
self.interval = self.interval * interval # multiply by units requested
[250] Fix | Delete
# The following line added because the filename passed in could be a
[251] Fix | Delete
# path object (see Issue #27493), but self.baseFilename will be a string
[252] Fix | Delete
filename = self.baseFilename
[253] Fix | Delete
if os.path.exists(filename):
[254] Fix | Delete
t = os.stat(filename)[ST_MTIME]
[255] Fix | Delete
else:
[256] Fix | Delete
t = int(time.time())
[257] Fix | Delete
self.rolloverAt = self.computeRollover(t)
[258] Fix | Delete
[259] Fix | Delete
def computeRollover(self, currentTime):
[260] Fix | Delete
"""
[261] Fix | Delete
Work out the rollover time based on the specified time.
[262] Fix | Delete
"""
[263] Fix | Delete
result = currentTime + self.interval
[264] Fix | Delete
# If we are rolling over at midnight or weekly, then the interval is already known.
[265] Fix | Delete
# What we need to figure out is WHEN the next interval is. In other words,
[266] Fix | Delete
# if you are rolling over at midnight, then your base interval is 1 day,
[267] Fix | Delete
# but you want to start that one day clock at midnight, not now. So, we
[268] Fix | Delete
# have to fudge the rolloverAt value in order to trigger the first rollover
[269] Fix | Delete
# at the right time. After that, the regular interval will take care of
[270] Fix | Delete
# the rest. Note that this code doesn't care about leap seconds. :)
[271] Fix | Delete
if self.when == 'MIDNIGHT' or self.when.startswith('W'):
[272] Fix | Delete
# This could be done with less code, but I wanted it to be clear
[273] Fix | Delete
if self.utc:
[274] Fix | Delete
t = time.gmtime(currentTime)
[275] Fix | Delete
else:
[276] Fix | Delete
t = time.localtime(currentTime)
[277] Fix | Delete
currentHour = t[3]
[278] Fix | Delete
currentMinute = t[4]
[279] Fix | Delete
currentSecond = t[5]
[280] Fix | Delete
currentDay = t[6]
[281] Fix | Delete
# r is the number of seconds left between now and the next rotation
[282] Fix | Delete
if self.atTime is None:
[283] Fix | Delete
rotate_ts = _MIDNIGHT
[284] Fix | Delete
else:
[285] Fix | Delete
rotate_ts = ((self.atTime.hour * 60 + self.atTime.minute)*60 +
[286] Fix | Delete
self.atTime.second)
[287] Fix | Delete
[288] Fix | Delete
r = rotate_ts - ((currentHour * 60 + currentMinute) * 60 +
[289] Fix | Delete
currentSecond)
[290] Fix | Delete
if r < 0:
[291] Fix | Delete
# Rotate time is before the current time (for example when
[292] Fix | Delete
# self.rotateAt is 13:45 and it now 14:15), rotation is
[293] Fix | Delete
# tomorrow.
[294] Fix | Delete
r += _MIDNIGHT
[295] Fix | Delete
currentDay = (currentDay + 1) % 7
[296] Fix | Delete
result = currentTime + r
[297] Fix | Delete
# If we are rolling over on a certain day, add in the number of days until
[298] Fix | Delete
# the next rollover, but offset by 1 since we just calculated the time
[299] Fix | Delete
# until the next day starts. There are three cases:
[300] Fix | Delete
# Case 1) The day to rollover is today; in this case, do nothing
[301] Fix | Delete
# Case 2) The day to rollover is further in the interval (i.e., today is
[302] Fix | Delete
# day 2 (Wednesday) and rollover is on day 6 (Sunday). Days to
[303] Fix | Delete
# next rollover is simply 6 - 2 - 1, or 3.
[304] Fix | Delete
# Case 3) The day to rollover is behind us in the interval (i.e., today
[305] Fix | Delete
# is day 5 (Saturday) and rollover is on day 3 (Thursday).
[306] Fix | Delete
# Days to rollover is 6 - 5 + 3, or 4. In this case, it's the
[307] Fix | Delete
# number of days left in the current week (1) plus the number
[308] Fix | Delete
# of days in the next week until the rollover day (3).
[309] Fix | Delete
# The calculations described in 2) and 3) above need to have a day added.
[310] Fix | Delete
# This is because the above time calculation takes us to midnight on this
[311] Fix | Delete
# day, i.e. the start of the next day.
[312] Fix | Delete
if self.when.startswith('W'):
[313] Fix | Delete
day = currentDay # 0 is Monday
[314] Fix | Delete
if day != self.dayOfWeek:
[315] Fix | Delete
if day < self.dayOfWeek:
[316] Fix | Delete
daysToWait = self.dayOfWeek - day
[317] Fix | Delete
else:
[318] Fix | Delete
daysToWait = 6 - day + self.dayOfWeek + 1
[319] Fix | Delete
newRolloverAt = result + (daysToWait * (60 * 60 * 24))
[320] Fix | Delete
if not self.utc:
[321] Fix | Delete
dstNow = t[-1]
[322] Fix | Delete
dstAtRollover = time.localtime(newRolloverAt)[-1]
[323] Fix | Delete
if dstNow != dstAtRollover:
[324] Fix | Delete
if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour
[325] Fix | Delete
addend = -3600
[326] Fix | Delete
else: # DST bows out before next rollover, so we need to add an hour
[327] Fix | Delete
addend = 3600
[328] Fix | Delete
newRolloverAt += addend
[329] Fix | Delete
result = newRolloverAt
[330] Fix | Delete
return result
[331] Fix | Delete
[332] Fix | Delete
def shouldRollover(self, record):
[333] Fix | Delete
"""
[334] Fix | Delete
Determine if rollover should occur.
[335] Fix | Delete
[336] Fix | Delete
record is not used, as we are just comparing times, but it is needed so
[337] Fix | Delete
the method signatures are the same
[338] Fix | Delete
"""
[339] Fix | Delete
# See bpo-45401: Never rollover anything other than regular files
[340] Fix | Delete
if os.path.exists(self.baseFilename) and not os.path.isfile(self.baseFilename):
[341] Fix | Delete
return False
[342] Fix | Delete
t = int(time.time())
[343] Fix | Delete
if t >= self.rolloverAt:
[344] Fix | Delete
return True
[345] Fix | Delete
return False
[346] Fix | Delete
[347] Fix | Delete
def getFilesToDelete(self):
[348] Fix | Delete
"""
[349] Fix | Delete
Determine the files to delete when rolling over.
[350] Fix | Delete
[351] Fix | Delete
More specific than the earlier method, which just used glob.glob().
[352] Fix | Delete
"""
[353] Fix | Delete
dirName, baseName = os.path.split(self.baseFilename)
[354] Fix | Delete
fileNames = os.listdir(dirName)
[355] Fix | Delete
result = []
[356] Fix | Delete
prefix = baseName + "."
[357] Fix | Delete
plen = len(prefix)
[358] Fix | Delete
for fileName in fileNames:
[359] Fix | Delete
if fileName[:plen] == prefix:
[360] Fix | Delete
suffix = fileName[plen:]
[361] Fix | Delete
if self.extMatch.match(suffix):
[362] Fix | Delete
result.append(os.path.join(dirName, fileName))
[363] Fix | Delete
if len(result) < self.backupCount:
[364] Fix | Delete
result = []
[365] Fix | Delete
else:
[366] Fix | Delete
result.sort()
[367] Fix | Delete
result = result[:len(result) - self.backupCount]
[368] Fix | Delete
return result
[369] Fix | Delete
[370] Fix | Delete
def doRollover(self):
[371] Fix | Delete
"""
[372] Fix | Delete
do a rollover; in this case, a date/time stamp is appended to the filename
[373] Fix | Delete
when the rollover happens. However, you want the file to be named for the
[374] Fix | Delete
start of the interval, not the current time. If there is a backup count,
[375] Fix | Delete
then we have to get a list of matching filenames, sort them and remove
[376] Fix | Delete
the one with the oldest suffix.
[377] Fix | Delete
"""
[378] Fix | Delete
if self.stream:
[379] Fix | Delete
self.stream.close()
[380] Fix | Delete
self.stream = None
[381] Fix | Delete
# get the time that this sequence started at and make it a TimeTuple
[382] Fix | Delete
currentTime = int(time.time())
[383] Fix | Delete
dstNow = time.localtime(currentTime)[-1]
[384] Fix | Delete
t = self.rolloverAt - self.interval
[385] Fix | Delete
if self.utc:
[386] Fix | Delete
timeTuple = time.gmtime(t)
[387] Fix | Delete
else:
[388] Fix | Delete
timeTuple = time.localtime(t)
[389] Fix | Delete
dstThen = timeTuple[-1]
[390] Fix | Delete
if dstNow != dstThen:
[391] Fix | Delete
if dstNow:
[392] Fix | Delete
addend = 3600
[393] Fix | Delete
else:
[394] Fix | Delete
addend = -3600
[395] Fix | Delete
timeTuple = time.localtime(t + addend)
[396] Fix | Delete
dfn = self.rotation_filename(self.baseFilename + "." +
[397] Fix | Delete
time.strftime(self.suffix, timeTuple))
[398] Fix | Delete
if os.path.exists(dfn):
[399] Fix | Delete
os.remove(dfn)
[400] Fix | Delete
self.rotate(self.baseFilename, dfn)
[401] Fix | Delete
if self.backupCount > 0:
[402] Fix | Delete
for s in self.getFilesToDelete():
[403] Fix | Delete
os.remove(s)
[404] Fix | Delete
if not self.delay:
[405] Fix | Delete
self.stream = self._open()
[406] Fix | Delete
newRolloverAt = self.computeRollover(currentTime)
[407] Fix | Delete
while newRolloverAt <= currentTime:
[408] Fix | Delete
newRolloverAt = newRolloverAt + self.interval
[409] Fix | Delete
#If DST changes and midnight or weekly rollover, adjust for this.
[410] Fix | Delete
if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
[411] Fix | Delete
dstAtRollover = time.localtime(newRolloverAt)[-1]
[412] Fix | Delete
if dstNow != dstAtRollover:
[413] Fix | Delete
if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour
[414] Fix | Delete
addend = -3600
[415] Fix | Delete
else: # DST bows out before next rollover, so we need to add an hour
[416] Fix | Delete
addend = 3600
[417] Fix | Delete
newRolloverAt += addend
[418] Fix | Delete
self.rolloverAt = newRolloverAt
[419] Fix | Delete
[420] Fix | Delete
class WatchedFileHandler(logging.FileHandler):
[421] Fix | Delete
"""
[422] Fix | Delete
A handler for logging to a file, which watches the file
[423] Fix | Delete
to see if it has changed while in use. This can happen because of
[424] Fix | Delete
usage of programs such as newsyslog and logrotate which perform
[425] Fix | Delete
log file rotation. This handler, intended for use under Unix,
[426] Fix | Delete
watches the file to see if it has changed since the last emit.
[427] Fix | Delete
(A file has changed if its device or inode have changed.)
[428] Fix | Delete
If it has changed, the old file stream is closed, and the file
[429] Fix | Delete
opened to get a new stream.
[430] Fix | Delete
[431] Fix | Delete
This handler is not appropriate for use under Windows, because
[432] Fix | Delete
under Windows open files cannot be moved or renamed - logging
[433] Fix | Delete
opens the files with exclusive locks - and so there is no need
[434] Fix | Delete
for such a handler. Furthermore, ST_INO is not supported under
[435] Fix | Delete
Windows; stat always returns zero for this value.
[436] Fix | Delete
[437] Fix | Delete
This handler is based on a suggestion and patch by Chad J.
[438] Fix | Delete
Schroeder.
[439] Fix | Delete
"""
[440] Fix | Delete
def __init__(self, filename, mode='a', encoding=None, delay=False):
[441] Fix | Delete
logging.FileHandler.__init__(self, filename, mode, encoding, delay)
[442] Fix | Delete
self.dev, self.ino = -1, -1
[443] Fix | Delete
self._statstream()
[444] Fix | Delete
[445] Fix | Delete
def _statstream(self):
[446] Fix | Delete
if self.stream:
[447] Fix | Delete
sres = os.fstat(self.stream.fileno())
[448] Fix | Delete
self.dev, self.ino = sres[ST_DEV], sres[ST_INO]
[449] Fix | Delete
[450] Fix | Delete
def reopenIfNeeded(self):
[451] Fix | Delete
"""
[452] Fix | Delete
Reopen log file if needed.
[453] Fix | Delete
[454] Fix | Delete
Checks if the underlying file has changed, and if it
[455] Fix | Delete
has, close the old stream and reopen the file to get the
[456] Fix | Delete
current stream.
[457] Fix | Delete
"""
[458] Fix | Delete
# Reduce the chance of race conditions by stat'ing by path only
[459] Fix | Delete
# once and then fstat'ing our new fd if we opened a new log stream.
[460] Fix | Delete
# See issue #14632: Thanks to John Mulligan for the problem report
[461] Fix | Delete
# and patch.
[462] Fix | Delete
try:
[463] Fix | Delete
# stat the file by path, checking for existence
[464] Fix | Delete
sres = os.stat(self.baseFilename)
[465] Fix | Delete
except FileNotFoundError:
[466] Fix | Delete
sres = None
[467] Fix | Delete
# compare file system stat with that of our stream file handle
[468] Fix | Delete
if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino:
[469] Fix | Delete
if self.stream is not None:
[470] Fix | Delete
# we have an open file handle, clean it up
[471] Fix | Delete
self.stream.flush()
[472] Fix | Delete
self.stream.close()
[473] Fix | Delete
self.stream = None # See Issue #21742: _open () might fail.
[474] Fix | Delete
# open a new file handle and get new stat info from that fd
[475] Fix | Delete
self.stream = self._open()
[476] Fix | Delete
self._statstream()
[477] Fix | Delete
[478] Fix | Delete
def emit(self, record):
[479] Fix | Delete
"""
[480] Fix | Delete
Emit a record.
[481] Fix | Delete
[482] Fix | Delete
If underlying file has changed, reopen the file before emitting the
[483] Fix | Delete
record to it.
[484] Fix | Delete
"""
[485] Fix | Delete
self.reopenIfNeeded()
[486] Fix | Delete
logging.FileHandler.emit(self, record)
[487] Fix | Delete
[488] Fix | Delete
[489] Fix | Delete
class SocketHandler(logging.Handler):
[490] Fix | Delete
"""
[491] Fix | Delete
A handler class which writes logging records, in pickle format, to
[492] Fix | Delete
a streaming socket. The socket is kept open across logging calls.
[493] Fix | Delete
If the peer resets it, an attempt is made to reconnect on the next call.
[494] Fix | Delete
The pickle which is sent is that of the LogRecord's attribute dictionary
[495] Fix | Delete
(__dict__), so that the receiver does not need to have the logging module
[496] Fix | Delete
installed in order to process the logging event.
[497] Fix | Delete
[498] Fix | Delete
To unpickle the record at the receiving end into a LogRecord, use the
[499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function