You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.8 KiB

#
# SPDX-FileCopyrightText: 2021 Splunk, Inc. <sales@splunk.com>
# SPDX-License-Identifier: LicenseRef-Splunk-8-2021
#
#
import logging
import logging.handlers as handlers
import os
import os.path as op
import time
try:
from splunk.clilib.bundle_paths import make_splunkhome_path
except ImportError:
from splunk.appserver.mrsparkle.lib.util import make_splunkhome_path
logging.Formatter.converter = time.gmtime
__LOG_FORMAT__ = (
"%(asctime)s +0000 log_level=%(levelname)s, pid=%(process)d, "
"tid=%(threadName)s, file=%(filename)s, "
"func_name=%(funcName)s, code_line_no=%(lineno)d | %(message)s"
)
class Log(object):
def __init__(self, namespace=None, default_level=logging.INFO):
self._loggers = {}
self._default_level = default_level
if namespace is None:
namespace = self._get_appname_from_path(op.abspath(__file__))
if namespace:
namespace = namespace.lower()
self._namespace = namespace
def get_logger(self, name, level=None, maxBytes=25000000, backupCount=5):
"""
Set up a default logger.
:param name: The log file name.
:param level: The logging level.
:param maxBytes: The maximum log file size before rollover.
:param backupCount: The number of log files to retain.
"""
# Strip ".py" from the log file name if auto-generated by a script.
if level is None:
level = self._default_level
name = self._get_log_name(name)
if name in self._loggers:
return self._loggers[name]
logger = logging.getLogger(name)
logfile = make_splunkhome_path(["var", "log", "splunk", name])
handler_exists = any(
[True for h in logger.handlers if h.baseFilename == logfile]
)
if not handler_exists:
file_handler = handlers.RotatingFileHandler(
logfile, mode="a", maxBytes=maxBytes, backupCount=backupCount
)
formatter = logging.Formatter(__LOG_FORMAT__)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.setLevel(level)
logger.propagate = False
self._loggers[name] = logger
return logger
def set_level(self, level, name=None):
"""
Change the log level of the logging
:param level: the level of the logging to be setLevel
:param name: the name of the logging to set, in case it is not set,
all the loggers will be affected
"""
if name is not None:
name = self._get_log_name(name)
logger = self._loggers.get(name)
if logger is not None:
logger.setLevel(level)
else:
self._default_level = level
for logger in self._loggers.values():
logger.setLevel(level)
def _get_log_name(self, name):
if name.endswith(".py"):
name = name.replace(".py", "")
if self._namespace:
name = "{}_{}.log".format(self._namespace, name)
else:
name = "{}.log".format(name)
return name
def _get_appname_from_path(self, absolute_path):
absolute_path = op.normpath(absolute_path)
parts = absolute_path.split(os.path.sep)
parts.reverse()
for key in ("apps", "slave-apps", "master-apps"):
try: # nosemgrep: gitlab.bandit.B112
idx = parts.index(key)
except ValueError:
continue
else:
try: # nosemgrep: gitlab.bandit.B110
if parts[idx + 1] == "etc":
return parts[idx - 1]
except IndexError:
pass
continue
# return None
return "-"