Преглед на файлове

Make logging configurable through config file

master
JustAnotherArchivist преди 4 години
родител
ревизия
7fcf7d5f0e
променени са 1 файла, в които са добавени 32 реда и са изтрити 7 реда
  1. +32
    -7
      http2irc.py

+ 32
- 7
http2irc.py Целия файл

@@ -8,13 +8,11 @@ import logging
import os.path
import signal
import ssl
import string
import sys
import toml


logging.basicConfig(level = logging.DEBUG, format = '{asctime} {levelname} {message}', style = '{')


SSL_CONTEXTS = {'yes': True, 'no': False, 'insecure': ssl.SSLContext()}


@@ -56,10 +54,24 @@ class Config(dict):
logging.info(repr(obj))

# Sanity checks
if any(x not in ('irc', 'web', 'maps') for x in obj.keys()):
if any(x not in ('logging', 'irc', 'web', 'maps') for x in obj.keys()):
raise InvalidConfig('Unknown sections found in base object')
if any(not isinstance(x, collections.abc.Mapping) for x in obj.values()):
raise InvalidConfig('Invalid section type(s), expected objects/dicts')
if 'logging' in obj:
if any(x not in ('level', 'format') for x in obj['logging']):
raise InvalidConfig('Unknown key found in log section')
if 'level' in obj['logging'] and obj['logging']['level'] not in ('DEBUG', 'INFO', 'WARNING', 'ERROR'):
raise InvalidConfig('Invalid log level')
if 'format' in obj['logging']:
if not isinstance(obj['logging']['format'], str):
raise InvalidConfig('Invalid log format')
try:
#TODO: Replace with logging.Formatter's validate option (3.8+); this test does not cover everything that could be wrong (e.g. invalid format spec or conversion)
# This counts the number of replacement fields. Formatter.parse yields tuples whose second value is the field name; if it's None, there is no field (e.g. literal text).
assert sum(1 for x in string.Formatter().parse(obj['logging']['format']) if x[1] is not None) > 0
except (ValueError, AssertionError) as e:
raise InvalidConfig('Invalid log format: parsing failed') from e
if 'irc' in obj:
if any(x not in ('host', 'port', 'ssl', 'nick', 'real', 'certfile', 'certkeyfile') for x in obj['irc']):
raise InvalidConfig('Unknown key found in irc section')
@@ -107,7 +119,7 @@ class Config(dict):
#TODO: Check values

# Default values
finalObj = {'irc': {'host': 'irc.hackint.org', 'port': 6697, 'ssl': 'yes', 'nick': 'h2ibot', 'real': 'I am an http2irc bot.', 'certfile': None, 'certkeyfile': None}, 'web': {'host': '127.0.0.1', 'port': 8080}, 'maps': {}}
finalObj = {'logging': {'level': 'INFO', 'format': '{asctime} {levelname} {message}'}, 'irc': {'host': 'irc.hackint.org', 'port': 6697, 'ssl': 'yes', 'nick': 'h2ibot', 'real': 'I am an http2irc bot.', 'certfile': None, 'certkeyfile': None}, 'web': {'host': '127.0.0.1', 'port': 8080}, 'maps': {}}

# Fill in default values for the maps
for key, map_ in obj['maps'].items():
@@ -119,13 +131,13 @@ class Config(dict):
map_['auth'] = False

# Merge in what was read from the config file and set keys on self
for key in ('irc', 'web', 'maps'):
for key in ('logging', 'irc', 'web', 'maps'):
if key in obj:
finalObj[key].update(obj[key])
self[key] = finalObj[key]

def __repr__(self):
return f'<Config(irc={self["irc"]!r}, web={self["web"]!r}, maps={self["maps"]!r})>'
return f'<Config(logging={self["logging"]!r}, irc={self["irc"]!r}, web={self["web"]!r}, maps={self["maps"]!r})>'

def reread(self):
return Config(self._filename)
@@ -412,12 +424,24 @@ class WebServer:
raise aiohttp.web.HTTPOk()


def configure_logging(config):
#TODO: Replace with logging.basicConfig(..., force = True) (Py 3.8+)
root = logging.getLogger()
root.setLevel(getattr(logging, config['logging']['level']))
root.handlers = [] #FIXME: Undocumented attribute of logging.Logger
formatter = logging.Formatter(config['logging']['format'], style = '{')
stderrHandler = logging.StreamHandler()
stderrHandler.setFormatter(formatter)
root.addHandler(stderrHandler)


async def main():
if len(sys.argv) != 2:
print('Usage: http2irc.py CONFIGFILE', file = sys.stderr)
sys.exit(1)
configFile = sys.argv[1]
config = Config(configFile)
configure_logging(config)

loop = asyncio.get_running_loop()

@@ -442,6 +466,7 @@ async def main():
logging.error(f'Config reload failed: {e!s}')
return
config = newConfig
configure_logging(config)
irc.update_config(config)
webserver.update_config(config)
loop.add_signal_handler(signal.SIGUSR1, sigusr1_callback)


Зареждане…
Отказ
Запис