133 lines
6.3 KiB
Python
133 lines
6.3 KiB
Python
"""
|
|
This file is part of Linspector (https://linspector.org/)
|
|
Copyright (c) 2013-2023 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
|
|
See LICENSE.
|
|
"""
|
|
|
|
import datetime
|
|
import importlib
|
|
import random
|
|
|
|
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
|
|
from apscheduler.jobstores.memory import MemoryJobStore
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
|
from pytz import utc
|
|
|
|
|
|
def job_execution(log, monitor):
|
|
try:
|
|
log.debug('executing job_function for monitor identifier: ' + monitor.get_identifier() +
|
|
' with monitor object: ' + str(monitor))
|
|
monitor.execute()
|
|
except Exception as err:
|
|
log.warning('execution failed for job_function for monitor identifier: ' +
|
|
monitor.get_identifier() + ' with monitor object: ' + str(monitor) +
|
|
' error: ' + str(err))
|
|
|
|
|
|
class Linspector:
|
|
def __init__(self, configuration, environment, log, monitors, plugins, scheduler):
|
|
self._configuration = configuration
|
|
self._environment = environment
|
|
self._jobs = []
|
|
self._log = log
|
|
self._monitors = monitors
|
|
self._plugin_list = []
|
|
self._plugins = plugins
|
|
self._scheduler = scheduler
|
|
|
|
# load plugins
|
|
log.info('message=loading plugins')
|
|
if configuration.get_option('linspector', 'plugins'):
|
|
plugin_list = configuration.get_option('linspector', 'plugins')
|
|
self._plugin_list = plugin_list.split(',')
|
|
for plugin_option in self._plugin_list:
|
|
if plugin_option not in plugins:
|
|
log.info('loading plugin: ' + plugin_option)
|
|
plugin_package = 'linspector.plugins.' + plugin_option.lower()
|
|
plugin_module = importlib.import_module(plugin_package)
|
|
plugin = plugin_module.create(configuration, environment, log, self)
|
|
plugins[plugin_option.lower()] = plugin
|
|
|
|
jobstores = {
|
|
'memory': MemoryJobStore()
|
|
}
|
|
if configuration.get_option('linspector', 'max_threads') and not \
|
|
configuration.get_option('linspector', 'scheduler_mode') == 'process':
|
|
executors = {
|
|
'default': ThreadPoolExecutor(int(configuration.get_option('linspector',
|
|
'max_threads')))
|
|
}
|
|
else:
|
|
executors = {
|
|
'default': ThreadPoolExecutor(1024)
|
|
}
|
|
if configuration.get_option('linspector', 'scheduler_mode'):
|
|
if configuration.get_option('linspector', 'scheduler_mode') == 'process':
|
|
executors = {
|
|
'default': ThreadPoolExecutor(
|
|
int(configuration.get_option('linspector', 'max_threads'))),
|
|
'processpool': ProcessPoolExecutor(
|
|
int(configuration.get_option('linspector', 'max_processes')))
|
|
}
|
|
job_defaults = {
|
|
'coalesce': True,
|
|
# every scheduler job (monitor) must only exist once.
|
|
'max_instances': 1
|
|
}
|
|
self._scheduler['linspector'] = BackgroundScheduler(jobstores=jobstores,
|
|
executors=executors,
|
|
job_defaults=job_defaults,
|
|
timezone=utc)
|
|
|
|
start_date = datetime.datetime.now()
|
|
log.debug(monitors.get_monitors())
|
|
monitors = self._monitors.get_monitors()
|
|
for monitor in monitors:
|
|
log.debug(monitor)
|
|
if configuration.get_option('linspector', 'delta_range'):
|
|
time_delta = round(random.uniform(0.00, float(
|
|
configuration.get_option('linspector', 'delta_range'))), 3)
|
|
else:
|
|
time_delta = round(random.uniform(0.00, 60.000), 3)
|
|
|
|
# TODO: write get functions in the monitor to get options. do not call
|
|
# get_monitor_configuration_option() here (example: get_start_date()).
|
|
if monitors.get(monitor).get_monitor_configuration_option('args', 'start_date'):
|
|
new_start_date = \
|
|
monitors.get(monitor).get_monitor_configuration_option('args', 'start_date')
|
|
else:
|
|
new_start_date = start_date + datetime.timedelta(seconds=time_delta)
|
|
|
|
monitor_job = monitors.get(monitor)
|
|
interval = monitor_job.get_interval()
|
|
|
|
if configuration.get_option('linspector', 'timezone'):
|
|
timezone = configuration.get_option('linspector', 'timezone')
|
|
if monitors.get(monitor).get_monitor_configuration_option('monitor', 'timezone'):
|
|
timezone = monitors.get(monitor).get_monitor_configuration_option('monitor',
|
|
'timezone')
|
|
else:
|
|
# set to local system timezone by as default
|
|
timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzname()
|
|
|
|
# add cron and one time run jobs to Linspector. not only "interval" jobs should be
|
|
# supported.
|
|
scheduler_job = scheduler['linspector'].add_job(job_execution,
|
|
'interval',
|
|
start_date=new_start_date,
|
|
seconds=interval,
|
|
timezone=timezone,
|
|
args=[log, monitors.get(monitor)])
|
|
|
|
monitor_job.set_job(scheduler_job)
|
|
self._jobs.append(monitor_job)
|
|
log.info('identifier=' + monitor +
|
|
' host=' + monitors.get(monitor).get_host() +
|
|
' service=' + monitor_job.get_service() +
|
|
' delta=' + str(time_delta) +
|
|
' next=' + str(new_start_date) +
|
|
' message=scheduling job')
|
|
|
|
if configuration.get_option('linspector', 'start_scheduler') == 'true':
|
|
self._scheduler['linspector'].start()
|