<commit_before>"""
Server Density plugin
MySQL

https://www.serverdensity.com/plugins/mysql/
https://github.com/serverdensity/sd-agent-plugins/

version: 0.1
"""
import traceback
import re

try:
    import MySQLdb
except ImportError:
    pass

# com commands.
COMMANDS = [
    'Com_select',
    'Com_delete',
    'Com_update',
    'Com_commit',
    'Questions',
    'Com_rollback',
]


class MySQL(object):

    def __init__(self, agent_config, checks_logger, raw_config):
        self.agent_config = agent_config
        self.checks_logger = checks_logger
        self.raw_config = raw_config
        self.connection = None
        self.datastore = {}

    def version_is_above_5(self, status):
        if (int(status['version'][0]) >= 5
                and int(status['version'][2]) >= 2):
            return True
        else:
            return False

    def get_db_results(self, db, query):
        cursor = db.cursor()
        try:
            cursor.execute(query)
            results = float(cursor.fetchone()[1])
        except ValueError:
            cursor.execute(query)
            results = cursor.fetchone()[1]
        return results

    def calculate_per_s(self, command, result):
        if (not self.datastore.get(command)
                and self.datastore.get(command) != 0):
            self.checks_logger.debug(
                'mysql: Datastore unset for '
                '{}, storing for first time'.format(command))
            self.datastore[command] = result
            com_per_s = 0
        else:
            com_per_s = (result - self.datastore[command]) / 60
            if com_per_s < 0:
                com_per_s = 0
            self.datastore[command] = result
        return com_per_s

    def preliminaries(self):
        if ('MySQLServer' not in self.raw_config
                and 'mysql_server' not in self.raw_config['MySQLServer']
                or self.raw_config['MySQLServer']['mysql_server'] == ''
                or self.raw_config['MySQLServer']['mysql_user'] == ''
                or self.raw_config['MySQLServer']['mysql_pass'] == ''):
            self.checks_logger.debug('mysql: config not set')
            return False

        if not self.raw_config['MySQLServer'].get('mysql_port'):
            self.raw_config['MySQLServer']['mysql_port'] = "3306"

        self.checks_logger.debug('mysql: config set')

        try:
            import MySQLdb
        except ImportError:
            self.checks_logger.error('mysql: unable to import MySQLdb')
            return False

        # Note, code here doesn't really make sense. See what I copied.
        if not self.raw_config['MySQLServer'].get('mysql_port'):
            # Connect
            try:
                MySQLdb.connect(
                    host=self.raw_config['MySQLServer']['mysql_server'],
                    user=self.raw_config['MySQLServer']['mysql_user'],
                    passw=self.raw_config['MySQLServer']['mysql_pass'],
                    port=int(self.raw_config['MySQLServer']['mysql_port'])
                    )
            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    "mysql: MySQL connection error: {}".format(message))
                return False
        else:
            # Connect
            try:
                MySQLdb.connect(
                    host='localhost',
                    user=self.raw_config['MySQLServer']['mysql_user'],
                    passwd=self.raw_config['MySQLServer']['mysql_pass'],
                    port=int(self.raw_config['MySQLServer']['mysql_port']))
            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL connection error: {}'.format(message)
                    )
                return False
        return True

    def get_connection(self):
        try:
            # connection
            db = MySQLdb.connect(
                host=self.raw_config['MySQLServer']['mysql_server'],
                user=self.raw_config['MySQLServer']['mysql_user'],
                passwd=self.raw_config['MySQLServer']['mysql_pass'],
                port=int(self.raw_config['MySQLServer']['mysql_port'])
                )
            self.connection = db
            # note, how do I take into account the socket?
        except Exception:
            self.checks_logger.error(
                'Unable to connect to MySQL server {0}'
                ' - Exception: {1}'.format(
                    self.config_raw['MySQLServer']['mysql_server'],
                    traceback.format_exc())
                )
            return False
        return True

    def run(self):
        self.checks_logger.debug('mysql: started gathering data')
        if not self.preliminaries():
            return False

        if not self.get_connection():
            return False

        try:
            db = self.connection

            # setup
            status = {}

            # Get MySQL version
            try:
                self.checks_logger.debug('mysql: getting mysqlversion')

                cursor = db.cursor()
                cursor.execute('SELECT VERSION()')
                result = cursor.fetchone()

                version = result[0].split('-')
                # Case 31237. Might include a description e.g. 4.1.26-log.
                # See http://dev.mysql.com/doc/refman/4.1/en/
                # information-functions.html#function_version
                version = version[0].split('.')

                status['version'] = []

                for version_item in version:
                    number = re.match('([0-9]+)', version_item)
                    number = number.group(0)
                    status['version'].append(number)

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when getting version: {}'.format(
                        message)
                    )
                return False

            # get Uptime
            try:
                status['Uptime'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Uptime"'
                )
            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when getting Uptime = {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting Uptime - done')

            # Slow queries
            # Determine query depending on version. For 5.02 and above we
            # need the GLOBAL keyword (case 31015)
            # note, update with slow queries store. making it per second?
            # ask jordi about that.
            try:
                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Slow_queries"'
                else:
                    query = 'SHOW STATUS LIKE "Slow_queries'

                status['Slow queries'] = self.get_db_results(db, query)
            except MySQLdb.OperationalError as message:
                self.checks_logger(
                    'mysql: MySQL query error when '
                    'getting Slow_queries = {}'.format(
                        message)
                    )
                return False
            self.checks_logger.debug('mysql: getting Slow_queries - done')

            # QPS - Queries per second.
            try:
                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Queries"'
                else:
                    query = 'SHOW STATUS LIKE "Queries"'

                qps = self.calculate_per_s('qps', self.get_db_results(
                    db, query))
                status['Queries per second'] = qps

            except MySQLdb.OperationalError as message:
                self.checks_logger.debug(
                    'mysql: MySQL query error when getting QPS = {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting QPS - done')

            # Connection pool
            try:
                status['threads connected'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Threads_connected"')

                status['threads running'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Threads_running"')

                status['max connections'] = self.get_db_results(
                    db, 'SHOW VARIABLES LIKE "max_connections"')

                status['max used connections'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Max_used_connections"')

                status['Connection usage %'] = (
                    (status['threads running']/status['max connections'])*100
                )

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting Threads_connected: {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting connections - done')

            # Buffer pool
            try:

                status['buffer pool pages total'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_total"')

                status['buffer pool pages free'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_free"')

                status['buffer pool pages dirty'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_dirty"')

                status['buffer pool pages data'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_data"')

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting Buffer pool pages = {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting buffer pool - done')

            # Query cache items
            try:
                status['qcache hits'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_hits"')

                qcache_ps = self.calculate_per_s('qcache_ps', status[
                    'qcache hits'])
                status['qcache hits/s'] = qcache_ps

                status['qcache free memory'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_free_memory"')

                status['qcache not cached'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_not_cached"')

                status['qcache in cache'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_queries_in_cache"')

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting Qcache data = {}'.format(
                        message))
                return False

            self.checks_logger.debug('mysql: getting Qcache data - done')

            # writes, reads, transactions
            try:
                # writes
                insert = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_insert"')

                replace = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_replace"')

                update = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_update"')

                delete = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_delete"')

                writes = insert + replace + update + delete
                status['Writes/s'] = self.calculate_per_s('writes', writes)

                # reads
                select = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_select"')

                reads = select + status['qcache hits']
                status['Reads/s'] = self.calculate_per_s('reads', reads)

                # read write ratio
                try:
                    status['RW ratio'] = reads/writes
                except ZeroDivisionError:
                    status['RW ratio'] = 0

                # transactions
                commit = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_commit"')

                rollback = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_rollback"')

                transactions = commit + rollback
                status['Transactions/s'] = self.calculate_per_s(
                    'transactions', transactions)

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when getting writes,'
                    ' reads and transactions = {}'.format(
                        message)
                )
                return False

            # Aborted connections and clients
            try:
                status['aborted clients'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Aborted_clients"')

                status['aborted connects'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Aborted_connects"')

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting aborted items = {}'.format(
                        message)
                )
                return False

            self.checks_logger.debug(
                'mysql: getting aborted connections - done')

            # Replication - Seconds Behind Master
            secondsBehindMaster = None
            try:
                cursor = db.cursor(MySQLdb.cursors.DictCursor)
                cursor.execute('SHOW SLAVE STATUS')
                result = cursor.fetchone()

            except MySQLdb.OperationalError as message:

                self.mainLogger.error(
                    'getMySQLStatus: MySQL query error when '
                    'getting SHOW SLAVE STATUS = %s', message)
                result = None

            if result is not None:
                try:
                    # Handle the case when Seconds_Behind_Master is NULL
                    if result['Seconds_Behind_Master'] is None:
                        secondsBehindMaster = -1
                    else:
                        secondsBehindMaster = result['Seconds_Behind_Master']

                    self.mainLogger.debug(
                        'getMySQLStatus: '
                        'secondsBehindMaster = %s', secondsBehindMaster
                    )

                except IndexError as e:
                    self.mainLogger.debug(
                        'getMySQLStatus: secondsBehindMaster empty. %s', e
                    )

            else:
                self.mainLogger.debug(
                    'getMySQLStatus: secondsBehindMaster empty. Result = None.'
                )

            # Created temporary tables in memory and on disk
            try:
                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Created_tmp_tables"'
                else:
                    query = 'SHOW STATUS LIKE "Created_tmp_tables"'
                status['created tmp tables'] = self.get_db_results(
                    db, query)

                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Created_tmp_disk_tables"'
                else:
                    query = 'SHOW STATUS LIKE "Created_tmp_disk_tables"'
                status['created tmp tables on disk'] = self.get_db_results(
                    db, query)

                status['Tmp Cache Hit Ratio'] = (
                    (1 - (status['created tmp tables on disk'] /
                          status['created tmp tables'])) * 100
                )<commit_msg>Remove tmp cache hit ratio<commit_after>"""
Server Density plugin
MySQL

https://www.serverdensity.com/plugins/mysql/
https://github.com/serverdensity/sd-agent-plugins/

version: 0.1
"""
import traceback
import re

try:
    import MySQLdb
except ImportError:
    pass

# com commands.
COMMANDS = [
    'Com_select',
    'Com_delete',
    'Com_update',
    'Com_commit',
    'Questions',
    'Com_rollback',
]


class MySQL(object):

    def __init__(self, agent_config, checks_logger, raw_config):
        self.agent_config = agent_config
        self.checks_logger = checks_logger
        self.raw_config = raw_config
        self.connection = None
        self.datastore = {}

    def version_is_above_5(self, status):
        if (int(status['version'][0]) >= 5
                and int(status['version'][2]) >= 2):
            return True
        else:
            return False

    def get_db_results(self, db, query):
        cursor = db.cursor()
        try:
            cursor.execute(query)
            results = float(cursor.fetchone()[1])
        except ValueError:
            cursor.execute(query)
            results = cursor.fetchone()[1]
        return results

    def calculate_per_s(self, command, result):
        if (not self.datastore.get(command)
                and self.datastore.get(command) != 0):
            self.checks_logger.debug(
                'mysql: Datastore unset for '
                '{}, storing for first time'.format(command))
            self.datastore[command] = result
            com_per_s = 0
        else:
            com_per_s = (result - self.datastore[command]) / 60
            if com_per_s < 0:
                com_per_s = 0
            self.datastore[command] = result
        return com_per_s

    def preliminaries(self):
        if ('MySQLServer' not in self.raw_config
                and 'mysql_server' not in self.raw_config['MySQLServer']
                or self.raw_config['MySQLServer']['mysql_server'] == ''
                or self.raw_config['MySQLServer']['mysql_user'] == ''
                or self.raw_config['MySQLServer']['mysql_pass'] == ''):
            self.checks_logger.debug('mysql: config not set')
            return False

        if not self.raw_config['MySQLServer'].get('mysql_port'):
            self.raw_config['MySQLServer']['mysql_port'] = "3306"

        self.checks_logger.debug('mysql: config set')

        try:
            import MySQLdb
        except ImportError:
            self.checks_logger.error('mysql: unable to import MySQLdb')
            return False

        # Note, code here doesn't really make sense. See what I copied.
        if not self.raw_config['MySQLServer'].get('mysql_port'):
            # Connect
            try:
                MySQLdb.connect(
                    host=self.raw_config['MySQLServer']['mysql_server'],
                    user=self.raw_config['MySQLServer']['mysql_user'],
                    passw=self.raw_config['MySQLServer']['mysql_pass'],
                    port=int(self.raw_config['MySQLServer']['mysql_port'])
                    )
            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    "mysql: MySQL connection error: {}".format(message))
                return False
        else:
            # Connect
            try:
                MySQLdb.connect(
                    host='localhost',
                    user=self.raw_config['MySQLServer']['mysql_user'],
                    passwd=self.raw_config['MySQLServer']['mysql_pass'],
                    port=int(self.raw_config['MySQLServer']['mysql_port']))
            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL connection error: {}'.format(message)
                    )
                return False
        return True

    def get_connection(self):
        try:
            # connection
            db = MySQLdb.connect(
                host=self.raw_config['MySQLServer']['mysql_server'],
                user=self.raw_config['MySQLServer']['mysql_user'],
                passwd=self.raw_config['MySQLServer']['mysql_pass'],
                port=int(self.raw_config['MySQLServer']['mysql_port'])
                )
            self.connection = db
            # note, how do I take into account the socket?
        except Exception:
            self.checks_logger.error(
                'Unable to connect to MySQL server {0}'
                ' - Exception: {1}'.format(
                    self.config_raw['MySQLServer']['mysql_server'],
                    traceback.format_exc())
                )
            return False
        return True

    def run(self):
        self.checks_logger.debug('mysql: started gathering data')
        if not self.preliminaries():
            return False

        if not self.get_connection():
            return False

        try:
            db = self.connection

            # setup
            status = {}

            # Get MySQL version
            try:
                self.checks_logger.debug('mysql: getting mysqlversion')

                cursor = db.cursor()
                cursor.execute('SELECT VERSION()')
                result = cursor.fetchone()

                version = result[0].split('-')
                # Case 31237. Might include a description e.g. 4.1.26-log.
                # See http://dev.mysql.com/doc/refman/4.1/en/
                # information-functions.html#function_version
                version = version[0].split('.')

                status['version'] = []

                for version_item in version:
                    number = re.match('([0-9]+)', version_item)
                    number = number.group(0)
                    status['version'].append(number)

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when getting version: {}'.format(
                        message)
                    )
                return False

            # get Uptime
            try:
                status['Uptime'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Uptime"'
                )
            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when getting Uptime = {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting Uptime - done')

            # Slow queries
            # Determine query depending on version. For 5.02 and above we
            # need the GLOBAL keyword (case 31015)
            # note, update with slow queries store. making it per second?
            # ask jordi about that.
            try:
                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Slow_queries"'
                else:
                    query = 'SHOW STATUS LIKE "Slow_queries'

                status['Slow queries'] = self.get_db_results(db, query)
            except MySQLdb.OperationalError as message:
                self.checks_logger(
                    'mysql: MySQL query error when '
                    'getting Slow_queries = {}'.format(
                        message)
                    )
                return False
            self.checks_logger.debug('mysql: getting Slow_queries - done')

            # QPS - Queries per second.
            try:
                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Queries"'
                else:
                    query = 'SHOW STATUS LIKE "Queries"'

                qps = self.calculate_per_s('qps', self.get_db_results(
                    db, query))
                status['Queries per second'] = qps

            except MySQLdb.OperationalError as message:
                self.checks_logger.debug(
                    'mysql: MySQL query error when getting QPS = {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting QPS - done')

            # Connection pool
            try:
                status['threads connected'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Threads_connected"')

                status['threads running'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Threads_running"')

                status['max connections'] = self.get_db_results(
                    db, 'SHOW VARIABLES LIKE "max_connections"')

                status['max used connections'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Max_used_connections"')

                status['Connection usage %'] = (
                    (status['threads running']/status['max connections'])*100
                )

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting Threads_connected: {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting connections - done')

            # Buffer pool
            try:

                status['buffer pool pages total'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_total"')

                status['buffer pool pages free'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_free"')

                status['buffer pool pages dirty'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_dirty"')

                status['buffer pool pages data'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Innodb_buffer_pool_pages_data"')

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting Buffer pool pages = {}'.format(
                        message)
                )
                return False
            self.checks_logger.debug('mysql: getting buffer pool - done')

            # Query cache items
            try:
                status['qcache hits'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_hits"')

                qcache_ps = self.calculate_per_s('qcache_ps', status[
                    'qcache hits'])
                status['qcache hits/s'] = qcache_ps

                status['qcache free memory'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_free_memory"')

                status['qcache not cached'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_not_cached"')

                status['qcache in cache'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Qcache_queries_in_cache"')

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting Qcache data = {}'.format(
                        message))
                return False

            self.checks_logger.debug('mysql: getting Qcache data - done')

            # writes, reads, transactions
            try:
                # writes
                insert = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_insert"')

                replace = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_replace"')

                update = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_update"')

                delete = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_delete"')

                writes = insert + replace + update + delete
                status['Writes/s'] = self.calculate_per_s('writes', writes)

                # reads
                select = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_select"')

                reads = select + status['qcache hits']
                status['Reads/s'] = self.calculate_per_s('reads', reads)

                # read write ratio
                try:
                    status['RW ratio'] = reads/writes
                except ZeroDivisionError:
                    status['RW ratio'] = 0

                # transactions
                commit = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_commit"')

                rollback = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Com_rollback"')

                transactions = commit + rollback
                status['Transactions/s'] = self.calculate_per_s(
                    'transactions', transactions)

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when getting writes,'
                    ' reads and transactions = {}'.format(
                        message)
                )
                return False

            # Aborted connections and clients
            try:
                status['aborted clients'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Aborted_clients"')

                status['aborted connects'] = self.get_db_results(
                    db, 'SHOW STATUS LIKE "Aborted_connects"')

            except MySQLdb.OperationalError as message:
                self.checks_logger.error(
                    'mysql: MySQL query error when '
                    'getting aborted items = {}'.format(
                        message)
                )
                return False

            self.checks_logger.debug(
                'mysql: getting aborted connections - done')

            # Replication - Seconds Behind Master
            secondsBehindMaster = None
            try:
                cursor = db.cursor(MySQLdb.cursors.DictCursor)
                cursor.execute('SHOW SLAVE STATUS')
                result = cursor.fetchone()

            except MySQLdb.OperationalError as message:

                self.mainLogger.error(
                    'getMySQLStatus: MySQL query error when '
                    'getting SHOW SLAVE STATUS = %s', message)
                result = None

            if result is not None:
                try:
                    # Handle the case when Seconds_Behind_Master is NULL
                    if result['Seconds_Behind_Master'] is None:
                        secondsBehindMaster = -1
                    else:
                        secondsBehindMaster = result['Seconds_Behind_Master']

                    self.mainLogger.debug(
                        'getMySQLStatus: '
                        'secondsBehindMaster = %s', secondsBehindMaster
                    )

                except IndexError as e:
                    self.mainLogger.debug(
                        'getMySQLStatus: secondsBehindMaster empty. %s', e
                    )

            else:
                self.mainLogger.debug(
                    'getMySQLStatus: secondsBehindMaster empty. Result = None.'
                )

            # Created temporary tables in memory and on disk
            try:
                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Created_tmp_tables"'
                else:
                    query = 'SHOW STATUS LIKE "Created_tmp_tables"'
                status['created tmp tables'] = self.get_db_results(
                    db, query)

                if self.version_is_above_5(status):
                    query = 'SHOW GLOBAL STATUS LIKE "Created_tmp_disk_tables"'
                else:
                    query = 'SHOW STATUS LIKE "Created_tmp_disk_tables"'
                status['created tmp tables on disk'] = self.get_db_results(
                    db, query)
{'fraction_non_alphanumeric': 0.0891858297078931, 'fraction_numerical': 0.003480422622747048, 'mean_word_length': 1.4112842799340626, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3773778', 'n_tokens_mistral': 8652, 'n_tokens_neox': 7836, 'n_words': 1920}