mirror of
https://github.com/NohamR/prometheus-qbittorrent-exporter.git
synced 2025-05-24 14:32:27 +00:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f4543b1969 | ||
![]() |
ff9e4cfabd | ||
![]() |
ec6af68f46 | ||
![]() |
6b9c2e5a50 | ||
![]() |
2602383484 | ||
![]() |
62952917be | ||
![]() |
c10515dc08 |
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
checks: write
|
checks: write
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.11"]
|
python-version: ["3.12"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
2
.github/workflows/pythonpublish.yml
vendored
2
.github/workflows/pythonpublish.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.12'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -136,3 +136,4 @@ config.env
|
|||||||
|
|
||||||
# Ignore ruff files
|
# Ignore ruff files
|
||||||
.ruff_cache
|
.ruff_cache
|
||||||
|
.DS_Store
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM python:3.11-alpine
|
FROM python:3.12-alpine
|
||||||
|
|
||||||
# Install package
|
# Install package
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
|
39
docker-compose.yml
Normal file
39
docker-compose.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
## Import
|
## Import
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|

|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 208 KiB |
BIN
grafana/screenshot1.png
Normal file
BIN
grafana/screenshot1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 343 KiB |
BIN
grafana/screenshot2.png
Normal file
BIN
grafana/screenshot2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 701 KiB |
BIN
grafana/screenshot3.png
Normal file
BIN
grafana/screenshot3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 420 KiB |
@ -1,11 +1,13 @@
|
|||||||
import faulthandler
|
import faulthandler
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
# from dotenv import load_dotenv
|
||||||
|
# load_dotenv()
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from enum import StrEnum, auto
|
from enum import Enum, auto
|
||||||
from typing import Any, Iterable
|
from typing import Any, Iterable
|
||||||
|
|
||||||
from prometheus_client import start_http_server
|
from prometheus_client import start_http_server
|
||||||
@ -17,8 +19,7 @@ from qbittorrentapi import Client, TorrentStates
|
|||||||
faulthandler.enable()
|
faulthandler.enable()
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class MetricType(Enum):
|
||||||
class MetricType(StrEnum):
|
|
||||||
"""
|
"""
|
||||||
Represents possible metric types (used in this project).
|
Represents possible metric types (used in this project).
|
||||||
"""
|
"""
|
||||||
@ -85,20 +86,22 @@ class QbittorrentMetricsCollector:
|
|||||||
"""
|
"""
|
||||||
Returns metrics about the state of the qbittorrent server.
|
Returns metrics about the state of the qbittorrent server.
|
||||||
"""
|
"""
|
||||||
response: dict[str, Any] = {}
|
maindata: dict[str, Any] = {}
|
||||||
version: str = ""
|
version: str = ""
|
||||||
|
|
||||||
# Fetch data from API
|
# Fetch data from API
|
||||||
try:
|
try:
|
||||||
response = self.client.transfer.info
|
maindata = self.client.sync_maindata()
|
||||||
version = self.client.app.version
|
version = self.client.app.version
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Couldn't get server info: {e}")
|
logger.error(f"Couldn't get server info: {e}")
|
||||||
|
|
||||||
|
server_state = maindata.get('server_state', {})
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Metric(
|
Metric(
|
||||||
name=f"{self.config['metrics_prefix']}_up",
|
name=f"{self.config['metrics_prefix']}_up",
|
||||||
value=bool(response),
|
value=bool(server_state),
|
||||||
labels={"version": version},
|
labels={"version": version},
|
||||||
help_text=(
|
help_text=(
|
||||||
"Whether the qBittorrent server is answering requests from this"
|
"Whether the qBittorrent server is answering requests from this"
|
||||||
@ -107,7 +110,7 @@ class QbittorrentMetricsCollector:
|
|||||||
),
|
),
|
||||||
Metric(
|
Metric(
|
||||||
name=f"{self.config['metrics_prefix']}_connected",
|
name=f"{self.config['metrics_prefix']}_connected",
|
||||||
value=response.get("connection_status", "") == "connected",
|
value=server_state.get("connection_status", "") == "connected",
|
||||||
labels={}, # no labels in the example
|
labels={}, # no labels in the example
|
||||||
help_text=(
|
help_text=(
|
||||||
"Whether the qBittorrent server is connected to the Bittorrent"
|
"Whether the qBittorrent server is connected to the Bittorrent"
|
||||||
@ -116,7 +119,7 @@ class QbittorrentMetricsCollector:
|
|||||||
),
|
),
|
||||||
Metric(
|
Metric(
|
||||||
name=f"{self.config['metrics_prefix']}_firewalled",
|
name=f"{self.config['metrics_prefix']}_firewalled",
|
||||||
value=response.get("connection_status", "") == "firewalled",
|
value=server_state.get("connection_status", "") == "firewalled",
|
||||||
labels={}, # no labels in the example
|
labels={}, # no labels in the example
|
||||||
help_text=(
|
help_text=(
|
||||||
"Whether the qBittorrent server is connected to the Bittorrent"
|
"Whether the qBittorrent server is connected to the Bittorrent"
|
||||||
@ -125,24 +128,91 @@ class QbittorrentMetricsCollector:
|
|||||||
),
|
),
|
||||||
Metric(
|
Metric(
|
||||||
name=f"{self.config['metrics_prefix']}_dht_nodes",
|
name=f"{self.config['metrics_prefix']}_dht_nodes",
|
||||||
value=response.get("dht_nodes", 0),
|
value=server_state.get("dht_nodes", 0),
|
||||||
labels={}, # no labels in the example
|
labels={}, # no labels in the example
|
||||||
help_text="Number of DHT nodes connected to.",
|
help_text="Number of DHT nodes connected to.",
|
||||||
),
|
),
|
||||||
Metric(
|
Metric(
|
||||||
name=f"{self.config['metrics_prefix']}_dl_info_data",
|
name=f"{self.config['metrics_prefix']}_dl_info_data",
|
||||||
value=response.get("dl_info_data", 0),
|
value=server_state.get("dl_info_data", 0),
|
||||||
labels={}, # no labels in the example
|
labels={}, # no labels in the example
|
||||||
help_text="Data downloaded since the server started, in bytes.",
|
help_text="Data downloaded since the server started, in bytes.",
|
||||||
metric_type=MetricType.COUNTER,
|
metric_type=MetricType.COUNTER,
|
||||||
),
|
),
|
||||||
Metric(
|
Metric(
|
||||||
name=f"{self.config['metrics_prefix']}_up_info_data",
|
name=f"{self.config['metrics_prefix']}_up_info_data",
|
||||||
value=response.get("up_info_data", 0),
|
value=server_state.get("up_info_data", 0),
|
||||||
labels={}, # no labels in the example
|
labels={}, # no labels in the example
|
||||||
help_text="Data uploaded since the server started, in bytes.",
|
help_text="Data uploaded since the server started, in bytes.",
|
||||||
metric_type=MetricType.COUNTER,
|
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:
|
def _fetch_categories(self) -> dict:
|
||||||
|
@ -270,6 +270,20 @@ class TestQbittorrentMetricsCollector(unittest.TestCase):
|
|||||||
help_text="Data uploaded since the server started, in bytes.",
|
help_text="Data uploaded since the server started, in bytes.",
|
||||||
metric_type=MetricType.COUNTER,
|
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()
|
metrics = self.collector._get_qbittorrent_status_metrics()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user