155 lines
5.9 KiB
Python
155 lines
5.9 KiB
Python
import os, time, shutil
|
|
from threading import Thread
|
|
|
|
class log(object):
|
|
def __init__(self, workdir):
|
|
'''
|
|
Init vars and threads.
|
|
'''
|
|
self.FATAL = "FATAL"
|
|
self.ERROR = "ERROR"
|
|
self.WARN = "WARN"
|
|
self.INFO = "INFO"
|
|
self.__levelMap = {
|
|
'FATAL': self.FATAL,
|
|
'ERROR': self.ERROR,
|
|
'WARN': self.WARN,
|
|
'INFO': self.INFO
|
|
}
|
|
if type(workdir) != str:
|
|
raise TypeError("Wrong type for param @workdir")
|
|
self.workdir = workdir
|
|
self.__logs = []
|
|
if os.path.exists(os.path.join(workdir, "logs")) and os.path.isdir(os.path.join(workdir, "logs")):
|
|
daemon = Thread(target = self.__daemon, name = "log4py-daemon")
|
|
daemon.daemon = True
|
|
daemon.start()
|
|
else:
|
|
try:
|
|
os.makedirs(os.path.join(workdir, "logs"), exist_ok = True)
|
|
daemon = Thread(target = self.__daemon, name = "log4py-daemon")
|
|
daemon.daemon = True
|
|
daemon.start()
|
|
except:
|
|
raise PermissionError("Failed to operate the log file! ")
|
|
def __daemon(self):
|
|
'''
|
|
Guard thread for recording logs and archiving.
|
|
'''
|
|
workdir = os.path.abspath(os.path.join(self.workdir, "logs"))
|
|
self.__suicide = False
|
|
def archive(workdir):
|
|
timeStamp = time.time()
|
|
logsList = []
|
|
for fname in os.listdir(workdir):
|
|
if os.path.isfile(os.path.join(workdir, fname)):
|
|
logsList.append(os.path.join(workdir, fname))
|
|
archiveList = []
|
|
today = time.strftime("%Y-%m-%d", time.localtime(timeStamp))
|
|
# yesterday = time.strftime("%Y-%m-%d", time.localtime(timeStamp - 86400))
|
|
flag = False
|
|
for fname in logsList:
|
|
if os.path.basename(fname) != "{}.logs".format(today) and os.path.splitext(fname)[-1] == ".logs":
|
|
archiveList.append(fname)
|
|
flag = True
|
|
if flag:
|
|
self.info("Archiving logs.")
|
|
# Archive each log in independence zip file
|
|
for fname in archiveList:
|
|
basename = os.path.basename(fname)
|
|
shutil.make_archive(os.path.join(workdir, os.path.splitext(basename)[0]), "zip", workdir, basename)
|
|
try:
|
|
os.remove(os.path.join(workdir, basename))
|
|
except:
|
|
pass
|
|
|
|
Thread(target = archive, args = (workdir,), name = "log4py-archive").start()
|
|
while True:
|
|
timeStamp = time.time()
|
|
today = time.strftime("%Y-%m-%d", time.localtime(timeStamp))
|
|
while True:
|
|
with open(os.path.join(workdir, "{}.logs".format(today)),"a+") as fb:
|
|
data, self.__logs = self.__logs, []
|
|
for log in data:
|
|
fb.write("[{}] [{}] {}\n".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(log[0])), log[1], log[2]))
|
|
if self.__suicide or today != time.strftime("%Y-%m-%d", time.localtime()):
|
|
break
|
|
archive(workdir)
|
|
if self.__suicide:
|
|
break
|
|
def suicide(self):
|
|
'''
|
|
Suicide the guard thread.
|
|
Before close the program, You have to exec this function.
|
|
'''
|
|
self.__suicide = True
|
|
def record(self, level = "INFO", *content, split = " ", output = True):
|
|
'''
|
|
Record logs.
|
|
@*content: The content for your log
|
|
@split: The split text for your each log
|
|
@level: The level for your log level
|
|
@output: Print the log or not
|
|
'''
|
|
temp = []
|
|
for con in content:
|
|
temp.append(str(con))
|
|
content = split.join(temp)
|
|
if type(level) != str or level not in self.__levelMap.values():
|
|
raise TypeError("Wrong type for param @level")
|
|
if type(output) != bool:
|
|
raise TypeError("Wrong type for param @output")
|
|
timeStamp = time.time()
|
|
self.__logs.append((timeStamp, level.upper(), content))
|
|
if output:
|
|
print("[{}] [{}] {}".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timeStamp)), level.upper(), content))
|
|
def info(self, *content, split = " ", output = True):
|
|
'''
|
|
Record logs for info level.
|
|
@*content: The content for your log
|
|
@split: The split text for your each log
|
|
@output: Print the log or not
|
|
'''
|
|
temp = []
|
|
for con in content:
|
|
temp.append(str(con))
|
|
content = split.join(temp)
|
|
self.record("INFO", content, split = split, output = output)
|
|
def warn(self, *content, split = " ", output = True):
|
|
'''
|
|
Record logs for warn level.
|
|
@*content: The content for your log
|
|
@split: The split text for your each log
|
|
@output: Print the log or not
|
|
'''
|
|
temp = []
|
|
for con in content:
|
|
temp.append(str(con))
|
|
content = split.join(temp)
|
|
self.record("WARN", content, split = split, output = output)
|
|
def error(self, *content, split = " ", output = True):
|
|
'''
|
|
Record logs for error level.
|
|
@*content: The content for your log
|
|
@split: The split text for your each log
|
|
@output: Print the log or not
|
|
'''
|
|
temp = []
|
|
for con in content:
|
|
temp.append(str(con))
|
|
content = split.join(temp)
|
|
self.record("ERROR", content, split = split, output = output)
|
|
def fatal(self, *content, split = " ", output = True):
|
|
'''
|
|
Record logs for fatal level.
|
|
@*content: The content for your log
|
|
@split: The split text for your each log
|
|
@output: Print the log or not
|
|
'''
|
|
temp = []
|
|
for con in content:
|
|
temp.append(str(con))
|
|
content = split.join(temp)
|
|
self.record("FATAL", content, split = split, output = output)
|
|
self.__suicide = True
|
|
raise Exception(content) |