hat.syslog.server.main
Syslog Server main module
1"""Syslog Server main module""" 2 3from pathlib import Path 4import argparse 5import asyncio 6import contextlib 7import logging.config 8import sys 9import time 10 11import appdirs 12 13from hat import aio 14 15from hat.syslog.server.backend import create_backend 16from hat.syslog.server.syslog import create_syslog_server 17from hat.syslog.server.ui import create_web_server 18 19 20mlog: logging.Logger = logging.getLogger('hat.syslog.server.main') 21"""Module logger""" 22 23user_data_dir: Path = Path(appdirs.user_data_dir('hat')) 24"""User data directory path""" 25 26default_log_level: str = 'INFO' 27"""Default console log level""" 28 29default_ui_addr: str = 'http://0.0.0.0:23020' 30"""Default UI listening address""" 31 32default_db_path: Path = user_data_dir / 'syslog.db' 33"""Default DB file path""" 34 35default_db_low_size: int = int(1e6) 36"""Default DB low size count""" 37 38default_db_high_size: int = int(1e7) 39"""Default DB high size count""" 40 41default_syslog_addrs: list[str] = ['tcp://0.0.0.0:6514', 42 'udp://0.0.0.0:6514'] 43"""Default syslog listening addresses""" 44 45 46def create_argument_parser() -> argparse.ArgumentParser: 47 """Create argument parser""" 48 parser = argparse.ArgumentParser( 49 description="Syslog Server listening for TCP and/or UDP messages. " 50 "If listening addresses are not provided, Syslog Server " 51 "listens on 'tcp://0.0.0.0:6514' and " 52 "'udp://0.0.0.0:6514'.") 53 parser.add_argument( 54 '--log-level', metavar='LEVEL', default=default_log_level, 55 choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], 56 help=f"console log level (default {default_log_level})") 57 parser.add_argument( 58 '--ui-addr', metavar='ADDR', default=default_ui_addr, 59 help=f"UI listening address (default {default_ui_addr})") 60 parser.add_argument( 61 '--db-path', metavar='PATH', type=Path, default=default_db_path, 62 help="sqlite database file path " 63 "(default $XDG_DATA_HOME/hat/syslog.db)") 64 parser.add_argument( 65 '--db-low-size', metavar='N', type=int, default=default_db_low_size, 66 help=f"number of messages kept in database after database " 67 f"cleanup (default {default_db_low_size})") 68 parser.add_argument( 69 '--db-high-size', metavar='N', type=int, default=default_db_high_size, 70 help=f"number of messages that will trigger database cleanup " 71 f"(default {default_db_high_size})") 72 parser.add_argument( 73 '--db-enable-archive', action='store_true', 74 help="should messages, deleted during database cleanup, be kept " 75 "in archive files") 76 parser.add_argument( 77 '--db-disable-journal', action='store_true', 78 help="disable sqlite journaling") 79 parser.add_argument( 80 '--syslog-pem-path', metavar='PATH', type=Path, default=None, 81 help="certificate PEM path used in case of tls syslog") 82 parser.add_argument( 83 'syslog_addrs', metavar='ADDR', nargs='*', 84 default=default_syslog_addrs, 85 help="syslog listening address formated as <prot>://<host>:<port> " 86 "(<prot> is 'tcp', 'udp' or 'tls'; <host> is host name or IP " 87 "address; <port> is UDP/TCP port)") 88 return parser 89 90 91def main(): 92 """Syslog Server""" 93 parser = create_argument_parser() 94 args = parser.parse_args() 95 96 logging.config.dictConfig({ 97 'version': 1, 98 'formatters': { 99 'console_formater': { 100 'format': '[%(asctime)s %(levelname)s %(name)s] %(message)s'}}, 101 'handlers': { 102 'console_handler': { 103 'class': 'logging.StreamHandler', 104 'formatter': 'console_formater', 105 'level': args.log_level}}, 106 'root': { 107 'level': args.log_level, 108 'handlers': ['console_handler']}, 109 'disable_existing_loggers': False}) 110 111 aio.init_asyncio() 112 with contextlib.suppress(asyncio.CancelledError): 113 aio.run_asyncio(async_main(ui_addr=args.ui_addr, 114 db_path=args.db_path, 115 db_low_size=args.db_low_size, 116 db_high_size=args.db_high_size, 117 db_enable_archive=args.db_enable_archive, 118 db_disable_journal=args.db_disable_journal, 119 syslog_pem_path=args.syslog_pem_path, 120 syslog_addrs=args.syslog_addrs)) 121 122 123async def async_main(ui_addr: str, 124 db_path: Path, 125 db_low_size: int, 126 db_high_size: int, 127 db_enable_archive: bool, 128 db_disable_journal: bool, 129 syslog_pem_path: Path | None, 130 syslog_addrs: list[str]): 131 """Syslog Server async main""" 132 async_group = aio.Group() 133 134 async def on_msg(msg): 135 await backend.register(time.time(), msg) 136 137 async def async_close(): 138 await async_group.async_close() 139 await asyncio.sleep(0.1) 140 141 try: 142 mlog.debug("creating backend...") 143 backend = await _create_resource(async_group, create_backend, 144 db_path, db_low_size, db_high_size, 145 db_enable_archive, db_disable_journal) 146 147 mlog.debug("creating web server...") 148 await _create_resource(async_group, create_web_server, ui_addr, 149 backend) 150 151 mlog.debug("creating syslog servers...") 152 for syslog_addr in syslog_addrs: 153 await _create_resource(async_group, create_syslog_server, 154 syslog_addr, on_msg, syslog_pem_path) 155 156 mlog.debug("initialization done") 157 await async_group.wait_closing() 158 159 finally: 160 mlog.debug("closing...") 161 await aio.uncancellable(async_close()) 162 163 164async def _create_resource(async_group, fn, *args): 165 resource = await async_group.spawn(fn, *args) 166 async_group.spawn(aio.call_on_cancel, resource.async_close) 167 async_group.spawn(aio.call_on_done, resource.wait_closing(), 168 async_group.close) 169 return resource 170 171 172if __name__ == '__main__': 173 sys.argv[0] = 'hat-syslog-server' 174 sys.exit(main())
Module logger
user_data_dir: pathlib.Path =
PosixPath('/home/runner/.local/share/hat')
User data directory path
default_log_level: str =
'INFO'
Default console log level
default_ui_addr: str =
'http://0.0.0.0:23020'
Default UI listening address
default_db_path: pathlib.Path =
PosixPath('/home/runner/.local/share/hat/syslog.db')
Default DB file path
default_db_low_size: int =
1000000
Default DB low size count
default_db_high_size: int =
10000000
Default DB high size count
default_syslog_addrs: list[str] =
['tcp://0.0.0.0:6514', 'udp://0.0.0.0:6514']
Default syslog listening addresses
def
create_argument_parser() -> argparse.ArgumentParser:
47def create_argument_parser() -> argparse.ArgumentParser: 48 """Create argument parser""" 49 parser = argparse.ArgumentParser( 50 description="Syslog Server listening for TCP and/or UDP messages. " 51 "If listening addresses are not provided, Syslog Server " 52 "listens on 'tcp://0.0.0.0:6514' and " 53 "'udp://0.0.0.0:6514'.") 54 parser.add_argument( 55 '--log-level', metavar='LEVEL', default=default_log_level, 56 choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], 57 help=f"console log level (default {default_log_level})") 58 parser.add_argument( 59 '--ui-addr', metavar='ADDR', default=default_ui_addr, 60 help=f"UI listening address (default {default_ui_addr})") 61 parser.add_argument( 62 '--db-path', metavar='PATH', type=Path, default=default_db_path, 63 help="sqlite database file path " 64 "(default $XDG_DATA_HOME/hat/syslog.db)") 65 parser.add_argument( 66 '--db-low-size', metavar='N', type=int, default=default_db_low_size, 67 help=f"number of messages kept in database after database " 68 f"cleanup (default {default_db_low_size})") 69 parser.add_argument( 70 '--db-high-size', metavar='N', type=int, default=default_db_high_size, 71 help=f"number of messages that will trigger database cleanup " 72 f"(default {default_db_high_size})") 73 parser.add_argument( 74 '--db-enable-archive', action='store_true', 75 help="should messages, deleted during database cleanup, be kept " 76 "in archive files") 77 parser.add_argument( 78 '--db-disable-journal', action='store_true', 79 help="disable sqlite journaling") 80 parser.add_argument( 81 '--syslog-pem-path', metavar='PATH', type=Path, default=None, 82 help="certificate PEM path used in case of tls syslog") 83 parser.add_argument( 84 'syslog_addrs', metavar='ADDR', nargs='*', 85 default=default_syslog_addrs, 86 help="syslog listening address formated as <prot>://<host>:<port> " 87 "(<prot> is 'tcp', 'udp' or 'tls'; <host> is host name or IP " 88 "address; <port> is UDP/TCP port)") 89 return parser
Create argument parser
def
main():
92def main(): 93 """Syslog Server""" 94 parser = create_argument_parser() 95 args = parser.parse_args() 96 97 logging.config.dictConfig({ 98 'version': 1, 99 'formatters': { 100 'console_formater': { 101 'format': '[%(asctime)s %(levelname)s %(name)s] %(message)s'}}, 102 'handlers': { 103 'console_handler': { 104 'class': 'logging.StreamHandler', 105 'formatter': 'console_formater', 106 'level': args.log_level}}, 107 'root': { 108 'level': args.log_level, 109 'handlers': ['console_handler']}, 110 'disable_existing_loggers': False}) 111 112 aio.init_asyncio() 113 with contextlib.suppress(asyncio.CancelledError): 114 aio.run_asyncio(async_main(ui_addr=args.ui_addr, 115 db_path=args.db_path, 116 db_low_size=args.db_low_size, 117 db_high_size=args.db_high_size, 118 db_enable_archive=args.db_enable_archive, 119 db_disable_journal=args.db_disable_journal, 120 syslog_pem_path=args.syslog_pem_path, 121 syslog_addrs=args.syslog_addrs))
Syslog Server
async def
async_main( ui_addr: str, db_path: pathlib.Path, db_low_size: int, db_high_size: int, db_enable_archive: bool, db_disable_journal: bool, syslog_pem_path: pathlib.Path | None, syslog_addrs: list[str]):
124async def async_main(ui_addr: str, 125 db_path: Path, 126 db_low_size: int, 127 db_high_size: int, 128 db_enable_archive: bool, 129 db_disable_journal: bool, 130 syslog_pem_path: Path | None, 131 syslog_addrs: list[str]): 132 """Syslog Server async main""" 133 async_group = aio.Group() 134 135 async def on_msg(msg): 136 await backend.register(time.time(), msg) 137 138 async def async_close(): 139 await async_group.async_close() 140 await asyncio.sleep(0.1) 141 142 try: 143 mlog.debug("creating backend...") 144 backend = await _create_resource(async_group, create_backend, 145 db_path, db_low_size, db_high_size, 146 db_enable_archive, db_disable_journal) 147 148 mlog.debug("creating web server...") 149 await _create_resource(async_group, create_web_server, ui_addr, 150 backend) 151 152 mlog.debug("creating syslog servers...") 153 for syslog_addr in syslog_addrs: 154 await _create_resource(async_group, create_syslog_server, 155 syslog_addr, on_msg, syslog_pem_path) 156 157 mlog.debug("initialization done") 158 await async_group.wait_closing() 159 160 finally: 161 mlog.debug("closing...") 162 await aio.uncancellable(async_close())
Syslog Server async main