2016-05-26 16:16:13 +00:00
|
|
|
# Copyright 2016 Mycroft AI, Inc.
|
|
|
|
#
|
|
|
|
# This file is part of Mycroft Core.
|
|
|
|
#
|
|
|
|
# Mycroft Core is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# Mycroft Core 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 for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
2017-09-18 18:55:58 +00:00
|
|
|
import inspect
|
2017-04-06 18:23:45 +00:00
|
|
|
import logging
|
2017-09-18 18:55:58 +00:00
|
|
|
import sys
|
|
|
|
from traceback import format_exception
|
2016-05-26 16:16:13 +00:00
|
|
|
|
2017-04-06 18:23:45 +00:00
|
|
|
from os.path import isfile
|
2017-09-18 18:55:58 +00:00
|
|
|
|
2017-06-22 12:45:38 +00:00
|
|
|
from mycroft.util.json_helper import load_commented_json
|
2016-05-26 16:16:13 +00:00
|
|
|
|
2016-05-20 22:15:53 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
def getLogger(name="MYCROFT"):
|
|
|
|
"""Depreciated. Use LOG instead"""
|
|
|
|
return logging.getLogger(name)
|
2016-05-20 14:16:01 +00:00
|
|
|
|
2017-04-06 18:23:45 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
class LOG:
|
|
|
|
"""
|
|
|
|
Custom logger class that acts like logging.Logger
|
|
|
|
The logger name is automatically generated by the module of the caller
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
LOG.debug('My message: %s', debug_str)
|
|
|
|
LOG('custom_name').debug('Another message')
|
|
|
|
"""
|
2017-04-06 18:23:45 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
_custom_name = None
|
2016-05-20 14:16:01 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
@classmethod
|
|
|
|
def init(cls):
|
|
|
|
sys_config = '/etc/mycroft/mycroft.conf'
|
|
|
|
cls.level = logging.getLevelName(load_commented_json(sys_config)['log_level']
|
|
|
|
if isfile(sys_config) else 'DEBUG')
|
2016-05-20 14:16:01 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
fmt = '%(asctime)s.%(msecs)03d - %(name)s - %(levelname)s - %(message)s'
|
|
|
|
datefmt = '%H:%M:%S'
|
|
|
|
formatter = logging.Formatter(fmt, datefmt)
|
|
|
|
cls.ch = logging.StreamHandler(sys.stdout)
|
|
|
|
cls.ch.setFormatter(formatter)
|
|
|
|
cls.create_logger('') # Enables logging in external modules
|
2016-05-20 14:16:01 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
@classmethod
|
|
|
|
def create_logger(cls, name):
|
|
|
|
l = logging.getLogger(name)
|
|
|
|
l.propagate = False
|
|
|
|
if not hasattr(cls, 'level'):
|
|
|
|
cls.init()
|
2016-05-20 14:16:01 +00:00
|
|
|
|
2017-09-18 18:55:58 +00:00
|
|
|
l.addHandler(cls.ch)
|
|
|
|
l.setLevel(cls.level)
|
|
|
|
return l
|
|
|
|
|
|
|
|
def __init__(self, name):
|
|
|
|
LOG._custom_name = name
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def _log(cls, func, args, kwargs):
|
|
|
|
if cls._custom_name is not None:
|
|
|
|
name = cls._custom_name
|
|
|
|
cls._custom_name = None
|
|
|
|
else:
|
|
|
|
# Stack:
|
|
|
|
# [0] - _log()
|
|
|
|
# [1] - debug(), info(), warning(), or error()
|
|
|
|
# [2] - caller
|
|
|
|
stack = inspect.stack()
|
|
|
|
|
|
|
|
# Record:
|
|
|
|
# [0] - frame object
|
|
|
|
# [1] - filename
|
|
|
|
# [2] - line number
|
|
|
|
# [3] - function
|
|
|
|
# ...
|
|
|
|
record = stack[2]
|
|
|
|
name = inspect.getmodule(record[0]).__name__ + ':' + record[3] + ':' + str(record[2])
|
|
|
|
func(cls.create_logger(name), *args, **kwargs)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def debug(cls, *args, **kwargs):
|
|
|
|
cls._log(logging.Logger.debug, args, kwargs)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def info(cls, *args, **kwargs):
|
|
|
|
cls._log(logging.Logger.info, args, kwargs)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def warning(cls, *args, **kwargs):
|
|
|
|
cls._log(logging.Logger.warning, args, kwargs)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def error(cls, *args, **kwargs):
|
|
|
|
cls._log(logging.Logger.error, args, kwargs)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def exception(cls, *args, **kwargs):
|
|
|
|
cls._log(logging.Logger.exception, args, kwargs)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def print_trace(cls, location='', warn=False, *args):
|
|
|
|
trace_lines = format_exception(*sys.exc_info())
|
|
|
|
if warn:
|
|
|
|
intro = 'Warning' + ('in ' + location + ': ' if location else ': ')
|
|
|
|
trace_str = intro + trace_lines[-1].strip()
|
|
|
|
t = logging.Logger.info
|
|
|
|
else:
|
|
|
|
trace_str = '\n' + ''.join(trace_lines)
|
|
|
|
if location:
|
|
|
|
trace_str = '\n=== ' + location + ' ===' + trace_str
|
|
|
|
trace_str = '\n' + trace_str
|
|
|
|
t = logging.Logger.error
|
|
|
|
cls._log(t, trace_str, args)
|