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
121 lines
3.8 KiB
#
|
|
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
|
|
# 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 "-"
|