diff --git a/README.md b/README.md index 7bba8e7..3d7848b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![PyPI](https://img.shields.io/pypi/v/connectbox-prometheus.svg)](https://pypi.org/project/connectbox-prometheus/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -A [Prometheus](https://prometheus.io/) exporter for monitoring Compal CH7465LG cable modems. These are sold under the name "Connect Box" by Unitymedia in Germany, Ziggo in the Netherlands and UPC in Switzerland/Austria. Or as "Virgin Media Super Hub 3" by Virgin Media. +A [Prometheus](https://prometheus.io/) exporter for monitoring Compal CH7465LG cable modems. These are sold under the name "Connect Box" by Unitymedia in Germany, Ziggo in the Netherlands and UPC in Switzerland/Austria/Poland. Or as "Virgin Media Super Hub 3" by Virgin Media. Makes thorough use of [compal_CH7465LG_py](https://github.com/ties/compal_CH7465LG_py) by [@ties](https://github.com/ties/) (thanks!). @@ -25,7 +25,7 @@ ip_address: 192.168.0.1 password: WhatEverYourPasswordIs ``` -Then run `connectbox_exporter path/to/your/config.yml` +Then run `connectbox_exporter path/to/your/config.yml` . ## Prometheus Configuration Add the following to your `prometheus.yml`: diff --git a/connectbox_exporter/connectbox_exporter.py b/connectbox_exporter/connectbox_exporter.py index 4cce6e5..9d03c64 100755 --- a/connectbox_exporter/connectbox_exporter.py +++ b/connectbox_exporter/connectbox_exporter.py @@ -1,10 +1,9 @@ import logging -import sys import threading import time import click -from compal import Compal +import compal from prometheus_client import CollectorRegistry, MetricsHandler from prometheus_client.exposition import _ThreadingSimpleServer from prometheus_client.metrics_core import GaugeMetricFamily @@ -18,6 +17,7 @@ PORT, TIMEOUT_SECONDS, ) +from connectbox_exporter.logger import get_logger, VerboseLogger from connectbox_exporter.xml2metric import ( CmStateExtractor, LanUserExtractor, @@ -29,7 +29,7 @@ class ConnectBoxCollector(object): def __init__( - self, logger: logging.Logger, ip_address: str, password: str, timeout: float + self, logger: VerboseLogger, ip_address: str, password: str, timeout: float ): self.logger = logger self.ip_address = ip_address @@ -50,7 +50,7 @@ def collect(self): # attempt login try: self.logger.debug("Logging in at " + self.ip_address) - connectbox = Compal( + connectbox = compal.Compal( self.ip_address, key=self.password, timeout=self.timeout ) connectbox.login() @@ -65,8 +65,12 @@ def collect(self): for extractor in self.metric_extractors: contents = [] for fun in extractor.functions: - self.logger.debug(f"Querying fun=" + str(fun) + "...") - contents.append(connectbox.xml_getter(fun, {}).content) + self.logger.debug(f"Querying fun={fun}...") + raw_xml = connectbox.xml_getter(fun, {}).content + self.logger.verbose( + f"Raw XML response for fun={fun}:\n{raw_xml.decode()}" + ) + contents.append(raw_xml) yield from extractor.extract(contents) except Exception as e: # bail out on any error @@ -100,22 +104,20 @@ def collect(self): @click.command() @click.argument("config_file", type=click.Path(exists=True, dir_okay=False)) -@click.option("-v", "--verbose", help="Print more log messages", is_flag=True) +@click.option( + "-v", + "--verbose", + help="Log more messages. Multiple -v increase verbosity.", + count=True, +) def main(config_file, verbose): """ Launch the exporter using a YAML config file. """ - # logging setup - log_level = logging.DEBUG if verbose else logging.INFO - logger = logging.getLogger("connectbox_exporter") - logger.setLevel(log_level) - handler = logging.StreamHandler(sys.stdout) - handler.setLevel(log_level) - formatter = logging.Formatter( - "%(asctime)s - %(name)s - %(levelname)s - %(message)s" - ) - handler.setFormatter(formatter) - logger.addHandler(handler) + + # hush the logger from the compal library and use our own custom logger + compal.LOGGER.setLevel(logging.WARNING) + logger = get_logger(verbose) # load user and merge with defaults config = load_config(config_file) diff --git a/connectbox_exporter/logger.py b/connectbox_exporter/logger.py new file mode 100644 index 0000000..7199869 --- /dev/null +++ b/connectbox_exporter/logger.py @@ -0,0 +1,42 @@ +from logging import Logger, NOTSET, addLevelName, INFO, DEBUG, StreamHandler, Formatter +import sys + +VERBOSE = 5 + + +class VerboseLogger(Logger): + """ + Logger with custom log level VERBOSE which is lower than DEBUG. + """ + + def __init__(self, name, level=NOTSET): + super().__init__(name, level) + addLevelName(VERBOSE, "VERBOSE") + + def verbose(self, msg, *args, **kwargs): + if self.isEnabledFor(VERBOSE): + self._log(VERBOSE, msg, args, **kwargs) + + +def get_logger(verbosity: int) -> VerboseLogger: + """ + Get logger object which logs to stdout with given verbosity. + :param verbosity: logs INFO if 0, DEBUG if 1 and VERBOSE if >1 + :return: + """ + if verbosity <= 0: + log_level = INFO + elif verbosity == 1: + log_level = DEBUG + else: + log_level = VERBOSE + + logger = VerboseLogger("connectbox_exporter") + logger.setLevel(log_level) + handler = StreamHandler(sys.stdout) + handler.setLevel(log_level) + formatter = Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + handler.setFormatter(formatter) + logger.addHandler(handler) + + return logger diff --git a/setup.py b/setup.py index 48b6347..d19a8bf 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="connectbox-prometheus", - version="0.2.0", + version="0.2.1", author="Michael Bugert", author_email="git@mbugert.de", description='Prometheus exporter for Compal CH7465LG cable modems, commonly sold as "Connect Box"',