diff --git a/bumper/__init__.py b/bumper/__init__.py index aea1216..667232a 100644 --- a/bumper/__init__.py +++ b/bumper/__init__.py @@ -4,13 +4,13 @@ import importlib import pkgutil import socket import sys -from logging.handlers import RotatingFileHandler from typing import Optional from bumper.confserver import ConfServer from bumper.db import * from bumper.models import * from bumper.mqttserver import MQTTServer, MQTTHelperBot +from bumper.util import get_logger, log_to_stdout from bumper.xmppserver import XMPPServer @@ -24,8 +24,6 @@ def strtobool(strbool): # os.environ['PYTHONASYNCIODEBUG'] = '1' # Uncomment to enable ASYNCIODEBUG bumper_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) -log_to_stdout = os.environ.get("LOG_TO_STDOUT") - # Set defaults from environment variables first # Folders if not log_to_stdout: @@ -73,111 +71,7 @@ discovered_plugins = { shutting_down = False -# Set format for all logs -logformat = logging.Formatter( - "[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s" -) - -bumperlog = logging.getLogger("bumper") -if not log_to_stdout: - bumper_rotate = RotatingFileHandler("logs/bumper.log", maxBytes=5000000, backupCount=5) - bumper_rotate.setFormatter(logformat) - bumperlog.addHandler(bumper_rotate) -else: - bumperlog.addHandler(logging.StreamHandler(sys.stdout)) -# Override the logging level -# bumperlog.setLevel(logging.INFO) - -confserverlog = logging.getLogger("confserver") -if not log_to_stdout: - conf_rotate = RotatingFileHandler( - "logs/confserver.log", maxBytes=5000000, backupCount=5 - ) - conf_rotate.setFormatter(logformat) - confserverlog.addHandler(conf_rotate) -else: - confserverlog.addHandler(logging.StreamHandler(sys.stdout)) -# Override the logging level -# confserverlog.setLevel(logging.INFO) - -mqttserverlog = logging.getLogger("mqttserver") -if not log_to_stdout: - mqtt_rotate = RotatingFileHandler( - "logs/mqttserver.log", maxBytes=5000000, backupCount=5 - ) - mqtt_rotate.setFormatter(logformat) - mqttserverlog.addHandler(mqtt_rotate) -else: - mqttserverlog.addHandler(logging.StreamHandler(sys.stdout)) -# Override the logging level -# mqttserverlog.setLevel(logging.INFO) - -### Additional MQTT Logs -translog = logging.getLogger("transitions") -if not log_to_stdout: - translog.addHandler(mqtt_rotate) -else: - translog.addHandler(logging.StreamHandler(sys.stdout)) -translog.setLevel(logging.CRITICAL + 1) # Ignore this logger -logging.getLogger("passlib").setLevel(logging.CRITICAL + 1) # Ignore this logger -brokerlog = logging.getLogger("hbmqtt.broker") -# brokerlog.setLevel( -# logging.CRITICAL + 1 -# ) # Ignore this logger #There are some sublogs that could be set if needed (.plugins) -if not log_to_stdout: - brokerlog.addHandler(mqtt_rotate) -else: - brokerlog.addHandler(logging.StreamHandler(sys.stdout)) -protolog = logging.getLogger("hbmqtt.mqtt.protocol") -# protolog.setLevel( -# logging.CRITICAL + 1 -# ) # Ignore this logger -if not log_to_stdout: - protolog.addHandler(mqtt_rotate) -else: - protolog.addHandler(logging.StreamHandler(sys.stdout)) -clientlog = logging.getLogger("hbmqtt.client") -# clientlog.setLevel(logging.CRITICAL + 1) # Ignore this logger -if not log_to_stdout: - clientlog.addHandler(mqtt_rotate) -else: - clientlog.addHandler(logging.StreamHandler(sys.stdout)) -helperbotlog = logging.getLogger("helperbot") -if not log_to_stdout: - helperbot_rotate = RotatingFileHandler( - "logs/helperbot.log", maxBytes=5000000, backupCount=5 - ) - helperbot_rotate.setFormatter(logformat) - helperbotlog.addHandler(helperbot_rotate) -else: - helperbotlog.addHandler(logging.StreamHandler(sys.stdout)) -# Override the logging level -# helperbotlog.setLevel(logging.INFO) - -boterrorlog = logging.getLogger("boterror") -if not log_to_stdout: - boterrorlog_rotate = RotatingFileHandler( - "logs/boterror.log", maxBytes=5000000, backupCount=5 - ) - boterrorlog_rotate.setFormatter(logformat) - boterrorlog.addHandler(boterrorlog_rotate) -else: - boterrorlog.addHandler(logging.StreamHandler(sys.stdout)) -# Override the logging level -# boterrorlog.setLevel(logging.INFO) - -xmppserverlog = logging.getLogger("xmppserver") -if not log_to_stdout: - xmpp_rotate = RotatingFileHandler( - "logs/xmppserver.log", maxBytes=5000000, backupCount=5 - ) - xmpp_rotate.setFormatter(logformat) - xmppserverlog.addHandler(xmpp_rotate) -else: - xmppserverlog.addHandler(logging.StreamHandler(sys.stdout)) -# Override the logging level -# xmppserverlog.setLevel(logging.INFO) - +bumperlog = get_logger("bumper") logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger mqtt_listen_port = 8883 @@ -206,7 +100,7 @@ async def start(): ) if not bumper_listen: - logging.log(logging.FATAL, "No listen address configured") + bumperlog.fatal("No listen address configured") return if not ( @@ -214,7 +108,7 @@ async def start(): and os.path.exists(server_cert) and os.path.exists(server_key) ): - logging.log(logging.FATAL, "Certificate(s) don't exist at paths specified") + bumperlog.fatal("Certificate(s) don't exist at paths specified") return bumperlog.info("Starting Bumper") @@ -324,10 +218,7 @@ def create_certs(): else: os.chdir(odir) - logging.log( - logging.FATAL, - "Can't determine platform. Create certs manually and try again.", - ) + bumperlog.fatal("Can't determine platform. Create certs manually and try again.") return print("Certificates created") diff --git a/bumper/confserver.py b/bumper/confserver.py index 65e0143..0c7c3af 100644 --- a/bumper/confserver.py +++ b/bumper/confserver.py @@ -9,7 +9,7 @@ import aiohttp_jinja2 import jinja2 from aiohttp import web -from bumper import plugins +from bumper import plugins, get_logger from bumper.models import * @@ -23,14 +23,14 @@ class aiohttp_filter(logging.Filter): if ( record.levelno == 10 - and logging.getLogger("confserver").getEffectiveLevel() == 10 + and get_logger("confserver").getEffectiveLevel() == 10 ): return True else: return False -confserverlog = logging.getLogger("confserver") +confserverlog = get_logger("confserver") logging.getLogger("aiohttp.access").addFilter( aiohttp_filter() ) # Add logging filter above to aiohttp.access diff --git a/bumper/db.py b/bumper/db.py index 304add3..2a3b19d 100644 --- a/bumper/db.py +++ b/bumper/db.py @@ -7,9 +7,10 @@ from datetime import datetime, timedelta from tinydb import TinyDB, Query import bumper +from bumper import get_logger from bumper.models import VacBotClient, VacBotDevice, BumperUser, EcoVacsHomeProducts, OAuth -bumperlog = logging.getLogger("bumper") +bumperlog = get_logger("bumper") def db_file(): diff --git a/bumper/mqttserver.py b/bumper/mqttserver.py index c5711bd..28eff7a 100644 --- a/bumper/mqttserver.py +++ b/bumper/mqttserver.py @@ -15,10 +15,11 @@ from hbmqtt.mqtt.constants import QOS_0 from passlib.apps import custom_app_context as pwd_context import bumper +from bumper.util import get_logger -helperbotlog = logging.getLogger("helperbot") -boterrorlog = logging.getLogger("boterror") -mqttserverlog = logging.getLogger("mqttserver") +mqttserverlog = get_logger("mqttserver") +helperbotlog = get_logger("helperbot") +boterrorlog = get_logger("boterror") class MQTTHelperBot: @@ -31,7 +32,6 @@ class MQTTHelperBot: self.command_responses = [] async def start_helper_bot(self): - try: if self.Client is None: self.Client = MQTTClient( @@ -49,24 +49,11 @@ class MQTTHelperBot: ("iot/atr/+", QOS_0), ] ) - - # except ConnectionRefusedError as e: - # helperbotlog.Error(e) - # pass - - # except asyncio.CancelledError as e: - # pass - - # except hbmqtt.client.ConnectException as e: - # helperbotlog.Error(e) - # pass - except Exception as e: helperbotlog.exception("{}".format(e)) async def wait_for_resp(self, requestid): try: - t_end = ( datetime.now() + timedelta(seconds=self.wait_resp_timeout_seconds) ).timestamp() @@ -84,29 +71,17 @@ class MQTTHelperBot: resp = {"id": requestid, "ret": "ok", "resp": resppayload} self.command_responses.remove(msg) return resp - - return { - "id": requestid, - "errno": 500, - "ret": "fail", - "debug": "wait for response timed out", - } - except asyncio.CancelledError as e: + except asyncio.CancelledError: helperbotlog.debug("wait_for_resp cancelled by asyncio") - return { - "id": requestid, - "errno": 500, - "ret": "fail", - "debug": "wait for response timed out", - } except Exception as e: helperbotlog.exception("{}".format(e)) - return { - "id": requestid, - "errno": 500, - "ret": "fail", - "debug": "wait for response timed out", - } + + return { + "id": requestid, + "errno": 500, + "ret": "fail", + "debug": "wait for response timed out", + } async def send_command(self, cmdjson, requestid): if not self.Client._handler.writer is None: diff --git a/bumper/util.py b/bumper/util.py new file mode 100644 index 0000000..a2aabcf --- /dev/null +++ b/bumper/util.py @@ -0,0 +1,40 @@ +import logging +import os +import sys +from logging.handlers import RotatingFileHandler + +from typing import MutableMapping + +logformat = logging.Formatter( + "[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s" +) + +__loggers: MutableMapping[str, logging.Logger] = {} +log_to_stdout = os.environ.get("LOG_TO_STDOUT") + + +def get_logger(name: str, rotate: RotatingFileHandler = None) -> logging.Logger: + found_logger = __loggers.get(name) + if found_logger: + return found_logger + + logger = logging.getLogger(name) + + if not log_to_stdout: + if not rotate: + rotate = RotatingFileHandler(f"logs/{name}.log", maxBytes=5000000, backupCount=5) + rotate.setFormatter(logformat) + logger.addHandler(rotate) + else: + logger.addHandler(logging.StreamHandler(sys.stdout)) + + __loggers[name] = logger + + if name == "mqttserver": + get_logger("transitions", rotate).setLevel(logging.CRITICAL + 1) # Ignore this logger + get_logger("passlib", rotate).setLevel(logging.CRITICAL + 1) # Ignore this logger + get_logger("hbmqtt.broker", rotate) + get_logger("hbmqtt.mqtt.protocol", rotate) + get_logger("hbmqtt.client", rotate) + + return logger diff --git a/bumper/xmppserver.py b/bumper/xmppserver.py index 697c201..eb7aed0 100644 --- a/bumper/xmppserver.py +++ b/bumper/xmppserver.py @@ -9,8 +9,10 @@ import ssl import bumper import asyncio -xmppserverlog = logging.getLogger("xmppserver") -boterrorlog = logging.getLogger("boterror") +from bumper import get_logger + +xmppserverlog = get_logger("xmppserver") +boterrorlog = get_logger("boterror") class XMPPServer: