diff --git a/MANIFEST.in b/MANIFEST.in index cc0d116..59b9904 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ -include LICENSE \ No newline at end of file +include LICENSE +include config.yml \ No newline at end of file diff --git a/README.md b/README.md index 0273113..4d88d65 100644 --- a/README.md +++ b/README.md @@ -9,29 +9,34 @@ A [Prometheus](https://prometheus.io/) exporter for the modem connection status Makes thorough use of [python-connect-box](https://github.com/fabaff/python-connect-box) by [@fabaff](https://github.com/fabaff) (thanks!). ## Installation -You need python3.6 or higher. Run: +You need python3.6 or higher. On your Prometheus server host, install the exporter via -`$ pip3 install connectbox-prometheus` +`pip3 install connectbox-prometheus` ## Usage -`./connectbox_exporter --pw YOUR_CONNECTBOX_PASSWORD` +This exporter queries exactly one Connect Box as a remote target. +To get started, modify `config.yml` from this repository or create your own with the following content: +```yaml +# Connect Box IP address +ip_address: 192.168.0.1 + +# Connect Box web interface password +password: WhatEverYourPasswordIs + +# port on which this exporter exposes metrics +exporter_port: 9705 +``` -To see all options, run `./connectbox_exporter --help` +Then run `connectbox_exporter path/to/your/config.yml` ## Prometheus Configuration +Add the following to your `prometheus.yml`: ```yaml scrape_configs: - job_name: 'connectbox' static_configs: - targets: - - 192.168.0.1 # IP address of your Connect Box - relabel_configs: - - source_labels: [__address__] - target_label: __param_target - - source_labels: [__param_target] - target_label: instance - - target_label: __address__ - replacement: 127.0.0.1:9705 # The exporter's real hostname:port. + - localhost:9705 ``` ## Exported Metrics @@ -40,16 +45,16 @@ scrape_configs: | `connectbox_up` | Connect Box reachable yes/no | | `connectbox_num_devices` | Number of connected devices | | `connectbox_downstream_frequency_hz` | Downstream channel frequency | -| `connectbox_downstream_power_level_dbmv` | Downstream channel power level | +| `connectbox_downstream_power_level_dbmv` | Downstream channel power level in dBmV | | `connectbox_downstream_modulation_qam` | Downstream channel modulation | -| `connectbox_downstream_signal_to_noise_db` | Downstream channel signal-to-noise | +| `connectbox_downstream_signal_to_noise_db` | Downstream channel signal-to-noise in dB | | `connectbox_downstream_errors_pre_rs_total` | Downstream channel errors before Reed-Solomon correction | | `connectbox_downstream_errors_post_rs_total` | Downstream channel errors after Reed-Solomon correction | | `connectbox_downstream_qam_locked` | Downstream channel QAM lock status | | `connectbox_downstream_freq_locked` | Downstream channel frequency lock status | | `connectbox_downstream_mpeg_locked` | Downstream channel MPEG lock status | | `connectbox_upstream_frequency_hz` | Upstream channel frequency | -| `connectbox_upstream_power_level_dbmv` | Upstream channel power level | +| `connectbox_upstream_power_level_dbmv` | Upstream channel power level in dBmV | | `connectbox_upstream_symbol_rate_ksps` | Upstream channel symbol rate | | `connectbox_upstream_modulation_qam` | Upstream channel modulation | | `connectbox_upstream_timeouts_total` | Upstream channel timeouts | \ No newline at end of file diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..62ff3cc --- /dev/null +++ b/config.yml @@ -0,0 +1,8 @@ +# Connect Box IP address +ip_address: 192.168.0.1 + +# Connect Box web interface password +password: WhatEverYourPasswordIs + +# port on which this exporter exposes metrics +exporter_port: 9705 \ No newline at end of file diff --git a/connectbox_exporter/__main__.py b/connectbox_exporter/__main__.py deleted file mode 100644 index 5f15be1..0000000 --- a/connectbox_exporter/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .connectbox_exporter import main - -main() diff --git a/connectbox_exporter/connectbox_exporter.py b/connectbox_exporter/connectbox_exporter.py old mode 100644 new mode 100755 index bb2be0b..6c65886 --- a/connectbox_exporter/connectbox_exporter.py +++ b/connectbox_exporter/connectbox_exporter.py @@ -13,12 +13,13 @@ ) from prometheus_client import start_http_server, CollectorRegistry from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily +from ruamel.yaml import YAML class ConnectBoxCollector(object): - def __init__(self, logger: logging.Logger, host: str, password: str): + def __init__(self, logger: logging.Logger, ip_address: str, password: str): self.logger = logger - self.host = host + self.ip_address = ip_address self.password = password def collect(self): @@ -176,7 +177,7 @@ def collect(self): def _retrieve_values(self) -> Optional[Tuple]: async def retrieve(): async with aiohttp.ClientSession() as session: - client = ConnectBox(session, self.password, host=self.host) + client = ConnectBox(session, self.password, host=self.ip_address) try: await client.async_get_downstream() await client.async_get_upstream() @@ -196,25 +197,16 @@ async def retrieve(): @click.command() -@click.option( - "--port", - default=9705, - help="Port where this exporter serves metrics", - type=int, - show_default=True, -) -@click.option("--host", default="192.168.0.1", help="Connect Box IP address", type=str) -@click.option( - "--pw", help="Connect Box web interface password", required=True, type=str -) +@click.argument("config_file", type=click.Path(exists=True, dir_okay=False)) @click.option("-v", "--verbose", help="Print more log messages", is_flag=True) -def main(port, host, pw, verbose): +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(__name__) + logger = logging.getLogger(__file__) logger.setLevel(log_level) - - # log to stdout handler = logging.StreamHandler(sys.stdout) handler.setLevel(log_level) formatter = logging.Formatter( @@ -223,12 +215,31 @@ def main(port, host, pw, verbose): handler.setFormatter(formatter) logger.addHandler(handler) + # load YAML config + IP_ADDRESS = "ip_address" + PASSWORD = "password" + EXPORTER_PORT = "exporter_port" + yaml = YAML() + with open(config_file) as f: + config = yaml.load(f) + if not all(key in config for key in [IP_ADDRESS, PASSWORD, EXPORTER_PORT]): + logger.error( + "Configuration YAML is missing entries. Please see README.md for an example." + ) + sys.exit(1) + # fire up collector reg = CollectorRegistry() - reg.register(ConnectBoxCollector(logger, host=host, password=pw)) - start_http_server(port, registry=reg) + reg.register( + ConnectBoxCollector( + logger, ip_address=config[IP_ADDRESS], password=config[PASSWORD] + ) + ) + start_http_server(config[EXPORTER_PORT], registry=reg) - logger.info("Exporter started.") + logger.info( + f"Exporter running at http://localhost:{config[EXPORTER_PORT]}, querying {config[IP_ADDRESS]}" + ) # stall the main thread indefinitely while True: diff --git a/requirements.txt b/requirements.txt index 40f9125..756145b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ black==19.10b0 click==7.1.1 connect-box==0.2.5 -prometheus-client==0.7.1 \ No newline at end of file +prometheus-client==0.7.1 +ruamel.yaml==0.16.10 \ No newline at end of file diff --git a/connectbox_exporter_wrapper.py b/run.py old mode 100755 new mode 100644 similarity index 100% rename from connectbox_exporter_wrapper.py rename to run.py