You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.2 KiB
Python

################################################################################
# Copyright (C) 2013-2014 gempa GmbH
#
# Thread-safe file logger
#
# Author: Stephan Herrnkind
# Email: herrnkind@gempa.de
################################################################################
from __future__ import absolute_import, division, print_function
import os
import sys
import time
import threading
if sys.version_info[0] < 3:
from Queue import Queue # pylint: disable=E0401
else:
from queue import Queue
#-------------------------------------------------------------------------------
def _worker(log):
while True:
# pylint: disable=W0212
msg = log._queue.get()
log._write(str(msg))
log._queue.task_done()
################################################################################
class Log:
#---------------------------------------------------------------------------
def __init__(self, filePath, archiveSize=7):
self._filePath = filePath
self._basePath = os.path.dirname(filePath)
self._fileName = os.path.basename(filePath)
self._archiveSize = archiveSize
self._queue = Queue()
self._lastLogTime = None
self._fd = None
if self._archiveSize < 0:
self._archiveSize = 0
# worker thread, responsible for writing messages to file
t = threading.Thread(target=_worker, args=(self,))
t.daemon = True
t.start()
#---------------------------------------------------------------------------
def __del__(self):
# wait for worker thread to write all pending log messages
self._queue.join()
if self._fd is not None:
self._fd.close()
#---------------------------------------------------------------------------
def log(self, msg):
self._queue.put(msg)
#---------------------------------------------------------------------------
def _rotate(self):
self._fd.close()
self._fd = None
try:
pattern = self._filePath + ".%i"
for i in range(self._archiveSize, 1, -1):
src = pattern % (i-1)
if os.path.isfile(src):
os.rename(pattern % (i-1), pattern % i)
os.rename(self._filePath, pattern % 1)
except Exception as e:
print("failed to rotate access log: %s\n" % str(e), file=sys.stderr)
self._fd = open(self._filePath, 'w')
#---------------------------------------------------------------------------
def _write(self, msg):
try:
now = time.localtime()
if self._fd is None:
if self._basePath and not os.path.exists(self._basePath):
os.makedirs(self._basePath)
self._fd = open(self._filePath, 'a')
elif self._archiveSize > 0 and self._lastLogTime is not None and \
(self._lastLogTime.tm_yday != now.tm_yday or
self._lastLogTime.tm_year != now.tm_year):
self._rotate()
self._fd.write("%s\n" % msg)
self._fd.flush()
self._lastLogTime = now
except Exception as e:
print("access log: %s\n" % str(e), file=sys.stderr)
# vim: ts=4 et