mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-05 17:43:37 +00:00
Change log rotation to occur at midnight
Change to keep a maximum of 7 log files Add automatic compression of old log files
This commit is contained in:
parent
be3890e740
commit
ba69616cf4
2 changed files with 58 additions and 87 deletions
|
@ -46,6 +46,9 @@
|
|||
* Change to stop updating the IMDb info on edit, mass edit and during the scheduled daily update for every show
|
||||
* Change to update the IMDb info for a show after snatching an episode for it
|
||||
* Fix updating of scene exception name cache after adding exceptions on Editshow page
|
||||
* Change log rotation to occur at midnight
|
||||
* Change to keep a maximum of 7 log files
|
||||
* Add automatic compression of old log files
|
||||
|
||||
[develop changelog]
|
||||
* Fix traceback error when using the menu item Manage/Update Kodi
|
||||
|
|
|
@ -22,11 +22,14 @@ import time
|
|||
import os
|
||||
import sys
|
||||
import threading
|
||||
|
||||
import zipfile
|
||||
import logging
|
||||
import glob
|
||||
import codecs
|
||||
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
|
||||
import sickbeard
|
||||
|
||||
from sickbeard import classes
|
||||
|
||||
try:
|
||||
|
@ -34,13 +37,6 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
# number of log files to keep
|
||||
NUM_LOGS = 3
|
||||
|
||||
# log size in bytes
|
||||
LOG_SIZE = 10000000 # 10 megs
|
||||
|
||||
ERROR = logging.ERROR
|
||||
WARNING = logging.WARNING
|
||||
MESSAGE = logging.INFO
|
||||
|
@ -59,16 +55,11 @@ class NullHandler(logging.Handler):
|
|||
pass
|
||||
|
||||
class SBRotatingLogHandler(object):
|
||||
def __init__(self, log_file, num_files, num_bytes):
|
||||
self.num_files = num_files
|
||||
self.num_bytes = num_bytes
|
||||
|
||||
def __init__(self, log_file):
|
||||
self.log_file = log_file
|
||||
self.log_file_path = log_file
|
||||
self.cur_handler = None
|
||||
|
||||
self.writes_since_check = 0
|
||||
|
||||
self.console_logging = False
|
||||
self.log_lock = threading.Lock()
|
||||
|
||||
|
@ -181,7 +172,7 @@ class SBRotatingLogHandler(object):
|
|||
Configure a file handler to log at file_name and return it.
|
||||
"""
|
||||
|
||||
file_handler = logging.FileHandler(self.log_file_path, encoding='utf-8')
|
||||
file_handler = TimedCompressedRotatingFileHandler(self.log_file_path, when='midnight', backupCount=7, encoding='utf-8')
|
||||
file_handler.setLevel(DB)
|
||||
file_handler.setFormatter(DispatchingFormatter(
|
||||
{'sickbeard': logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', '%Y-%m-%d %H:%M:%S'),
|
||||
|
@ -197,79 +188,10 @@ class SBRotatingLogHandler(object):
|
|||
|
||||
return file_handler
|
||||
|
||||
def _log_file_name(self, i):
|
||||
"""
|
||||
Returns a numbered log file name depending on i. If i==0 it just uses logName, if not it appends
|
||||
it to the extension (blah.log.3 for i == 3)
|
||||
|
||||
i: Log number to ues
|
||||
"""
|
||||
|
||||
return self.log_file_path + ('.' + str(i) if i else '')
|
||||
|
||||
def _num_logs(self):
|
||||
"""
|
||||
Scans the log folder and figures out how many log files there are already on disk
|
||||
|
||||
Returns: The number of the last used file (eg. mylog.log.3 would return 3). If there are no logs it returns -1
|
||||
"""
|
||||
|
||||
cur_log = 0
|
||||
while os.path.isfile(self._log_file_name(cur_log)):
|
||||
cur_log += 1
|
||||
return cur_log - 1
|
||||
|
||||
def _rotate_logs(self):
|
||||
|
||||
sb_logger = logging.getLogger('sickbeard')
|
||||
sub_logger = logging.getLogger('subliminal')
|
||||
imdb_logger = logging.getLogger('imdbpy')
|
||||
tornado_logger = logging.getLogger('tornado')
|
||||
feedcache_logger = logging.getLogger('feedcache')
|
||||
|
||||
# delete the old handler
|
||||
if self.cur_handler:
|
||||
self.close_log()
|
||||
|
||||
# rename or delete all the old log files
|
||||
for i in range(self._num_logs(), -1, -1):
|
||||
cur_file_name = self._log_file_name(i)
|
||||
try:
|
||||
if i >= NUM_LOGS:
|
||||
if sickbeard.TRASH_ROTATE_LOGS:
|
||||
new_name = '%s.%s' % (cur_file_name, int(time.time()))
|
||||
os.rename(cur_file_name, new_name)
|
||||
send2trash(new_name)
|
||||
else:
|
||||
os.remove(cur_file_name)
|
||||
else:
|
||||
os.rename(cur_file_name, self._log_file_name(i + 1))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# the new log handler will always be on the un-numbered .log file
|
||||
new_file_handler = self._config_handler()
|
||||
|
||||
self.cur_handler = new_file_handler
|
||||
|
||||
sb_logger.addHandler(new_file_handler)
|
||||
sub_logger.addHandler(new_file_handler)
|
||||
imdb_logger.addHandler(new_file_handler)
|
||||
tornado_logger.addHandler(new_file_handler)
|
||||
feedcache_logger.addHandler(new_file_handler)
|
||||
|
||||
def log(self, toLog, logLevel=MESSAGE):
|
||||
|
||||
with self.log_lock:
|
||||
|
||||
# check the size and see if we need to rotate
|
||||
if self.writes_since_check >= 10:
|
||||
if os.path.isfile(self.log_file_path) and os.path.getsize(self.log_file_path) >= LOG_SIZE:
|
||||
self._rotate_logs()
|
||||
self.writes_since_check = 0
|
||||
else:
|
||||
self.writes_since_check += 1
|
||||
|
||||
meThread = threading.currentThread().getName()
|
||||
message = meThread + u" :: " + toLog
|
||||
|
||||
|
@ -323,7 +245,53 @@ class DispatchingFormatter:
|
|||
return formatter.format(record)
|
||||
|
||||
|
||||
sb_log_instance = SBRotatingLogHandler('sickbeard.log', NUM_LOGS, LOG_SIZE)
|
||||
class TimedCompressedRotatingFileHandler(TimedRotatingFileHandler):
|
||||
"""
|
||||
Extended version of TimedRotatingFileHandler that compress logs on rollover.
|
||||
by Angel Freire <cuerty at gmail dot com>
|
||||
"""
|
||||
def doRollover(self):
|
||||
"""
|
||||
do a rollover; in this case, a date/time stamp is appended to the filename
|
||||
when the rollover happens. However, you want the file to be named for the
|
||||
start of the interval, not the current time. If there is a backup count,
|
||||
then we have to get a list of matching filenames, sort them and remove
|
||||
the one with the oldest suffix.
|
||||
|
||||
This method is a copy of the one in TimedRotatingFileHandler. Since it uses
|
||||
|
||||
"""
|
||||
self.stream.close()
|
||||
# get the time that this sequence started at and make it a TimeTuple
|
||||
t = self.rolloverAt - self.interval
|
||||
timeTuple = time.localtime(t)
|
||||
file_name = self.baseFilename.rpartition('.')[0]
|
||||
dfn = '%s_%s.log' % (file_name, time.strftime(self.suffix, timeTuple))
|
||||
if os.path.exists(dfn):
|
||||
os.remove(dfn)
|
||||
os.rename(self.baseFilename, dfn)
|
||||
if self.backupCount > 0:
|
||||
# find the oldest log file and delete it
|
||||
s = glob.glob(file_name + '_*')
|
||||
if len(s) > self.backupCount:
|
||||
s.sort()
|
||||
os.remove(s[0])
|
||||
#print "%s -> %s" % (self.baseFilename, dfn)
|
||||
if self.encoding:
|
||||
self.stream = codecs.open(self.baseFilename, 'w', self.encoding)
|
||||
else:
|
||||
self.stream = open(self.baseFilename, 'w')
|
||||
self.rolloverAt = self.rolloverAt + self.interval
|
||||
zip_name = dfn.rpartition('.')[0] + '.zip'
|
||||
if os.path.exists(zip_name):
|
||||
os.remove(zip_name)
|
||||
file = zipfile.ZipFile(zip_name, 'w')
|
||||
file.write(dfn, os.path.basename(dfn), zipfile.ZIP_DEFLATED)
|
||||
file.close()
|
||||
os.remove(dfn)
|
||||
|
||||
|
||||
sb_log_instance = SBRotatingLogHandler('sickbeard.log')
|
||||
|
||||
|
||||
def log(toLog, logLevel=MESSAGE):
|
||||
|
@ -335,4 +303,4 @@ def log_error_and_exit(error_msg):
|
|||
|
||||
|
||||
def close():
|
||||
sb_log_instance.close_log()
|
||||
sb_log_instance.close_log()
|
Loading…
Reference in a new issue