'Unable to Mock the logging variables
I have created a custom logging class which is used to log in the elastic search. But to run the unit-test, I want to mock those variable but I am unable to figure out a way to do so.
Below is the sample to recreate the error:
main.py:
from app.log_utils import printlog, timing
from time import sleep
def func():
timing.start("abc")
print("Running...")
def func2():
name="Root logger"
greeting="Nice to meet you"
printlog.info(f"Hi, {name}. {greeting}")
name="world"
greeting="Nice to meet you"
printlog.warn(f"Hi, {name}! {greeting}")
printlog.info("Logging info")
func2()
timing.end("abc")
print("Sleeping...")
sleep(0.5)
print("Done.")
if __name__=="__main__":
func()
log_utils.py:
import ...
open("./logs/file.log", "a").close()
logfile_format = " - ".join(
[
"%(asctime)s",
"%(process)-6d",
"%(levelname)-8s",
"%(filename)s",
"%(funcName)s",
"%(message)s",
]
)
stdout_format = " - ".join(["%(asctime)s", "%(levelname)s", "%(message)s"])
class Timing: ...
class CustomLog:
def __init__(self, host, port, index, level) -> None:
try:
self.log_level = int(logging.getLevelName(level)) if level.upper()!="ALL" else 0
except ValueError:
raise f"Invalid level input {level}"
self.es = elasticsearch.Elasticsearch([{"scheme": "http", 'host': host, 'port': port}])
self.index = index
self.logger = self.get_logger(log_filename="./logs/file.log",
maxsize_MB=100,
stdout_level=level,
logfile_level=level)
self.logger.propagate = False
self.es_create_index_if_not_exists()
def es_create_index_if_not_exists(self):
"""Create the given ElasticSearch index and ignore error if it already exists"""
try:
self.es.indices.create(index = f"{self.index}")
self.es.indices.refresh(index=f"{self.index}")
except elasticsearch.exceptions.RequestError as ex:
if ex.error == 'resource_already_exists_exception':
pass # Index already exists. Ignore.
else: # Other exception - raise it
pass
def _check_level(self, level):
if logging.getLevelName(level) >= self.log_level:
return True
return False
def log(self, msg, log_lvl, caller=None):
caller = getframeinfo(stack()[1][0]) if caller is None else caller
_index = f"{self.index}_{datetime.now().date().strftime('%y.%m.%d')}"
doc = {
"@timestamp": datetime.now(),
"log.level": log_lvl,
"message": msg,
"host": socket.gethostname(),
"file": {
"line": caller.lineno,
"name": caller.filename,
"function": caller.function
}
}
self.logger.log(logging.getLevelName(log_lvl), msg)
try:
self.es.index(index=_index, document=doc)
except Exception as ex:
self.logger.error(f"Unable to write to the elastic {repr(ex)}")
# self.es.indices.refresh(index=self.index)
def info(self, msg):
lvl = "INFO"
caller = getframeinfo(stack()[1][0])
if self._check_level(lvl):
self.log(msg, lvl, caller)
def error(self, msg):
lvl = "ERROR"
caller = getframeinfo(stack()[1][0])
if self._check_level(lvl):
self.log(msg, lvl, caller)
def debug(self, msg):
lvl = "DEBUG"
caller = getframeinfo(stack()[1][0])
if self._check_level(lvl):
self.log(msg, lvl, caller)
def fatal(self, msg):
lvl = "FATAL"
caller = getframeinfo(stack()[1][0])
if self._check_level(lvl):
self.log(msg, lvl, caller)
def warning(self, msg):
lvl = "WARNING"
caller = getframeinfo(stack()[1][0])
if self._check_level(lvl):
self.log(msg, lvl, caller)
def warn(self,msg):
lvl = "WARN"
caller = getframeinfo(stack()[1][0])
if self._check_level(lvl):
self.log(msg, lvl, caller)
def get_logger(self,log_filename, maxsize_MB=0, backupCount=3, stdout_level='INFO', logfile_level='DEBUG'):
logger = logging.getLogger(__name__)
logger.setLevel(logging.getLevelName(logfile_level.upper()))
screen_formatter = logging.Formatter(stdout_format,
datefmt="%Y-%m-%d %H:%M:%S")
file_formatter = logging.Formatter(logfile_format,
datefmt="%Y-%m-%d %H:%M:%S")
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.getLevelName(stdout_level.upper()))
ch.setFormatter(screen_formatter)
logger.addHandler(ch)
handler = RotatingFileHandler(log_filename, maxBytes=maxsize_MB * 1e6, backupCount=backupCount)
handler.setLevel(logging.getLevelName(logfile_level.upper()))
handler.setFormatter(file_formatter)
logger.addHandler(handler)
return logger
printlog = CustomLog( host = os.environ.get("IP"), port = os.environ.get("port"), index = os.environ.get("_index"), level = "INFO")
timing = Timing(logger=printlog)
I have tried to write the unit-test for above implementation but getting error while importing the 'func' method due to this line in the log_utils.py self.es = elasticsearch.Elasticsearch([{"scheme": "http", 'host': host, 'port': port}]).
test_func.py:
import mock
import unittest
from app.main import func
@mock.patch('app.seqlogtest.printlog')
@mock.patch('app.seqlogtest.timing')
class RmTestCase(unittest.TestCase):
def test_func(self): # , mock_log, mock_timing
self.assertEqual(func(),None)
Any assistance is greatly appreciated.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
