diff --git a/container_exporter.py b/container_exporter.py index 25fb2c4..cad0bb0 100755 --- a/container_exporter.py +++ b/container_exporter.py @@ -42,6 +42,8 @@ async def lifespan(app: FastAPI): counter_net_rx = Gauge("cxp_network_rx_bytes_total", "Total bytes received over network", ['container_name']) counter_net_tx = Gauge("cxp_network_tx_bytes_total", "Total bytes sent over network", ['container_name']) +counter_running_containers_total = Gauge("cxp_running_cotainers_total", "Total number of running containers") + async def get_containers(all=False) -> list[DockerContainer]: return await docker_client.containers.list(all=all) @@ -56,9 +58,12 @@ def update_container_status(running_containers:list[DockerContainer]): gauge_container_status.labels(container_name=name).set(2) # Async metrics gathering -async def container_stats( running_containers: list[DockerContainer]): +async def container_stats(running_containers: list[DockerContainer]): all_stats = await stat.get_containers_stats(running_containers) + running_containers_total = len(running_containers) + counter_running_containers_total.set(running_containers_total) + for stats in all_stats: name = stats[0].get('name', stats[0].get('id', 'Unkown').lstrip("/")).lstrip("/") @@ -80,7 +85,9 @@ async def container_stats( running_containers: list[DockerContainer]): ] # Metrics we want to always keep, and set to 0 instead -persistent_metrics: list[Gauge] = [gauge_container_status] +persistent_metrics: list[Gauge] = [ + gauge_container_status, counter_running_containers_total +] @app.get("/") @@ -115,4 +122,4 @@ async def metrics(): ) except Exception as e: logger.error("Error running metrics collection: %s", e, exc_info=settings.CONTAINER_EXPORTER_DEBUG) - return PlainTextResponse(f"Error running metrics collection: {str(e)}", status_code=500) \ No newline at end of file + return PlainTextResponse(f"Error running metrics collection: {str(e)}", status_code=500) diff --git a/utils/metrics.py b/utils/metrics.py index 2c8c47b..6f6d1d0 100644 --- a/utils/metrics.py +++ b/utils/metrics.py @@ -14,6 +14,8 @@ def prune_stale_metrics(active_names: Iterable[str], prunable_metrics: list[Prom active_set = set(active_names) for metric in prunable_metrics: + if not hasattr(metric, '_metrics'): + continue for labels in metric._metrics: name = labels[0] if name not in active_set: @@ -25,6 +27,8 @@ def prune_stale_metrics(active_names: Iterable[str], prunable_metrics: list[Prom metric.clear() for metric in persistent_metrics: + if not hasattr(metric, '_metrics'): + continue for labels in list(metric._metrics): name = labels[0] if name not in active_set: @@ -37,4 +41,4 @@ def normalize_name(raw_names: list[str], fallback_id: str) -> str: """ if raw_names and isinstance(raw_names, list) and raw_names[0]: return raw_names[0].lstrip("/") - return fallback_id[:12] \ No newline at end of file + return fallback_id[:12]