Reputation: 262
I need file rotation to happen exactly when the hour change, not after an hour from the program has started.
PS: I took care of writing logs at <hour>:59:58
and <hour+1>:00:02
to to avoid to wait next write.
Is it possible?
[handler_file_handler]
class=handlers.TimedRotatingFileHandler
level=INFO
formatter=formatter
delay=False
args=('logfile.log', 'H', 1, 0)
Upvotes: 1
Views: 3620
Reputation: 1121494
The TimedRotatingFileHandler
documentation tells you that it uses an offset from the current time; the only exceptions are the weekday and daily options (W0-W6
and midnight
), which use atTime
as the point in time to roll over:
When computing the next rollover time for the first time (when the handler is created), the last modification time of an existing log file, or else the current time, is used to compute when the next rotation will occur.
[...]
If
atTime
is notNone
, it must be adatetime.time
instance which specifies the time of day when rollover occurs, for the cases where rollover is set to happen “at midnight” or “on a particular weekday”. Note that in these cases, theatTime
value is effectively used to compute the initial rollover, and subsequent rollovers would be calculated via the normal interval calculation.
If you must have roll-overs occur hourly, on the hour, then you have two options:
mtime
modification value set to the most recent whole hour. This will then be used to write current entries to, and it'll be rotated a whole hour from the set modification time.TimedRotatingFileHandler.computeRollover()
implementation which returns the timestamp for the next whole hour, rather than just current time + interval.The latter is probably the better path here; rounding the current time to the nearest self.interval
multiple is simple enough:
from logging.handlers import TimedRotatingFileHandler
class WholeIntervalRotatingFileHandler(TimedRotatingFileHandler):
def computeRollover(self, currentTime):
if self.when[0] == 'W' or self.when == 'MIDNIGHT':
# use existing computation
return super().computeRollover(currentTime)
# round time up to nearest next multiple of the interval
return ((currentTime // self.interval) + 1) * self.interval
This calculates the next rollover time to be an exact multiple of the interval. Take into account that if you set the interval
argument to the class to a value other than 1
then the next whole interval time value could be different; interval=2
would pick the next whole hour divisible by 2, set it to 0.5
you'd see rotation at the whole and half hour.
To use the above in a fileConfig
configuration file, just put the code in a module that lives on the module search path, then use class=modulename.WholeIntervalRotatingFileHandler
in your handler section.
Demo to show that the next computed rollover time is indeed the next whole hour:
>>> from datetime import datetime
>>> print(datetime.now()) # current time
2018-11-17 16:48:08.793855
>>> handler = WholeIntervalRotatingFileHandler('/tmp/logfile.log', 'H', 1, 0)
>>> print(datetime.fromtimestamp(handler.rolloverAt)) # next rotation time
2018-11-17 17:00:00
Upvotes: 8