����JFIF��x�x����'
Server IP : 78.140.185.180 / Your IP : 216.73.216.82 Web Server : LiteSpeed System : Linux cpanel13.v.fozzy.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64 User : builderbox ( 1072) PHP Version : 7.3.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /opt/cloudlinux/venv/lib64/python3.11/site-packages/cl_plus/collectors/ |
Upload File : |
# coding=utf-8 # # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2020 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENCE.TXT # import time import warnings from typing import Optional, Tuple try: import pymysql except ImportError: pymysql = None from clcommon.cpapi import db_access from clcommon.cpapi.cpapiexceptions import NoDBAccessData, NotSupported from clcommon import mysql_lib from .collector_base import CollectorBase # enough to collect only several times per minute, cause we rely on DB counter MYSQL_COLLECTION_INTERVAL = 30 def _total_queries_num_request(db, query_str): """ Execs passed query and returns value """ with warnings.catch_warnings(): warnings.filterwarnings('ignore', category=pymysql.Warning) data = db.execute_query(query_str) return data[0][1] class MySQLCollector(CollectorBase): class DBAccess: def __init__(self, login: Optional[str] = None, password: Optional[str] = None): self.login = login self.password = password self.expire_time = time.time() + 3600 def __eq__(self, other): return self.login == other.login and self.password == other.password def __bool__(self): return bool(self.login and self.password and not self.is_expired()) def is_expired(self) -> bool: return time.time() > self.expire_time def __init__(self, _logger): super(MySQLCollector, self).__init__(_logger) self._is_mysql_error = False self.collection_interval = MYSQL_COLLECTION_INTERVAL self.access = self.DBAccess() self.previous_num, self.current_num = None, None self._aggregation_times = 0 def init(self): """ Initialize MySQL collector :return: None """ self._aggregated_data = 0 self._logger.info("MySQL collector init") self._logger.info('MySQL collector initial values: previous: %s, current: %s', str(self.previous_num), str(self.current_num)) def _get_total_queries_num(self, dblogin: str, dbpass: str): """ Gets total queries number via Queries variable in DB it is a total counter of queries made to DB it is used be such monitoring system as Nagios and mysqladmin returns it https://github.com/nagios-plugins/nagios-plugins/blob/master/plugins/check_mysql.c """ if not pymysql: return "No MySQL client libraries installed", 0 try: connector = mysql_lib.MySQLConnector(host='localhost', user=dblogin, passwd=dbpass, db='mysql', use_unicode=True, charset='utf8') with connector.connect() as db: total = _total_queries_num_request(db, 'show global status where Variable_name = \'Questions\';') self._aggregation_times += 1 # since mysql_lib is our lib, it could through different exceptions except Exception as e: return str(e), 0 return 'OK', int(total) def _get_db_access(self) -> Tuple[str, str]: """ Get DB access data from cpapi function. Logs error :return: tuple (db_root_login, db_password) None, None if error """ if not self.access: try: access = db_access() # {'pass': str, 'login': str} self.access = self.DBAccess(access['login'], access['pass']) except (NoDBAccessData, NotSupported, KeyError, TypeError) as e: # Can't retrieve data if not self._is_mysql_error: self._logger.warn("MySQL collector: can't obtain MySQL DB access: %s", str(e)) self._is_mysql_error = True return self.access.login, self.access.password def aggregate_new_data(self): """ Retrieve and aggregate new data :return None """ self._get_db_access() if not self.access: # access data still is not set return # New data present - aggregate message, total_queries = self._get_total_queries_num(self.access.login, self.access.password) if message == 'OK': self.previous_num = self.current_num self.current_num = total_queries # no previous value to compare during 1st iteration after collector is started if self.previous_num is not None and self.current_num is not None: # if mysql counter was re-set if self.current_num < self.previous_num: self._logger.info('MySQL collector: QUERIES counter was re-set in database, ' 're-set collectors previous counter as well') self.previous_num = 0 self._aggregated_data += self.current_num - self.previous_num self._is_mysql_error = False return # Retrieve data error if not self._is_mysql_error: self._logger.error("MySQL collector can't obtain MySQL queries number: %s", message) self._is_mysql_error = True def get_averages(self): """ Get collector's averages data :return: dict: { "mysql_queries_num": 16} or None if can't get data """ mysql_queries_num = max(0, self._aggregated_data - self._aggregation_times) self._aggregated_data = 0 self._aggregation_times = 0 return {"mysql_queries_num": mysql_queries_num}