linspector/bin/linspector

205 lines
8.8 KiB
Python
Executable file

#!/usr/bin/python3 -d
"""
This file is part of Linspector (https://linspector.org/)
Copyright (c) 2013-2023 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.
"""
# TODO: VERY IMPORTANT! IMPLEMENT ERROR HANDLING ALL THE WAY...!!!
# Only exit execution on critical core errors. Do not exit when monitors are failing on
# configuration and execution, but log these errors.
import argparse
import importlib
import signal
import sys
from loguru import logger as log
from linspector.configuration import Configuration
from linspector.environment import Environment
from linspector.linspector import Linspector
from linspector.monitors import Monitors
__author__ = 'Johannes Findeisen'
__author_email__ = 'you@hanez.org'
__description__ = 'linspector is a infrastructure and system monitoring daemon and toolchain.'
__version__ = '0.30.2'
sys.stderr = open('/dev/null', 'w')
def parse_args():
parser = argparse.ArgumentParser(
description=__description__,
epilog='author: ' + __author__ + ' <' + __author_email__ + '>',
prog='linspector')
parser.add_argument('configuration_path', metavar='CONFIGURATION_PATH',
help='the configuration path to use')
parser.add_argument('-d', '--daemon', default=False, dest='daemon', action='store_true',
help='run linspector as native daemon (default: false)')
parser.add_argument('-k', '--kill', default=False, dest='kill', action='store_true',
help='kill the daemon if it is running (default: false)')
parser.add_argument('-r', '--restart', default=False, dest='restart', action='store_true',
help='restart the daemon if it is running (default: false)')
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + str(__version__))
return parser.parse_args()
def linspector():
print('Starting Linspector ' + __version__ + '...')
print('This software is free software licensed under the terms of the MIT license. Copyright (c) 2013-2023 by ' +
__author__ + ' <' + __author_email__ + '>')
args = parse_args()
monitors = {}
notifications = {}
plugins = {}
# the scheduler is a dict to make it possible in the future to run more than one scheduler in
# one linspector instance. need to think about it a little more...
scheduler = {}
services = {}
tasks = {}
try:
configuration = Configuration(args.configuration_path)
except Exception as err:
print('Configuration error: {0}'.format(err))
sys.exit(1)
log.remove()
default_log_format = 'timestamp={time:YYYY-MM-DD HH:mm:ss.SSSSSS ZZ} uptime={elapsed} level={level} ' \
'name=linspector {message}'
if configuration.get_option('linspector', 'logfile'):
logfile_count = '10'
if configuration.get_option('linspector', 'logfile_count'):
logfile_count = configuration.get_option('linspector', 'logfile_count')
logfile_format = default_log_format
if configuration.get_option('linspector', 'logfile_format'):
logfile_format = configuration.get_option('linspector', 'logfile_format')
logfile_level = 'INFO'
if configuration.get_option('linspector', 'logfile_level'):
logfile_level = configuration.get_option('linspector', 'logfile_level')
if logfile_level == 'DEBUG':
logfile_format = 'timestamp={time:YYYY-MM-DD HH:mm:ss.SSSSSS ZZ} uptime={elapsed} level={level} ' \
'name=linspector exec={name}:{function} line={line} {message}'
logfile_size = '1MB'
if configuration.get_option('linspector', 'logfile_size'):
logfile_size = configuration.get_option('linspector', 'logfile_size')
log.add(configuration.get_option('linspector', 'logfile'), backtrace=True, diagnose=True, enqueue=True,
format=logfile_format, level=logfile_level, retention=int(logfile_count), rotation=logfile_size)
default_debug_log_format = 'timestamp={time:YYYY-MM-DD HH:mm:ss.SSSSSS ZZ} uptime={elapsed} level={level} ' \
'name=linspector exec={name}:{function} line={line} {message}'
if configuration.get_option('linspector', 'debug_logfile'):
debug_logfile_count = '10'
if configuration.get_option('linspector', 'debug_logfile_count'):
debug_logfile_count = configuration.get_option('linspector', 'debug_logfile_count')
debug_logfile_format = default_debug_log_format
if configuration.get_option('linspector', 'error_logfile_format'):
debug_logfile_format = configuration.get_option('linspector', 'debug_logfile_format')
debug_logfile_level = 'DEBUG'
debug_logfile_size = '1MB'
if configuration.get_option('linspector', 'debug_logfile_size'):
debug_logfile_size = configuration.get_option('linspector', 'debug_logfile_size')
log.add(configuration.get_option('linspector', 'debug_logfile'), backtrace=True, diagnose=True,
enqueue=True, format=debug_logfile_format, level=debug_logfile_level,
retention=int(debug_logfile_count), rotation=debug_logfile_size)
default_error_log_format = 'timestamp={time:YYYY-MM-DD HH:mm:ss.SSSSSS ZZ} uptime={elapsed} level={level} ' \
'name=linspector exec={name}:{function} line={line} {message}'
if configuration.get_option('linspector', 'error_logfile'):
error_logfile_count = '10'
if configuration.get_option('linspector', 'error_logfile_count'):
error_logfile_count = configuration.get_option('linspector', 'error_logfile_count')
error_logfile_format = default_error_log_format
if configuration.get_option('linspector', 'error_logfile_format'):
error_logfile_format = configuration.get_option('linspector', 'error_logfile_format')
error_logfile_level = 'ERROR'
error_logfile_size = '1MB'
if configuration.get_option('linspector', 'error_logfile_size'):
error_logfile_size = configuration.get_option('linspector', 'error_logfile_size')
log.add(configuration.get_option('linspector', 'error_logfile'), backtrace=True, diagnose=True,
enqueue=True, format=error_logfile_format, level=error_logfile_level,
retention=int(error_logfile_count), rotation=error_logfile_size)
environment = Environment(log)
try:
if configuration.get_option('linspector', 'tasks'):
log.info('loading tasks: ' + configuration.get_option('linspector', 'tasks'))
print('Loading tasks: ' + configuration.get_option('linspector', 'tasks'))
task_list = configuration.get_option('linspector', 'tasks')
task_list = task_list.split(',')
for task_name in task_list:
task_package = 'linspector.tasks.' + task_name
if importlib.util.find_spec(task_package) is not None:
task_module = importlib.import_module(task_package)
task_object = task_module.create(configuration, environment, log)
tasks[task_name] = task_object
else:
log.warning('initialization of task: {0} failed! seems it does not exist.'.format(task_name))
except Exception as err:
log.warning('task initialization error: {0}'.format(err))
try:
monitors = Monitors(configuration, environment, log, notifications, services, tasks)
except Exception as err:
log.warning('monitor initialization error: {0}'.format(err))
try:
linspector = Linspector(configuration, environment, log, monitors, plugins, scheduler)
# linspector.print_debug()
except Exception as err:
log.critical('core initialization error: {0}'.format(err))
log.critical('program terminating...')
sys.exit(1)
# daemon initialization
if args.daemon:
try:
from linspector.linspectord import Linspectord
linspectord = Linspectord(configuration, environment, linspector, log)
# do handling of restart, start and stop commands but for now "start" is enough... ;)
if args.kill:
log.info('stopping daemon.')
linspectord.stop()
elif args.restart:
log.info('restarting daemon.')
linspectord.restart()
else:
log.info('starting daemon.')
linspectord.start()
except Exception as err:
log.critical('daemon error: {0}'.format(err))
sys.exit(1)
else:
try:
signal.pause()
except KeyboardInterrupt:
log.info('program terminated by user!')
print('Program terminated by user!')
if __name__ == '__main__':
linspector()