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
104 lines
3.2 KiB
Python
1 year ago
|
################################################################################
|
||
|
# 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
|