Replace transmission-exporter with homegrown Python exporter #283
2 changed files with 16 additions and 30 deletions
Address PR feedback: uv run --script, latest Python/Alpine, serve_forever
- Use #!/usr/bin/env -S uv run --script shebang with PEP 723 metadata - Drop venv/pip multi-stage build; uv handles deps at runtime - Upgrade to python:3.13-alpine3.23 - Unpin dependency versions (no upper bounds) - Replace threading.Event().wait() with wsgiref serve_forever() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
commit
9c1b4a9a23
|
|
@ -1,31 +1,21 @@
|
|||
# Transmission Prometheus exporter - collect-on-scrape, no polling loop
|
||||
# Two-stage build: uv installs deps into venv, runtime is minimal Alpine
|
||||
# uv run --script handles dependency resolution at runtime
|
||||
|
||||
ARG CONTAINER_APP_VERSION=1.0.0
|
||||
|
||||
FROM python:3.12-alpine3.22 AS base
|
||||
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
COPY exporter.py .
|
||||
RUN uv venv .venv && \
|
||||
uv pip install --python .venv/bin/python \
|
||||
"prometheus-client>=0.24,<1.0" \
|
||||
"transmission-rpc>=7.0,<8.0" && \
|
||||
find /app/.venv \( -type d -a -name test -o -name tests \) \
|
||||
-o \( -type f -a -name '*.pyc' -o -name '*.pyo' \) -exec rm -rf '{}' \+
|
||||
|
||||
FROM base
|
||||
FROM python:3.13-alpine3.23
|
||||
|
||||
LABEL org.opencontainers.image.title="Transmission Exporter"
|
||||
LABEL org.opencontainers.image.description="Prometheus exporter for Transmission BitTorrent client"
|
||||
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
ENV UV_CACHE_DIR=/tmp/uv-cache
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app /app
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
COPY exporter.py .
|
||||
|
||||
EXPOSE 19091
|
||||
USER 65534:65534
|
||||
CMD ["python", "-u", "/app/exporter.py"]
|
||||
CMD ["uv", "run", "--script", "/app/exporter.py"]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# requires-python = ">=3.13"
|
||||
# dependencies = [
|
||||
# "prometheus-client>=0.24,<1.0",
|
||||
# "transmission-rpc>=7.0,<8.0",
|
||||
# "prometheus-client",
|
||||
# "transmission-rpc",
|
||||
# ]
|
||||
# ///
|
||||
"""Minimal Prometheus exporter for Transmission, using collect-on-scrape."""
|
||||
|
|
@ -10,8 +11,9 @@
|
|||
import os
|
||||
import sys
|
||||
import urllib.parse
|
||||
from wsgiref.simple_server import make_server
|
||||
|
||||
from prometheus_client import start_http_server
|
||||
from prometheus_client import make_wsgi_app
|
||||
from prometheus_client.core import REGISTRY, GaugeMetricFamily
|
||||
from transmission_rpc import Client
|
||||
|
||||
|
|
@ -48,7 +50,6 @@ class TransmissionCollector:
|
|||
print(f"Error collecting metrics: {e}", file=sys.stderr)
|
||||
return
|
||||
|
||||
# Session stats
|
||||
yield _gauge(
|
||||
"transmission_session_stats_download_speed_bytes",
|
||||
"Current download speed in bytes/s",
|
||||
|
|
@ -86,7 +87,6 @@ class TransmissionCollector:
|
|||
uploaded.add_metric(["cumulative"], session.cumulative_stats.uploaded_bytes)
|
||||
yield uploaded
|
||||
|
||||
# Per-torrent metrics
|
||||
t_download = GaugeMetricFamily(
|
||||
"transmission_torrent_download_bytes",
|
||||
"Torrent total downloaded bytes",
|
||||
|
|
@ -142,12 +142,8 @@ def main():
|
|||
REGISTRY.register(TransmissionCollector(client_kwargs))
|
||||
|
||||
print(f"Listening on :{port}, scraping {addr}")
|
||||
start_http_server(port)
|
||||
|
||||
# Block forever
|
||||
import threading
|
||||
|
||||
threading.Event().wait()
|
||||
httpd = make_server("", port, make_wsgi_app())
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue