File: //usr/lib/mysqlsh/python-packages/mysql_gadgets/common/logger.py
#
# Copyright (c) 2016, 2024, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is designed to work with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have either included with
# the program or referenced in the documentation.
#
# 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, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
import logging
import sys
import mysqlsh
from mysql_gadgets.exceptions import GadgetLogError
shell = mysqlsh.globals.shell
PY2 = int(sys.version[0]) == 2
# Custom logging level.
STEP_LOG_LEVEL_NAME = 'STEP'
STEP_LOG_LEVEL_VALUE = 25
def setup_logging(verbosity=0):
"""Setup logging for mysqlprovision.
This method setup the logging configuration (i.e., verbosity) and logging
to be performed to the terminal and file through the shell log.
:param verbosity: Verbosity level used to setup the logging level.
If > 0 then DEBUG otherwise INFO. By default 0.
:type verbosity: Integer
"""
# Set Logger class to use.
logging.setLoggerClass(CustomLevelLogger)
# Determine the logging level to use based on verbosity.
# Note: Set at the root logger level to be used by default.
logging_level = logging.DEBUG if verbosity > 1 else logging.INFO
logging.getLogger().setLevel(logging_level)
class CustomLevelLogger(logging.getLoggerClass()):
""" Custom Logger
Logs messages directly through shell.
"""
def __init__(self, name, level=logging.NOTSET):
""" Constructor.
:param name: Name of the logger.
:type name: string
:param level: Initial logging level for the logger. By default, NOTSET.
:type level: string
"""
# Use old-class initialization for compatibility with Python 2.6
# and add logging.getLoggerClass() check to avoid recursion issues.
# super(CustomLevelLogger, self).__init__(name, level)
if logging.getLoggerClass() != CustomLevelLogger:
logging.getLoggerClass().__init__(self, name, level)
else:
logging.Logger.__init__(self, name, level)
logging.addLevelName(STEP_LOG_LEVEL_VALUE, STEP_LOG_LEVEL_NAME)
def step(self, msg, *args, **kwargs):
"""Log message of STEP severity."""
self.log(STEP_LOG_LEVEL_VALUE, msg, *args, **kwargs)
def debug(self, msg, *args, **kwargs):
"""Log message of DEBUG severity (function overwrite)."""
self.log(logging.DEBUG, msg, *args, **kwargs)
def info(self, msg, *args, **kwargs):
"""Log message of INFO severity (function overwrite)."""
self.log(logging.INFO, msg, *args, **kwargs)
def warning(self, msg, *args, **kwargs):
"""Log message of WARNING severity (function overwrite)."""
self.log(logging.WARNING, msg, *args, **kwargs)
def error(self, msg, *args, **kwargs):
"""Log message of ERROR severity (function overwrite)."""
self.log(logging.ERROR, msg, *args, **kwargs)
def critical(self, msg, *args, **kwargs):
"""Log message of CRITICAL severity (function overwrite)."""
self.log(logging.CRITICAL, msg, *args, **kwargs)
def log(self, level, msg, *args, **kwargs):
""" Log message of any severity (function overwrite). """
if kwargs:
raise GadgetLogError("Invalid use of logging parameters. kwargs "
"not supported for log(): "
"{0}".format(kwargs))
levellog = levelname = logging.getLevelName(level)
if levelname == "CRITICAL":
levellog = levelname = "ERROR"
if levelname == STEP_LOG_LEVEL_NAME:
levellog = "INFO"
formatted_msg = msg % args
if self.isEnabledFor(level):
if level >= logging.ERROR:
output = sys.stderr
else:
output = sys.stdout
output.write(
u"%s\n" % {
"type": levelname,
"msg":
formatted_msg.encode('utf-8') if PY2 else formatted_msg
})
shell.log(levellog, "mysqlprovision: " + formatted_msg)