# # Copyright 2021 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Copyright (C) 2005-2019 Splunk Inc. All Rights Reserved. log utility for TA """ import logging import logging.handlers as handlers import os.path as op import time import warnings import splunktalib.common.util as cutil from splunktalib.common.pattern import singleton from splunktalib.splunk_platform import make_splunkhome_path logging.Formatter.converter = time.gmtime def log_enter_exit(logger): """ Log decorator to log function enter and exit """ warnings.warn( "This function is deprecated. " "Please see https://github.com/splunk/addonfactory-ta-library-python/issues/38", DeprecationWarning, stacklevel=2, ) def log_decorator(func): def wrapper(*args, **kwargs): logger.debug("{} entered.".format(func.__name__)) result = func(*args, **kwargs) logger.debug("{} exited.".format(func.__name__)) return result return wrapper return log_decorator @singleton class Logs: def __init__(self, namespace=None, default_level=logging.INFO): warnings.warn( "This class is deprecated. " "Please see https://github.com/splunk/addonfactory-ta-library-python/issues/38", DeprecationWarning, stacklevel=2, ) self._loggers = {} self._default_level = default_level if namespace is None: namespace = cutil.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] logfile = make_splunkhome_path(["var", "log", "splunk", name]) logger = logging.getLogger(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( "%(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" ) 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 # Global logger logger = Logs().get_logger("util") def reset_logger(name): """ Reset global logger. """ warnings.warn( "This function is deprecated. " "Please see https://github.com/splunk/addonfactory-ta-library-python/issues/38", DeprecationWarning, stacklevel=2, ) global logger logger = Logs().get_logger(name)