"""faas logger"""
import gzip
import logging
import logging.handlers
import os
import shutil
from yr.log import CustomFilter, RuntimeLogger
LOG_DEFAULT_MAX_BYTES = 50 * 1024 * 1024
LOG_DEFAULT_BACKUP_COUNT = 3
USER_FUNCTION_LOGGER = None
class RotatingFileHandler(logging.handlers.RotatingFileHandler):
"""
RotatingFileHandler
"""
def __init__(self, file_name, mode="a", max_bytes=0, backup_count=0, log_name=""):
super(RotatingFileHandler, self).__init__(file_name, mode, max_bytes, backup_count, None, False)
self.log_name = log_name
self.backup_count = backup_count
self.log_dir = os.path.dirname(log_name)
def doRollover(self) -> None:
"""
go rollover
"""
super(RotatingFileHandler, self).doRollover()
to_compress = []
for f in os.listdir(self.log_dir):
if f.startswith(self.log_name) and not f.endswith((".gz", ".log")):
to_compress.append(os.path.join(self.log_dir, f))
self._update_zip_file_name()
for f in to_compress:
if os.path.exists(f):
with open(f, "rb") as _old, gzip.open(f + ".gz", "wb") as _new:
shutil.copyfileobj(_old, _new)
os.remove(f)
def _update_zip_file_name(self):
zip_log_files = {}
for f in os.listdir(self.log_dir):
if f.startswith(self.log_name) and f.endswith(".gz"):
f_split = f.split(".")
if len(f_split) < 3:
os.remove(os.path.join(self.log_name, f))
continue
try:
index = int(f_split[-2])
except IndexError:
os.remove(os.path.join(self.log_dir, f))
continue
finally:
pass
if index >= self.backup_count:
os.remove(os.path.join(self.log_dir, f))
continue
zip_log_files[index] = os.path.join(self.log_dir, f)
for i in range(self.backup_count - 1, 0, -1):
if i in zip_log_files:
f_split = zip_log_files.get(i).split(".")
f_split[-2] = str(i + 1)
os.rename(zip_log_files.get(i), ".".join(f_split))
del zip_log_files
def init_user_function_log(loglevel, logger=None):
""" initialize user function log """
global USER_FUNCTION_LOGGER
if logger is not None:
USER_FUNCTION_LOGGER = logger
else:
USER_FUNCTION_LOGGER = logging.getLogger("user-function")
USER_FUNCTION_LOGGER.setLevel(loglevel)
USER_FUNCTION_LOGGER.addFilter(CustomFilter())
log_file_name = os.path.join(RuntimeLogger().get_runtime_log_location(), RuntimeLogger().get_runtime_id() +
"-user-function.log")
handler = RotatingFileHandler(file_name=log_file_name, mode="a", max_bytes=LOG_DEFAULT_MAX_BYTES,
backup_count=LOG_DEFAULT_BACKUP_COUNT, log_name="user-function")
formatter = logging.Formatter('{"Level":"%(levelname)s",'
'"log":"%(message)s",'
'"projectId":"%(tenant_id)s",'
'"podName":"%(pod_name)s",'
'"package":"%(package)s",'
'"function":"%(function_name)s",'
'"version":"%(version)s",'
'"stream":"%(stream)s",'
'"instanceId":"%(instance_id)s",'
'"requestId":"%(request_id)s",'
'"time":"%(asctime)s.%(msecs)03d",'
'"stage":"%(stage)s",'
'"status":"%(status)s",'
'"finishLog":"%(finish_log)s"}', datefmt='%Y-%m-%dT%H:%M:%S')
handler.setFormatter(formatter)
USER_FUNCTION_LOGGER.addHandler(handler)
def get_user_function_logger(log_level: int = logging.DEBUG):
"""
get user function log
return user function log, singleton mode
"""
global USER_FUNCTION_LOGGER
if USER_FUNCTION_LOGGER is None:
init_user_function_log(log_level)
return USER_FUNCTION_LOGGER