input-remapper/keymapper/logger.py

224 lines
6.3 KiB
Python
Raw Normal View History

2020-10-26 22:45:22 +00:00
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# key-mapper - GUI for device specific keyboard mappings
2021-02-22 18:48:20 +00:00
# Copyright (C) 2021 sezanzeb <proxima@sezanzeb.de>
2020-10-26 22:45:22 +00:00
#
2020-10-31 13:02:59 +00:00
# This file is part of key-mapper.
2020-10-26 22:45:22 +00:00
#
2020-10-31 13:02:59 +00:00
# key-mapper is free software: you can redistribute it and/or modify
2020-10-26 22:45:22 +00:00
# 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.
#
2020-10-31 13:02:59 +00:00
# key-mapper is distributed in the hope that it will be useful,
2020-10-26 22:45:22 +00:00
# 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
2020-10-31 13:02:59 +00:00
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
2020-10-26 22:45:22 +00:00
2020-10-31 13:02:59 +00:00
"""Logging setup for key-mapper."""
2020-10-26 22:45:22 +00:00
import os
2021-03-21 18:15:20 +00:00
import shutil
2020-12-03 19:37:36 +00:00
import time
2020-10-26 22:45:22 +00:00
import logging
import pkg_resources
2021-03-21 18:15:20 +00:00
from keymapper.user import HOME
2021-04-15 19:16:07 +00:00
try:
from keymapper.commit_hash import COMMIT_HASH
except ImportError:
2021-09-26 10:44:56 +00:00
COMMIT_HASH = ""
2021-04-15 19:16:07 +00:00
2020-10-26 22:45:22 +00:00
2020-11-26 23:34:45 +00:00
SPAM = 5
2021-01-05 18:33:47 +00:00
start = time.time()
previous_key_spam = None
2020-11-26 23:34:45 +00:00
2020-11-29 15:22:53 +00:00
def spam(self, message, *args, **kwargs):
2020-11-26 23:34:45 +00:00
"""Log a more-verbose message than debug."""
# pylint: disable=protected-access
2020-11-18 21:06:54 +00:00
if self.isEnabledFor(SPAM):
2020-11-18 19:03:37 +00:00
# https://stackoverflow.com/a/13638084
2020-11-29 15:22:53 +00:00
self._log(SPAM, message, args, **kwargs)
2020-11-18 19:03:37 +00:00
2021-01-05 18:33:47 +00:00
def key_spam(self, key, msg, *args):
2021-01-07 16:15:12 +00:00
"""Log a spam message custom tailored to keycode_mapper.
Parameters
----------
key : tuple
anything that can be string formatted, but usually a tuple of
(type, code, value) tuples
"""
# pylint: disable=protected-access
2021-01-05 18:33:47 +00:00
if not self.isEnabledFor(SPAM):
return
global previous_key_spam
2021-01-05 18:33:47 +00:00
msg = msg % args
str_key = str(key)
2021-09-26 10:44:56 +00:00
str_key = str_key.replace(",)", ")")
spacing = " " + "-" * max(0, 30 - len(str_key))
2021-01-05 18:33:47 +00:00
if len(spacing) == 1:
2021-09-26 10:44:56 +00:00
spacing = ""
msg = f"{str_key}{spacing} {msg}"
if msg == previous_key_spam:
# avoid some super spam from EV_ABS events
return
previous_key_spam = msg
2021-01-05 18:33:47 +00:00
self._log(SPAM, msg, args=None)
2020-11-18 21:06:54 +00:00
logging.addLevelName(SPAM, "SPAM")
logging.Logger.spam = spam
2021-01-05 18:33:47 +00:00
logging.Logger.key_spam = key_spam
2020-11-18 19:03:37 +00:00
2021-03-21 18:15:20 +00:00
LOG_PATH = (
2021-09-26 10:44:56 +00:00
"/var/log/key-mapper"
if os.access("/var/log", os.W_OK)
else f"{HOME}/.log/key-mapper"
2021-03-21 18:15:20 +00:00
)
2021-08-22 09:44:16 +00:00
logger = logging.getLogger()
def is_debug():
"""True, if the logger is currently in DEBUG or SPAM mode."""
return logger.level <= logging.DEBUG
2020-11-18 19:03:37 +00:00
2020-10-26 22:45:22 +00:00
class Formatter(logging.Formatter):
"""Overwritten Formatter to print nicer logs."""
2021-09-26 10:44:56 +00:00
2020-10-26 22:45:22 +00:00
def format(self, record):
2020-11-22 20:41:29 +00:00
"""Overwritten format function."""
2020-11-26 23:34:45 +00:00
# pylint: disable=protected-access
2020-11-29 15:22:53 +00:00
debug = is_debug()
2020-10-26 22:45:22 +00:00
if record.levelno == logging.INFO and not debug:
# if not launched with --debug, then don't print "INFO:"
2021-09-26 10:44:56 +00:00
self._style._fmt = "%(message)s"
2020-10-26 22:45:22 +00:00
else:
# see https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit
# for those numbers
color = {
logging.WARNING: 33,
logging.ERROR: 31,
logging.FATAL: 31,
logging.DEBUG: 36,
2020-11-18 21:06:54 +00:00
SPAM: 34,
2020-10-26 22:45:22 +00:00
logging.INFO: 32,
}.get(record.levelno, 0)
2020-10-26 22:45:22 +00:00
if debug:
2021-09-26 10:44:56 +00:00
delta = f"{str(time.time() - start)[:7]}"
2020-10-26 22:45:22 +00:00
self._style._fmt = ( # noqa
2021-09-26 10:44:56 +00:00
f"\033[{color}m" # color
f"{os.getpid()} "
f"{delta} "
f"%(levelname)s "
f"%(filename)s:%(lineno)d: "
"%(message)s"
"\033[0m" # end style
2020-10-26 22:45:22 +00:00
)
else:
self._style._fmt = ( # noqa
2021-09-26 10:44:56 +00:00
f"\033[{color}m%(levelname)s\033[0m: %(message)s"
2020-10-26 22:45:22 +00:00
)
return super().format(record)
handler = logging.StreamHandler()
handler.setFormatter(Formatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)
2021-09-26 10:44:56 +00:00
logging.getLogger("asyncio").setLevel(logging.WARNING)
2020-10-26 22:45:22 +00:00
2021-03-21 13:17:34 +00:00
try:
2021-09-26 10:44:56 +00:00
VERSION = pkg_resources.require("key-mapper")[0].version
EVDEV_VERSION = pkg_resources.require("evdev")[0].version
2021-03-21 13:17:34 +00:00
except pkg_resources.DistributionNotFound as error:
2021-09-26 10:44:56 +00:00
VERSION = ""
2021-03-28 11:19:44 +00:00
EVDEV_VERSION = None
2021-09-26 10:44:56 +00:00
logger.info("Could not figure out the version")
2021-03-21 13:17:34 +00:00
logger.debug(error)
2020-10-26 22:45:22 +00:00
2021-09-26 10:44:56 +00:00
def log_info(name="key-mapper"):
2021-03-28 11:19:44 +00:00
"""Log version and name to the console."""
2021-03-21 13:17:34 +00:00
logger.info(
2021-09-26 10:44:56 +00:00
"%s %s %s https://github.com/sezanzeb/key-mapper",
name,
VERSION,
COMMIT_HASH,
2021-03-21 13:17:34 +00:00
)
2020-12-26 15:46:01 +00:00
2021-03-28 11:19:44 +00:00
if EVDEV_VERSION:
2021-09-26 10:44:56 +00:00
logger.info("python-evdev %s", EVDEV_VERSION)
2020-10-26 22:45:22 +00:00
if is_debug():
logger.warning(
2021-09-26 10:44:56 +00:00
"Debug level will log all your keystrokes! Do not post this "
"output in the internet if you typed in sensitive or private "
"information with your device!"
)
2020-10-26 22:45:22 +00:00
def update_verbosity(debug):
2020-12-05 10:33:35 +00:00
"""Set the logging verbosity according to the settings object.
Also enable rich tracebacks in debug mode.
"""
2021-02-14 11:34:56 +00:00
# pylint really doesn't like what I'm doing with rich.traceback here
# pylint: disable=broad-except,import-error,import-outside-toplevel
2020-10-26 22:45:22 +00:00
if debug:
2020-11-18 21:06:54 +00:00
logger.setLevel(SPAM)
2020-12-05 10:33:35 +00:00
try:
from rich.traceback import install
2021-09-26 10:44:56 +00:00
2020-12-05 10:33:35 +00:00
install(show_locals=True)
2021-09-26 10:44:56 +00:00
logger.debug("Using rich.traceback")
2020-12-05 10:33:35 +00:00
except Exception as error:
# since this is optional, just skip all exceptions
if not isinstance(error, ImportError):
2021-09-26 10:44:56 +00:00
logger.debug("Cannot use rich.traceback: %s", error)
2020-10-26 22:45:22 +00:00
else:
logger.setLevel(logging.INFO)
2021-03-21 18:15:20 +00:00
def add_filehandler(log_path=LOG_PATH):
2020-10-26 22:45:22 +00:00
"""Clear the existing logfile and start logging to it."""
logger.info('This output is also stored in "%s"', LOG_PATH)
2021-03-21 18:15:20 +00:00
log_path = os.path.expanduser(log_path)
os.makedirs(os.path.dirname(log_path), exist_ok=True)
2020-10-26 22:45:22 +00:00
2021-03-21 18:15:20 +00:00
if os.path.exists(log_path):
2020-10-26 22:45:22 +00:00
# keep the log path small, start from scratch each time
2021-03-21 18:15:20 +00:00
if os.path.isdir(log_path):
# used to be a folder < 0.8.0
shutil.rmtree(log_path)
else:
os.remove(log_path)
2020-10-26 22:45:22 +00:00
2021-03-21 18:15:20 +00:00
file_handler = logging.FileHandler(log_path)
2020-10-26 22:45:22 +00:00
file_handler.setFormatter(Formatter())
2020-11-25 20:55:04 +00:00
2021-03-21 18:15:20 +00:00
logger.info('Logging to "%s"', log_path)
2020-11-25 20:55:04 +00:00
2020-10-26 22:45:22 +00:00
logger.addHandler(file_handler)