Source code for mentat.module.informant

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# This file is part of Mentat system (https://mentat.cesnet.cz/).
#
# Copyright (C) since 2011 CESNET, z.s.p.o (http://www.ces.net/)
# Use of this source is governed by the MIT license, see LICENSE file.
#-------------------------------------------------------------------------------


"""
This Mentat module is a script providing periodical informational reports about
overall performance of Mentat system.

This script is implemented using the :py:mod:`pyzenkit.zenscript` framework and
so it provides all of its core features. See the documentation for more in-depth
details.

It is further based on :py:mod:`mentat.script.fetcher` module, which provides
database fetching and message post-processing capabilities.


Usage examples
--------------

.. code-block:: shell

    # Display help message and exit.
    mentat-informant.py --help

    # Run in debug mode (enable output of debugging information to terminal).
    mentat-informant.py --debug

    # Run with increased logging level.
    mentat-informant.py --log-level debug


Available script commands
-------------------------

``report`` (*default*)
    Generate report containing overall Mentat system performance statistics
    within configured time interval thresholds.

"""


__author__  = "Jan Mach <jan.mach@cesnet.cz>"
__credits__ = "Pavel Kácha <pavel.kacha@cesnet.cz>, Andrea Kropáčová <andrea.kropacova@cesnet.cz>"


#
# Custom libraries
#
import mentat.script.fetcher
import mentat.plugin.app.mailer
import mentat.const
import mentat.reports.overview


[docs]class MentatInformantScript(mentat.script.fetcher.FetcherScript): """ Implementation of Mentat module (script) providing periodical statistical overview for message processing performance analysis. """ # # Class constants. # # List of configuration keys. CORECFG_INFORMANT = '__core__informant' CONFIG_REPORTS_DIR = 'reports_dir' CONFIG_TEMPLATES_DIR = 'templates_dir' CONFIG_TEMPLATE_VARS = 'template_vars' CONFIG_FORCE_TEMPLATE = 'force_template' CONFIG_FORCE_LOCALE = 'force_locale' CONFIG_FORCE_TIMEZONE = 'force_timezone' def __init__(self): """ Initialize statistician script object. This method overrides the base implementation in :py:func:`mentat.script.fetcher.FetcherScript.__init__` and it aims to even more simplify the script object creation by providing configuration values for parent contructor. """ # Declare private attributes. self.sqlservice = None self.mailerservice = None super().__init__( description = 'mentat-informant.py - Mentat system overall performance statistics', # # Load additional application-level plugins. # plugins = [ mentat.plugin.app.mailer.MailerPlugin() ] ) def _sub_stage_init(self, **kwargs): """ **SUBCLASS HOOK**: Perform additional custom initialization actions. This method is called from the main constructor in :py:func:`pyzenkit.baseapp.BaseApp.__init__` as a part of the **__init__** stage of application`s life cycle. :param kwargs: Various additional parameters passed down from constructor. """ # Override default 'interval' value. self.config[self.CONFIG_INTERVAL] = 'daily' # Override default 'adjust_thresholds' value. self.config[self.CONFIG_ADJUST_THRESHOLDS] = True def _init_argparser(self, **kwargs): """ Initialize script command line argument parser. This method overrides the base implementation in :py:func:`pyzenkit.zenscript.ZenScript._init_argparser` and it must return valid :py:class:`argparse.ArgumentParser` object. It appends additional command line options custom for this script object. This method is called from the main constructor in :py:func:`pyzenkit.baseapp.BaseApp.__init__` as a part of the **__init__** stage of application`s life cycle. :param kwargs: Various additional parameters passed down from object constructor. :return: Valid argument parser object. :rtype: argparse.ArgumentParser """ argparser = super()._init_argparser(**kwargs) # # Create and populate options group for custom script arguments. # arggroup_script = argparser.add_argument_group('custom script arguments') arggroup_script.add_argument( '--force-template', type = str, default = None, help = 'force a template for generating reports' ) arggroup_script.add_argument( '--force-locale', type = str, default = None, help = 'force a locale for generating reports' ) arggroup_script.add_argument( '--force-timezone', type = str, default = None, help = 'force a timezone for generating reports' ) return argparser def _init_config(self, cfgs, **kwargs): """ Initialize default script configurations. This method overrides the base implementation in :py:func:`pyzenkit.zenscript.ZenScript._init_config` and it appends additional configurations via ``cfgs`` parameter. This method is called from the main constructor in :py:func:`pyzenkit.baseapp.BaseApp.__init__` as a part of the **__init__** stage of application`s life cycle. :param list cfgs: Additional set of configurations. :param kwargs: Various additional parameters passed down from constructor. :return: Default configuration structure. :rtype: dict """ cfgs = ( (self.CONFIG_FORCE_TEMPLATE, 'default'), (self.CONFIG_FORCE_LOCALE, 'en'), (self.CONFIG_FORCE_TIMEZONE, 'UTC'), (self.CONFIG_TEMPLATE_VARS, {}), ) + cfgs return super()._init_config(cfgs, **kwargs) #---------------------------------------------------------------------------
[docs] def get_default_command(self): """ Return the name of the default script command. This command will be executed in case it is not explicitly selected either by command line option, or by configuration file directive. :return: Name of the default command. :rtype: str """ return 'report'
[docs] def cbk_command_report(self): """ Implementation of the **report** command (*default*). Calculate statistics for messages stored into database within configured time interval thresholds. """ (time_l, time_h) = self.calculate_interval_thresholds( time_high = self.c(self.CONFIG_TIME_HIGH), interval = self.c(self.CONFIG_INTERVAL), adjust = self.c(self.CONFIG_REGULAR) ) time_l = time_l.replace(microsecond = 0) time_h = time_h.replace(microsecond = 0) self.logger.info("Lower summary report calculation time interval threshold: %s (%s)", time_l.isoformat(), time_l.timestamp()) self.logger.info("Upper summary report calculation time interval threshold: %s (%s)", time_h.isoformat(), time_h.timestamp()) self.logger.info("Using template '%s' to generate informational summary report.", self.c(self.CONFIG_FORCE_TEMPLATE)) reporter = mentat.reports.overview.OverviewReporter( self.logger, self.config[self.CORECFG_INFORMANT][self.CONFIG_REPORTS_DIR], self.config[self.CORECFG_INFORMANT][self.CONFIG_TEMPLATES_DIR], self.c(self.CONFIG_FORCE_LOCALE), self.c(self.CONFIG_FORCE_TIMEZONE) ) result = reporter.report( time_h, time_l, self.sqlservice.session, self.c(self.CONFIG_FORCE_TEMPLATE), self.mailerservice, self.c(self.CONFIG_TEMPLATE_VARS), ) return result