Compare commits

..

No commits in common. "master" and "1.4.0" have entirely different histories.

13 changed files with 201 additions and 1551 deletions

View File

@ -15,7 +15,7 @@ jobs:
checks: write
strategy:
matrix:
python-version: ["3.12"]
python-version: ["3.11"]
steps:
- uses: actions/checkout@v3

View File

@ -12,7 +12,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.12'
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip

1
.gitignore vendored
View File

@ -136,4 +136,3 @@ config.env
# Ignore ruff files
.ruff_cache
.DS_Store

View File

@ -1,4 +1,4 @@
FROM python:3.12-alpine
FROM python:3.11-alpine
# Install package
WORKDIR /code

View File

@ -1,39 +0,0 @@
name: prom-qb-alltime
services:
esanchezm:
cpu_shares: 90
command: []
deploy:
resources:
limits:
memory: 7943M
environment:
- QBITTORRENT_HOST=192.168.1.58
- QBITTORRENT_PASS=Cp3mMdP!#
- QBITTORRENT_PORT=8188
- QBITTORRENT_USER=noham
image: prom-qb-alltime
labels:
icon: https://raw.githubusercontent.com/esanchezm/prometheus-qbittorrent-exporter/master/logo.png
ports:
- target: 8000
published: "9101"
protocol: tcp
restart: unless-stopped
volumes: []
devices: []
cap_add: []
network_mode: bridge
privileged: false
container_name: ""
x-casaos:
author: self
category: self
hostname: ""
icon: https://raw.githubusercontent.com/esanchezm/prometheus-qbittorrent-exporter/master/logo.png
index: /metrics
port_map: "9101"
scheme: http
store_app_id: relaxed_albert
title:
custom: prom-qb-alltime

View File

@ -2,10 +2,8 @@
## Import
To import the dashboard into your grafana, download the [dashboard.json](https://raw.githubusercontent.com/nohamr/prometheus-qbittorrent-exporter/master/grafana/dashboard.json) file and import it into your server. Select your prometheus instance and that should be all.
To import the dashboard into your grafana, download the [dashboard.json](https://raw.githubusercontent.com/esanchezm/prometheus-qbittorrent-exporter/master/grafana/dashboard.json) file and import it into your server. Select your prometheus instance and that should be all.
## Screenshot
![](./screenshot1.png)
![](./screenshot2.png)
![](./screenshot3.png)
![](./screenshot.png)

File diff suppressed because it is too large Load Diff

BIN
grafana/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 KiB

View File

@ -1,13 +1,11 @@
import faulthandler
import logging
import os
# from dotenv import load_dotenv
# load_dotenv()
import signal
import sys
import time
from dataclasses import dataclass, field
from enum import Enum, auto
from enum import StrEnum, auto
from typing import Any, Iterable
from prometheus_client import start_http_server
@ -19,7 +17,8 @@ from qbittorrentapi import Client, TorrentStates
faulthandler.enable()
logger = logging.getLogger()
class MetricType(Enum):
class MetricType(StrEnum):
"""
Represents possible metric types (used in this project).
"""
@ -86,22 +85,20 @@ class QbittorrentMetricsCollector:
"""
Returns metrics about the state of the qbittorrent server.
"""
maindata: dict[str, Any] = {}
response: dict[str, Any] = {}
version: str = ""
# Fetch data from API
try:
maindata = self.client.sync_maindata()
response = self.client.transfer.info
version = self.client.app.version
except Exception as e:
logger.error(f"Couldn't get server info: {e}")
server_state = maindata.get('server_state', {})
return [
Metric(
name=f"{self.config['metrics_prefix']}_up",
value=bool(server_state),
value=bool(response),
labels={"version": version},
help_text=(
"Whether the qBittorrent server is answering requests from this"
@ -110,7 +107,7 @@ class QbittorrentMetricsCollector:
),
Metric(
name=f"{self.config['metrics_prefix']}_connected",
value=server_state.get("connection_status", "") == "connected",
value=response.get("connection_status", "") == "connected",
labels={}, # no labels in the example
help_text=(
"Whether the qBittorrent server is connected to the Bittorrent"
@ -119,7 +116,7 @@ class QbittorrentMetricsCollector:
),
Metric(
name=f"{self.config['metrics_prefix']}_firewalled",
value=server_state.get("connection_status", "") == "firewalled",
value=response.get("connection_status", "") == "firewalled",
labels={}, # no labels in the example
help_text=(
"Whether the qBittorrent server is connected to the Bittorrent"
@ -128,91 +125,24 @@ class QbittorrentMetricsCollector:
),
Metric(
name=f"{self.config['metrics_prefix']}_dht_nodes",
value=server_state.get("dht_nodes", 0),
value=response.get("dht_nodes", 0),
labels={}, # no labels in the example
help_text="Number of DHT nodes connected to.",
),
Metric(
name=f"{self.config['metrics_prefix']}_dl_info_data",
value=server_state.get("dl_info_data", 0),
value=response.get("dl_info_data", 0),
labels={}, # no labels in the example
help_text="Data downloaded since the server started, in bytes.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_up_info_data",
value=server_state.get("up_info_data", 0),
value=response.get("up_info_data", 0),
labels={}, # no labels in the example
help_text="Data uploaded since the server started, in bytes.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_alltime_dl",
value=server_state.get("alltime_dl", 0),
labels={}, # no labels in the example
help_text="Total data downloaded, in bytes.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_alltime_ul",
value=server_state.get("alltime_ul", 0),
labels={}, # no labels in the example
help_text="Total data uploaded, in bytes.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_total_peer_connections",
value=server_state.get("total_peer_connections", 0),
labels={}, # no labels in the example
help_text="total_peer_connections.",
metric_type=MetricType.COUNTER,
),
#### Disk metrics
Metric(
name=f"{self.config['metrics_prefix']}_write_cache_overload",
value=server_state.get("write_cache_overload", 0),
labels={}, # no labels in the example
help_text="write_cache_overload.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_read_cache_overload",
value=server_state.get("read_cache_overload", 0),
labels={}, # no labels in the example
help_text="read_cache_overload.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_read_cache_hits",
value=server_state.get("read_cache_hits", 0),
labels={}, # no labels in the example
help_text="read_cache_hits.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_average_time_queue",
value=server_state.get("average_time_queue", 0),
labels={}, # no labels in the example
help_text="average_time_queue.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_free_space_on_disk",
value=server_state.get("free_space_on_disk", 0),
labels={}, # no labels in the example
help_text="free_space_on_disk.",
metric_type=MetricType.COUNTER,
),
Metric(
name=f"{self.config['metrics_prefix']}_queued_io_jobs",
value=server_state.get("queued_io_jobs", 0),
labels={}, # no labels in the example
help_text="queued_io_jobs.",
metric_type=MetricType.COUNTER,
),
]
def _fetch_categories(self) -> dict:

View File

@ -270,20 +270,6 @@ class TestQbittorrentMetricsCollector(unittest.TestCase):
help_text="Data uploaded since the server started, in bytes.",
metric_type=MetricType.COUNTER,
),
Metric(
name="qbittorrent_alltime_dl",
value=0,
labels={}, # no labels in the example
help_text="Total data downloaded, in bytes.",
metric_type=MetricType.COUNTER,
),
Metric(
name="qbittorrent_alltime_ul",
value=0,
labels={}, # no labels in the example
help_text="Total data uploaded, in bytes.",
metric_type=MetricType.COUNTER,
),
]
metrics = self.collector._get_qbittorrent_status_metrics()