diff --git a/dockerfiles/nodemapper.py b/dockerfiles/nodemapper.py index cda853c..001e213 100644 --- a/dockerfiles/nodemapper.py +++ b/dockerfiles/nodemapper.py @@ -1,17 +1,18 @@ #!/usr/bin/env python3 """ -This is a lightweight web service which will retrieve a peer list -from a Monero node, determine GeoIP information, and return +This is a lightweight web service which will retrieve a peer list +from a Monero node, determine GeoIP information, and return a list of metrics in a Prometheus compatible structure. Use it to start plotting maps of active node connections. """ -import socket, struct from os import environ as env +from typing import Union import requests import geoip2.database +from geoip2.models import City from geoip2.errors import AddressNotFoundError from flask import Flask, make_response @@ -23,42 +24,52 @@ NODE_HOST = env.get('NODE_HOST', 'monerod') NODE_PORT = env.get('NODE_PORT', 18083) -def get_geoip(ip): - """Takes an IP address and determines GeoIP data""" +def get_geoip(ip) -> Union[City, None]: + """Takes an IP address and determines GeoIP data if possible""" try: with geoip2.database.Reader("./geoip.mmdb") as reader: return reader.city(ip) except AddressNotFoundError: + print(f"{ip} not found in GeoIP database") + return None + except Exception as e: + print(f"Error getting GeoIP data for {ip}: {e}") + return None + +def generate_prometheus_line(ip, status) -> Union[str, None]: + """Generate a Prometheus formatted line for a given peer given an IP and status with GeoIP data included""" + geo = get_geoip(ip) + if geo is None or 'en' not in geo.continent.names: return None + geostr = 'geoip{{latitude="{lat}", longitude="{lon}", country_code="{country_code}", country_name="{country_name}", status="{status}"}} 1' + # print(f"Found GeoIP for {ip}: {geostr}") + return geostr.format( + lat=geo.location.latitude, + lon=geo.location.longitude, + country_code=geo.continent.code, + country_name=geo.continent.names['en'], + status=status + ) @app.route("/metrics") def nodes(): - """Return all nodes""" - peers = list() + """Get peer list from monerod and generate Prometheus endpoint output""" + peers_found = list() + prom_lines = list() peer_list = requests.get(f'http://{NODE_HOST}:{NODE_PORT}/get_peer_list').json() - def add_peer(host, status): - geo = get_geoip(host) - if geo is None: - return - - geostr = 'geoip{{latitude="{lat}", longitude="{lon}", country_code="{country_code}", country_name="{country_name}", status="{status}"}} 1' - if geostr not in peers: - if 'en' in geo.continent.names: - peers.append(geostr.format( - lat=geo.location.latitude, - lon=geo.location.longitude, - country_code=geo.continent.code, - country_name=geo.continent.names['en'], - status=status - )) + if not peer_list: + return "" for peer in peer_list['gray_list']: - if peer.get('host'): - add_peer(peer['host'], 'gray') + peer['status'] = 'gray' + peers_found.append(peer) for peer in peer_list['white_list']: - if peer.get('host'): - add_peer(peer['host'], 'white') - data = '\n'.join(peers) - response = make_response(data, 200) + peer['status'] = 'white' + peers_found.append(peer) + for peer in peers_found: + prom = generate_prometheus_line(peer['host'], peer['status']) + if prom: + prom_lines.append(prom) + response = make_response('\n'.join(prom_lines), 200) response.mimetype = "text/plain" return response diff --git a/release.sh b/release.sh index 95a1beb..2b7bdf6 100644 --- a/release.sh +++ b/release.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Build and tag container images for each service based upon passed argument; monerod, nodemapper, or exporter +# Build and tag container images for each service based upon passed argument; monerod, nodemapper, or exporter # All are manually tagged since some do not update as frequently as others. Bump the script # to bump the image stored on Dockerhub. @@ -12,7 +12,7 @@ MONEROD_VERSION=v0.18.3.2 MONEROD_BASE=${DH_USER}/monerod EXPORTER_VERSION=1.0.0 EXPORTER_BASE=${DH_USER}/exporter -NODEMAPPER_VERSION=1.0.1 +NODEMAPPER_VERSION=1.0.2 NODEMAPPER_BASE=${DH_USER}/nodemapper if [[ "${IMAGE}" == "nodemapper" ]]