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