Mini Shell

Direktori : /opt/imh-python/lib/python3.9/site-packages/ngxstats/
Upload File :
Current File : //opt/imh-python/lib/python3.9/site-packages/ngxstats/influx.py

# vim: set ts=4 sw=4 expandtab syntax=python:
"""

ngxstats.influx
Realtime Nginx stats aggregation tool
InfluxDB aggregate stats writer process

Copyright (c) 2019-2020 InMotion Hosting, Inc.
https://www.inmotionhosting.com/

@author J. Hipps <jacobh@inmotionhosting.com>

"""

import os
import logging
import multiprocessing
import platform
from urllib.parse import urlparse
import urllib3

import arrow
import toml
from influxdb import InfluxDBClient
from setproctitle import setproctitle

from ngxstats.util import gconf, check_alive

# disable warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

logger = logging.getLogger('ngxstats')


def start(inq):
    """
    InfluxDB writer
    """
    ppid = os.getppid()
    logger.info(
        "influx: subservice started. pid = %d / ppid = %d",
        multiprocessing.current_process().pid,
        ppid,
    )
    try:
        setproctitle("ngxstats: influx")
    except Exception:
        pass

    if gconf.influx_use_telegraf_config is True:
        tconf = get_telegraf_config()
    else:
        tconf = {
            'database': gconf.influx_database,
            'host': gconf.influx_host,
            'port': gconf.influx_port,
            'username': gconf.influx_username,
            'password': gconf.influx_password,
            'ssl': gconf.influx_ssl,
            'verify_ssl': gconf.influx_verify_ssl,
        }

    # Connect to InfluxDB
    try:
        flux = InfluxDBClient(**tconf)
    except Exception as e:
        logger.error("Failed to connect to InfluxDB: %s", str(e))
        return None

    # Main processing loop
    while True:
        # Check if master is still alive
        if not check_alive(ppid):
            logger.info("influx: master %d has died. aborting.", ppid)
            os._exit(0)  # pylint: disable=protected-access

        # Grab the next batch, hot off the queue
        # This will block for 1 second, check if the parent is alive,
        # then block again until it receives a measurement
        try:
            tbatch = inq.get(1)
            logger.debug("influx: received new measurement")
        except multiprocessing.TimeoutError:
            continue

        # Construct query
        jbody = [
            {
                'measurement': gconf.influx_measurement,
                'tags': {
                    'host': platform.node(),
                },
                'time': arrow.get().isoformat(),
                'fields': tbatch,
            }
        ]
        logger.debug("influx: aggro jbody = %s", jbody)

        # Send to InfluxDB server
        try:
            flux.write_points(jbody)
            logger.debug("influx: wrote measurement to server")
        except Exception as e:
            logger.error("influx: write_points failed: %s", str(e))


def get_telegraf_config(confpath='/etc/telegraf/telegraf.conf'):
    """
    Determine InfluxDB server and credentials from local Telegraf config
    """
    oconf = {}
    try:
        with open(confpath, encoding='utf-8') as f:
            tconf = toml.load(f)
    except Exception as e:
        logger.debug("Unable to read local Telegraf configuration: %s", e)
        return None

    try:
        # Determine InfluxDB server
        sraw = tconf['outputs']['influxdb'][0]['urls']
        if isinstance(sraw, list):
            dburl = urlparse(sraw[0])
        else:
            dburl = urlparse(sraw)

        oconf['host'] = dburl.hostname
        oconf['port'] = dburl.port
        oconf['ssl'] = dburl.scheme == 'https'
        oconf['verify_ssl'] = bool(
            tconf['outputs']['influxdb'][0].get('insecure_skip_verify', False)
        )

        # Database, User, Password
        oconf['database'] = tconf['outputs']['influxdb'][0]['database']
        oconf['username'] = tconf['outputs']['influxdb'][0]['username']
        oconf['password'] = tconf['outputs']['influxdb'][0]['password']
    except Exception as e:
        logger.error("Failed to parse Telegraf config: %s", str(e))
        return None
    return oconf

Zerion Mini Shell 1.0