gns3-server/gns3server/logger.py

170 lines
5.5 KiB
Python
Raw Normal View History

2015-01-20 13:59:19 +00:00
#!/usr/bin/env python
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Provide a pretty logging on console"""
import logging
import sys
import os
import shutil
import gzip
from logging.handlers import RotatingFileHandler
2015-01-20 13:59:19 +00:00
class ColouredFormatter(logging.Formatter):
2021-04-13 09:16:50 +00:00
RESET = "\x1B[0m"
RED = "\x1B[31m"
YELLOW = "\x1B[33m"
GREEN = "\x1B[32m"
PINK = "\x1b[35m"
2015-01-20 13:59:19 +00:00
def format(self, record, colour=False):
2015-01-20 15:37:18 +00:00
2015-01-20 13:59:19 +00:00
message = super().format(record)
if not colour or sys.platform.startswith("win"):
2015-01-20 14:18:57 +00:00
return message.replace("#RESET#", "")
2015-01-20 13:59:19 +00:00
level_no = record.levelno
if level_no >= logging.CRITICAL:
colour = self.RED
elif level_no >= logging.ERROR:
colour = self.RED
elif level_no >= logging.WARNING:
colour = self.YELLOW
elif level_no >= logging.INFO:
colour = self.GREEN
elif level_no >= logging.DEBUG:
colour = self.PINK
else:
colour = self.RESET
2015-01-20 14:18:57 +00:00
message = message.replace("#RESET#", self.RESET)
2020-10-22 09:26:53 +00:00
# do not show uvicorn filename and line number in logs
if record.name.startswith("uvicorn"):
message = message.replace(f"{record.name}:{record.lineno}", "uvicorn")
2021-04-13 09:16:50 +00:00
message = f"{colour}{message}{self.RESET}"
2015-01-20 13:59:19 +00:00
return message
class ColouredStreamHandler(logging.StreamHandler):
def format(self, record, colour=False):
2015-01-20 15:37:18 +00:00
2015-01-20 13:59:19 +00:00
if not isinstance(self.formatter, ColouredFormatter):
self.formatter = ColouredFormatter()
return self.formatter.format(record, colour)
def emit(self, record):
2015-01-20 15:37:18 +00:00
2015-01-20 13:59:19 +00:00
stream = self.stream
try:
msg = self.format(record, stream.isatty())
stream.write(msg)
stream.write(self.terminator)
self.flush()
2016-05-18 09:23:45 +00:00
# On OSX when frozen flush raise a BrokenPipeError
except BrokenPipeError:
pass
2015-01-20 13:59:19 +00:00
except Exception:
self.handleError(record)
class WinStreamHandler(logging.StreamHandler):
def emit(self, record):
if sys.stdin.encoding != "utf-8":
record = record
stream = self.stream
try:
msg = self.formatter.format(record, stream.isatty())
stream.write(msg.encode(stream.encoding, errors="replace").decode(stream.encoding))
stream.write(self.terminator)
self.flush()
except Exception:
self.handleError(record)
2017-05-12 08:48:43 +00:00
class LogFilter:
"""
This filter some noise from the logs
"""
2021-04-13 09:16:50 +00:00
2017-05-12 08:48:43 +00:00
def filter(record):
if isinstance(record.msg, str) and "/settings" in record.msg and "200" in record.msg:
2017-05-12 08:48:43 +00:00
return 0
return 1
class CompressedRotatingFileHandler(RotatingFileHandler):
"""
Custom rotating file handler with compression support.
"""
def doRollover(self):
if self.stream:
self.stream.close()
if self.backupCount > 0:
for i in range(self.backupCount - 1, 0, -1):
sfn = "%s.%d.gz" % (self.baseFilename, i)
dfn = "%s.%d.gz" % (self.baseFilename, i + 1)
if os.path.exists(sfn):
if os.path.exists(dfn):
os.remove(dfn)
os.rename(sfn, dfn)
dfn = self.baseFilename + ".1.gz"
if os.path.exists(dfn):
os.remove(dfn)
2021-04-13 09:16:50 +00:00
with open(self.baseFilename, "rb") as f_in, gzip.open(dfn, "wb") as f_out:
shutil.copyfileobj(f_in, f_out)
2021-04-13 09:16:50 +00:00
self.mode = "w"
self.stream = self._open()
def init_logger(level, logfile=None, max_bytes=10000000, backup_count=10, compression=True, quiet=False):
2015-04-22 15:28:58 +00:00
if logfile and len(logfile) > 0:
if compression:
stream_handler = CompressedRotatingFileHandler(logfile, maxBytes=max_bytes, backupCount=backup_count)
else:
stream_handler = RotatingFileHandler(logfile, maxBytes=max_bytes, backupCount=backup_count)
2021-04-13 09:16:50 +00:00
stream_handler.formatter = ColouredFormatter(
"{asctime} {levelname} {filename}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{"
)
2015-04-22 15:28:58 +00:00
elif sys.platform.startswith("win"):
stream_handler = WinStreamHandler(sys.stdout)
2021-04-13 09:16:50 +00:00
stream_handler.formatter = ColouredFormatter(
"{asctime} {levelname} {filename}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{"
)
else:
stream_handler = ColouredStreamHandler(sys.stdout)
2021-04-13 09:16:50 +00:00
stream_handler.formatter = ColouredFormatter(
"{asctime} {levelname} {name}:{lineno}#RESET# {message}", "%Y-%m-%d %H:%M:%S", "{"
)
2015-01-20 13:59:19 +00:00
if quiet:
stream_handler.addFilter(logging.Filter(name="user_facing"))
2020-10-22 09:26:53 +00:00
logging.getLogger("user_facing").propagate = False
2017-05-12 08:48:43 +00:00
if level > logging.DEBUG:
stream_handler.addFilter(LogFilter)
2015-01-20 13:59:19 +00:00
logging.basicConfig(level=level, handlers=[stream_handler])
2020-10-22 09:26:53 +00:00
return stream_handler