mirror of
https://github.com/NohamR/prometheus-qbittorrent-exporter.git
synced 2026-01-10 16:18:38 +00:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c885b5fa0 | ||
|
|
039f7a7ef4 | ||
|
|
8bdaa48c48 | ||
|
|
e8dd24f731 | ||
|
|
12dcad10d5 | ||
|
|
597307c230 | ||
|
|
a25005b6a0 | ||
|
|
cfe62f8115 | ||
|
|
b5d20e3fe6 | ||
|
|
0ff6a56f18 | ||
|
|
2d968bc8e8 | ||
|
|
8ab307a630 | ||
|
|
de00864f11 | ||
|
|
03d332979b | ||
|
|
1f6e8aa380 | ||
|
|
ef00d90e2f | ||
|
|
7f783f0b0a | ||
|
|
345888ef68 | ||
|
|
0e4c4a97ea | ||
|
|
d144f412ca | ||
|
|
9002a709b7 | ||
|
|
b91bff0f0c | ||
|
|
ed44d88c5b | ||
|
|
8f0a0381d3 | ||
|
|
b3e5e69f1f | ||
|
|
ef12d46431 | ||
|
|
9a19f46b7e | ||
|
|
a53c7ae08b | ||
|
|
17ebcb0834 | ||
|
|
7016e3de2b | ||
|
|
af51fd5b67 | ||
|
|
82151b1d82 | ||
|
|
b6e3131929 | ||
|
|
688fcc54cb | ||
|
|
bc79a0dd52 | ||
|
|
af732087e8 | ||
|
|
15130f1c95 | ||
|
|
53dc38f796 | ||
|
|
3bfc3f0673 | ||
|
|
eee65ec84e | ||
|
|
b4aefff06d | ||
|
|
baf14d495c | ||
|
|
003297ecfd | ||
|
|
2497249b8c | ||
|
|
9e9f4a9ce4 | ||
|
|
40d9bb964e | ||
|
|
0b3fb04728 | ||
|
|
13a52c40f2 | ||
|
|
109924d0da | ||
|
|
b391e5f83a | ||
|
|
b924dd2bbb | ||
|
|
28f1611079 |
44
.github/workflows/docker.yml
vendored
Normal file
44
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
name: Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
release:
|
||||||
|
types: [ created ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 'Checkout GitHub Action'
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
tag=${GITHUB_REF#refs/tags/}
|
||||||
|
tag=${tag#refs/heads/}
|
||||||
|
if echo $tag | grep -q -E "[0-9]+\.[0-9]+\.[0-9]+"; then
|
||||||
|
tag="v$tag"
|
||||||
|
fi
|
||||||
|
echo "##[set-output name=tag;]$tag"
|
||||||
|
id: extract_branch
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push docker
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/386
|
||||||
|
tags: ${{ secrets.REGISTRY_USERNAME }}/prometheus-qbittorrent-exporter:latest,${{ secrets.REGISTRY_USERNAME }}/prometheus-qbittorrent-exporter:${{ steps.extract_branch.outputs.tag }}
|
||||||
26
.github/workflows/pythonpublish.yml
vendored
Normal file
26
.github/workflows/pythonpublish.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Upload Python Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: '3.6'
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install setuptools wheel twine
|
||||||
|
- name: Build and publish
|
||||||
|
env:
|
||||||
|
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
|
||||||
|
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
python setup.py sdist
|
||||||
|
twine upload dist/*
|
||||||
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM alpine:3.11
|
||||||
|
|
||||||
|
# Installing required packages
|
||||||
|
RUN apk add --update --no-cache \
|
||||||
|
python3
|
||||||
|
|
||||||
|
# Install package
|
||||||
|
WORKDIR /code
|
||||||
|
COPY . .
|
||||||
|
RUN pip3 install .
|
||||||
|
|
||||||
|
ENV QBITTORRENT_HOST=""
|
||||||
|
ENV QBITTORRENT_PORT=""
|
||||||
|
ENV QBITTORRENT_USER=""
|
||||||
|
ENV QBITTORRENT_PASS=""
|
||||||
|
ENV EXPORTER_PORT="8000"
|
||||||
|
ENV EXPORTER_LOG_LEVEL="INFO"
|
||||||
|
|
||||||
|
ENTRYPOINT ["qbittorrent-exporter"]
|
||||||
20
README.md
20
README.md
@@ -20,9 +20,14 @@ qbittorrent-exporter
|
|||||||
Another option is run it in a docker container.
|
Another option is run it in a docker container.
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run esanchezm/prometheus-qbittorrent-exporter
|
docker run -e QBITTORRENT_PORT=8080 -e QBITTORRENT_HOST=myserver.local -p 8000:8000 esanchezm/prometheus-qbittorrent-exporter
|
||||||
|
```
|
||||||
|
Add this to your prometheus.yml
|
||||||
|
```
|
||||||
|
- job_name: "qbittorrent_exporter"
|
||||||
|
static_configs:
|
||||||
|
- targets: ['yourqbittorrentexporter:port']
|
||||||
```
|
```
|
||||||
|
|
||||||
The application reads configuration using environment variables:
|
The application reads configuration using environment variables:
|
||||||
|
|
||||||
| Environment variable | Default | Description |
|
| Environment variable | Default | Description |
|
||||||
@@ -33,11 +38,12 @@ The application reads configuration using environment variables:
|
|||||||
| `QBITTORRENT_PASS` | `""` | qbittorrent password |
|
| `QBITTORRENT_PASS` | `""` | qbittorrent password |
|
||||||
| `EXPORTER_PORT` | `8000` | Exporter listening port |
|
| `EXPORTER_PORT` | `8000` | Exporter listening port |
|
||||||
| `EXPORTER_LOG_LEVEL` | `INFO` | Log level. One of: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
|
| `EXPORTER_LOG_LEVEL` | `INFO` | Log level. One of: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
|
||||||
|
| `METRICS_PREFIX` | `qbittorrent` | Prefix to add to all the metrics |
|
||||||
|
|
||||||
|
|
||||||
## Metrics
|
## Metrics
|
||||||
|
|
||||||
These are the metrics this program exports:
|
These are the metrics this program exports, assuming the `METRICS_PREFIX` is `qbittorrent`:
|
||||||
|
|
||||||
|
|
||||||
| Metric name | Type | Description |
|
| Metric name | Type | Description |
|
||||||
@@ -48,7 +54,13 @@ These are the metrics this program exports:
|
|||||||
| `qbittorrent_dht_nodes` | gauge | Number of DHT nodes connected to |
|
| `qbittorrent_dht_nodes` | gauge | Number of DHT nodes connected to |
|
||||||
| `qbittorrent_dl_info_data` | counter | Data downloaded since the server started, in bytes |
|
| `qbittorrent_dl_info_data` | counter | Data downloaded since the server started, in bytes |
|
||||||
| `qbittorrent_up_info_data` | counter | Data uploaded since the server started, in bytes |
|
| `qbittorrent_up_info_data` | counter | Data uploaded since the server started, in bytes |
|
||||||
| `torrents_count` | gauge | Number of torrents for each `category` and `status`. Example: `torrents_count{category="movies",status="downloading"}`|
|
| `qbittorrent_torrents_count` | gauge | Number of torrents for each `category` and `status`. Example: `qbittorrent_torrents_count{category="movies",status="downloading"}`|
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[More info](./grafana/README.md)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
9
grafana/README.md
Normal file
9
grafana/README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Grafana dashboard
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|

|
||||||
927
grafana/dashboard.json
Normal file
927
grafana/dashboard.json
Normal file
@@ -0,0 +1,927 @@
|
|||||||
|
{
|
||||||
|
"__inputs": [
|
||||||
|
{
|
||||||
|
"name": "DS_PROMETHEUS",
|
||||||
|
"label": "Prometheus",
|
||||||
|
"description": "",
|
||||||
|
"type": "datasource",
|
||||||
|
"pluginId": "prometheus",
|
||||||
|
"pluginName": "Prometheus"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"__requires": [
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "gauge",
|
||||||
|
"name": "Gauge",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "grafana",
|
||||||
|
"id": "grafana",
|
||||||
|
"name": "Grafana",
|
||||||
|
"version": "7.2.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "grafana-piechart-panel",
|
||||||
|
"name": "Pie Chart",
|
||||||
|
"version": "1.6.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "graph",
|
||||||
|
"name": "Graph",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "datasource",
|
||||||
|
"id": "prometheus",
|
||||||
|
"name": "Prometheus",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "stat",
|
||||||
|
"name": "Stat",
|
||||||
|
"version": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": "-- Grafana --",
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"gnetId": null,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"iteration": 1603732792335,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 0,
|
||||||
|
"text": "Online",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 1,
|
||||||
|
"text": "Offline",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 2,
|
||||||
|
"text": "Unknown",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "semi-dark-red",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "semi-dark-green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "qbittorrent_up",
|
||||||
|
"format": "time_series",
|
||||||
|
"instant": false,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Qbittorrent Status",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 0,
|
||||||
|
"text": "Connected",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 1,
|
||||||
|
"text": "Disconnected",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 2,
|
||||||
|
"text": "Firewalled",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "-1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "dark-red",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "semi-dark-green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 3,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "qbittorrent_connected - qbittorrent_firewalled",
|
||||||
|
"format": "time_series",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Status",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Bittorrent network",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 1,
|
||||||
|
"text": "No DHT",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 2,
|
||||||
|
"text": "Firewalled",
|
||||||
|
"to": "",
|
||||||
|
"type": 1,
|
||||||
|
"value": "-1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "dark-red",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "semi-dark-green",
|
||||||
|
"value": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 6,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 13,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "qbittorrent_dht_nodes",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "DHT nodes",
|
||||||
|
"refId": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "DHT nodes",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "decbytes"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 9,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "increase(qbittorrent_dl_info_data_total[100y])",
|
||||||
|
"instant": false,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Data downloaded",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "decbytes"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 12,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "increase(qbittorrent_up_info_data_total[100y])",
|
||||||
|
"instant": false,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Data uploaded",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 15,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "increase(qbittorrent_up_info_data_total[100y]) / increase(qbittorrent_dl_info_data_total[100y])",
|
||||||
|
"instant": false,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Accumulated ratio",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"decimals": 1,
|
||||||
|
"mappings": [],
|
||||||
|
"max": 48000000,
|
||||||
|
"min": 0,
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "dark-red",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "dark-green",
|
||||||
|
"value": 8000000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "binBps"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 18,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 16,
|
||||||
|
"options": {
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showThresholdLabels": false,
|
||||||
|
"showThresholdMarkers": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(qbittorrent_dl_info_data_total[1m])",
|
||||||
|
"instant": false,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Download speed",
|
||||||
|
"type": "gauge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {},
|
||||||
|
"decimals": 1,
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"from": "",
|
||||||
|
"id": 1,
|
||||||
|
"text": "",
|
||||||
|
"to": "",
|
||||||
|
"type": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"max": 18000000,
|
||||||
|
"min": 0,
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "dark-red",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "dark-green",
|
||||||
|
"value": 4000000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "binBps"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 3,
|
||||||
|
"x": 21,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 17,
|
||||||
|
"options": {
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showThresholdLabels": false,
|
||||||
|
"showThresholdMarkers": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(qbittorrent_up_info_data_total[1m])",
|
||||||
|
"hide": false,
|
||||||
|
"instant": false,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Upload speed",
|
||||||
|
"type": "gauge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aliasColors": {},
|
||||||
|
"bars": false,
|
||||||
|
"dashLength": 10,
|
||||||
|
"dashes": false,
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"fill": 1,
|
||||||
|
"fillGradient": 0,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 4
|
||||||
|
},
|
||||||
|
"hiddenSeries": false,
|
||||||
|
"id": 15,
|
||||||
|
"legend": {
|
||||||
|
"avg": false,
|
||||||
|
"current": false,
|
||||||
|
"max": false,
|
||||||
|
"min": false,
|
||||||
|
"show": true,
|
||||||
|
"total": false,
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"lines": true,
|
||||||
|
"linewidth": 1,
|
||||||
|
"nullPointMode": "null",
|
||||||
|
"options": {
|
||||||
|
"alertThreshold": true
|
||||||
|
},
|
||||||
|
"percentage": false,
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"pointradius": 2,
|
||||||
|
"points": false,
|
||||||
|
"renderer": "flot",
|
||||||
|
"seriesOverrides": [],
|
||||||
|
"spaceLength": 10,
|
||||||
|
"stack": false,
|
||||||
|
"steppedLine": false,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(qbittorrent_dl_info_data_total[1m])",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Download",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(qbittorrent_up_info_data_total[1m])",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Upload",
|
||||||
|
"refId": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"thresholds": [],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeRegions": [],
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Transfer ratio",
|
||||||
|
"tooltip": {
|
||||||
|
"shared": true,
|
||||||
|
"sort": 0,
|
||||||
|
"value_type": "individual"
|
||||||
|
},
|
||||||
|
"type": "graph",
|
||||||
|
"xaxis": {
|
||||||
|
"buckets": null,
|
||||||
|
"mode": "time",
|
||||||
|
"name": null,
|
||||||
|
"show": true,
|
||||||
|
"values": []
|
||||||
|
},
|
||||||
|
"yaxes": [
|
||||||
|
{
|
||||||
|
"format": "binBps",
|
||||||
|
"label": null,
|
||||||
|
"logBase": 1,
|
||||||
|
"max": null,
|
||||||
|
"min": null,
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "binBps",
|
||||||
|
"label": null,
|
||||||
|
"logBase": 1,
|
||||||
|
"max": null,
|
||||||
|
"min": null,
|
||||||
|
"show": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"yaxis": {
|
||||||
|
"align": false,
|
||||||
|
"alignLevel": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aliasColors": {},
|
||||||
|
"bars": true,
|
||||||
|
"cacheTimeout": null,
|
||||||
|
"dashLength": 10,
|
||||||
|
"dashes": false,
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"fill": 1,
|
||||||
|
"fillGradient": 0,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 14,
|
||||||
|
"x": 0,
|
||||||
|
"y": 14
|
||||||
|
},
|
||||||
|
"hiddenSeries": false,
|
||||||
|
"id": 11,
|
||||||
|
"interval": null,
|
||||||
|
"legend": {
|
||||||
|
"alignAsTable": true,
|
||||||
|
"avg": false,
|
||||||
|
"current": false,
|
||||||
|
"max": false,
|
||||||
|
"min": false,
|
||||||
|
"rightSide": true,
|
||||||
|
"show": true,
|
||||||
|
"total": false,
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"lines": false,
|
||||||
|
"linewidth": 0,
|
||||||
|
"links": [],
|
||||||
|
"nullPointMode": "null as zero",
|
||||||
|
"options": {
|
||||||
|
"alertThreshold": true
|
||||||
|
},
|
||||||
|
"percentage": false,
|
||||||
|
"pluginVersion": "7.2.2",
|
||||||
|
"pointradius": 2,
|
||||||
|
"points": false,
|
||||||
|
"renderer": "flot",
|
||||||
|
"seriesOverrides": [],
|
||||||
|
"spaceLength": 10,
|
||||||
|
"stack": true,
|
||||||
|
"steppedLine": true,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(qbittorrent_torrents_count{category=~\"${categories}\", status!=\"complete\"}) by (status)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{status}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"thresholds": [],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeRegions": [],
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Torrents by status",
|
||||||
|
"tooltip": {
|
||||||
|
"shared": true,
|
||||||
|
"sort": 0,
|
||||||
|
"value_type": "individual"
|
||||||
|
},
|
||||||
|
"type": "graph",
|
||||||
|
"xaxis": {
|
||||||
|
"buckets": null,
|
||||||
|
"mode": "time",
|
||||||
|
"name": null,
|
||||||
|
"show": true,
|
||||||
|
"values": []
|
||||||
|
},
|
||||||
|
"yaxes": [
|
||||||
|
{
|
||||||
|
"format": "short",
|
||||||
|
"label": null,
|
||||||
|
"logBase": 1,
|
||||||
|
"max": null,
|
||||||
|
"min": null,
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "short",
|
||||||
|
"label": null,
|
||||||
|
"logBase": 1,
|
||||||
|
"max": null,
|
||||||
|
"min": null,
|
||||||
|
"show": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"yaxis": {
|
||||||
|
"align": false,
|
||||||
|
"alignLevel": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aliasColors": {},
|
||||||
|
"breakPoint": "50%",
|
||||||
|
"cacheTimeout": null,
|
||||||
|
"combine": {
|
||||||
|
"label": "Others",
|
||||||
|
"threshold": 0
|
||||||
|
},
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {
|
||||||
|
"align": null,
|
||||||
|
"filterable": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"fontSize": "80%",
|
||||||
|
"format": "short",
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 10,
|
||||||
|
"x": 14,
|
||||||
|
"y": 14
|
||||||
|
},
|
||||||
|
"id": 12,
|
||||||
|
"interval": null,
|
||||||
|
"legend": {
|
||||||
|
"percentage": true,
|
||||||
|
"show": true,
|
||||||
|
"sideWidth": null,
|
||||||
|
"values": true
|
||||||
|
},
|
||||||
|
"legendType": "Right side",
|
||||||
|
"links": [],
|
||||||
|
"nullPointMode": "connected",
|
||||||
|
"pieType": "donut",
|
||||||
|
"pluginVersion": "7.2.0",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(qbittorrent_torrents_count{category=~\"${categories}\",status!=\"complete\"}) by (category)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{category}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Torrents by categories",
|
||||||
|
"type": "grafana-piechart-panel",
|
||||||
|
"valueName": "current"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "30s",
|
||||||
|
"schemaVersion": 26,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {},
|
||||||
|
"datasource": "${DS_PROMETHEUS}",
|
||||||
|
"definition": "label_values(qbittorrent_torrents_count, category)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Categories",
|
||||||
|
"multi": true,
|
||||||
|
"name": "categories",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values(qbittorrent_torrents_count, category)",
|
||||||
|
"refresh": 1,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 0,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tags": [],
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-5m",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "Qbittorrent",
|
||||||
|
"uid": "eKyTETFMk",
|
||||||
|
"version": 40
|
||||||
|
}
|
||||||
BIN
grafana/screenshot.png
Normal file
BIN
grafana/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
@@ -3,7 +3,9 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import signal
|
import signal
|
||||||
import faulthandler
|
import faulthandler
|
||||||
|
from attrdict import AttrDict
|
||||||
from qbittorrentapi import Client, TorrentStates
|
from qbittorrentapi import Client, TorrentStates
|
||||||
|
from qbittorrentapi.exceptions import APIConnectionError
|
||||||
from prometheus_client import start_http_server
|
from prometheus_client import start_http_server
|
||||||
from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, REGISTRY
|
from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, REGISTRY
|
||||||
import logging
|
import logging
|
||||||
@@ -12,7 +14,7 @@ from pythonjsonlogger import jsonlogger
|
|||||||
|
|
||||||
# Enable dumps on stderr in case of segfault
|
# Enable dumps on stderr in case of segfault
|
||||||
faulthandler.enable()
|
faulthandler.enable()
|
||||||
logger = None
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class QbittorrentMetricsCollector():
|
class QbittorrentMetricsCollector():
|
||||||
@@ -40,6 +42,7 @@ class QbittorrentMetricsCollector():
|
|||||||
self.torrents = self.client.torrents.info()
|
self.torrents = self.client.torrents.info()
|
||||||
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}")
|
||||||
|
return None
|
||||||
|
|
||||||
metrics = self.get_qbittorrent_metrics()
|
metrics = self.get_qbittorrent_metrics()
|
||||||
|
|
||||||
@@ -65,46 +68,49 @@ class QbittorrentMetricsCollector():
|
|||||||
return metrics
|
return metrics
|
||||||
|
|
||||||
def get_qbittorrent_status_metrics(self):
|
def get_qbittorrent_status_metrics(self):
|
||||||
|
response = {}
|
||||||
|
version = ""
|
||||||
|
|
||||||
# Fetch data from API
|
# Fetch data from API
|
||||||
try:
|
try:
|
||||||
response = self.client.transfer.info
|
response = self.client.transfer.info
|
||||||
version = self.client.app.version
|
version = self.client.app.version
|
||||||
self.torrents = self.client.torrents.info()
|
self.torrents = self.client.torrents.info()
|
||||||
except Exception as e:
|
except APIConnectionError as e:
|
||||||
logger.error(f"Couldn't get server info: {e}")
|
logger.error(f"Couldn't get server info: {e.error_message}")
|
||||||
response = None
|
except Exception:
|
||||||
version = ""
|
logger.error(f"Couldn't get server info")
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"name": "up",
|
"name": f"{self.config['metrics_prefix']}_up",
|
||||||
"value": response is None,
|
"value": bool(response),
|
||||||
"labels": {"version": version},
|
"labels": {"version": version},
|
||||||
"help": "Whether if server is alive or not",
|
"help": "Whether if server is alive or not",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "connected",
|
"name": f"{self.config['metrics_prefix']}_connected",
|
||||||
"value": response.get("connection_status", "") == "connected",
|
"value": response.get("connection_status", "") == "connected",
|
||||||
"help": "Whether if server is connected or not",
|
"help": "Whether if server is connected or not",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firewalled",
|
"name": f"{self.config['metrics_prefix']}_firewalled",
|
||||||
"value": response.get("connection_status", "") == "firewalled",
|
"value": response.get("connection_status", "") == "firewalled",
|
||||||
"help": "Whether if server is under a firewall or not",
|
"help": "Whether if server is under a firewall or not",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "dht_nodes",
|
"name": f"{self.config['metrics_prefix']}_dht_nodes",
|
||||||
"value": response.get("dht_nodes", 0),
|
"value": response.get("dht_nodes", 0),
|
||||||
"help": "DHT nodes connected to",
|
"help": "DHT nodes connected to",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "dl_info_data",
|
"name": f"{self.config['metrics_prefix']}_dl_info_data",
|
||||||
"value": response.get("dl_info_data", 0),
|
"value": response.get("dl_info_data", 0),
|
||||||
"help": "Data downloaded this session (bytes)",
|
"help": "Data downloaded this session (bytes)",
|
||||||
"type": "counter"
|
"type": "counter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "up_info_data",
|
"name": f"{self.config['metrics_prefix']}_up_info_data",
|
||||||
"value": response.get("up_info_data", 0),
|
"value": response.get("up_info_data", 0),
|
||||||
"help": "Data uploaded this session (bytes)",
|
"help": "Data uploaded this session (bytes)",
|
||||||
"type": "counter"
|
"type": "counter"
|
||||||
@@ -116,17 +122,15 @@ class QbittorrentMetricsCollector():
|
|||||||
categories = self.client.torrent_categories.categories
|
categories = self.client.torrent_categories.categories
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Couldn't fetch categories: {e}")
|
logger.error(f"Couldn't fetch categories: {e}")
|
||||||
categories = None
|
|
||||||
|
|
||||||
if not categories:
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if not self.torrents:
|
if not self.torrents:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
metrics = []
|
metrics = []
|
||||||
|
categories.Uncategorized = AttrDict({'name': 'Uncategorized', 'savePath': ''})
|
||||||
for category in categories:
|
for category in categories:
|
||||||
category_torrents = [t for t in self.torrents if t['category'] == category]
|
category_torrents = [t for t in self.torrents if t['category'] == category or (category == "Uncategorized" and t['category'] == "")]
|
||||||
|
|
||||||
for status in self.TORRENT_STATUSES:
|
for status in self.TORRENT_STATUSES:
|
||||||
status_prop = f"is_{status}"
|
status_prop = f"is_{status}"
|
||||||
@@ -134,7 +138,7 @@ class QbittorrentMetricsCollector():
|
|||||||
t for t in category_torrents if getattr(TorrentStates, status_prop).fget(TorrentStates(t['state']))
|
t for t in category_torrents if getattr(TorrentStates, status_prop).fget(TorrentStates(t['state']))
|
||||||
]
|
]
|
||||||
metrics.append({
|
metrics.append({
|
||||||
"name": "torrents_count",
|
"name": f"{self.config['metrics_prefix']}_torrents_count",
|
||||||
"value": len(status_torrents),
|
"value": len(status_torrents),
|
||||||
"labels": {
|
"labels": {
|
||||||
"status": status,
|
"status": status,
|
||||||
@@ -148,44 +152,61 @@ class QbittorrentMetricsCollector():
|
|||||||
|
|
||||||
class SignalHandler():
|
class SignalHandler():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.shutdown = False
|
self.shutdownCount = 0
|
||||||
|
|
||||||
# Register signal handler
|
# Register signal handler
|
||||||
signal.signal(signal.SIGINT, self._on_signal_received)
|
signal.signal(signal.SIGINT, self._on_signal_received)
|
||||||
signal.signal(signal.SIGTERM, self._on_signal_received)
|
signal.signal(signal.SIGTERM, self._on_signal_received)
|
||||||
|
|
||||||
def is_shutting_down(self):
|
def is_shutting_down(self):
|
||||||
return self.shutdown
|
return self.shutdownCount > 0
|
||||||
|
|
||||||
def _on_signal_received(self, signal, frame):
|
def _on_signal_received(self, signal, frame):
|
||||||
|
if self.shutdownCount > 1:
|
||||||
|
logger.warn("Forcibly killing exporter")
|
||||||
|
sys.exit(1)
|
||||||
logger.info("Exporter is shutting down")
|
logger.info("Exporter is shutting down")
|
||||||
self.shutdown = True
|
self.shutdownCount += 1
|
||||||
|
|
||||||
|
def get_config_value(key, default=""):
|
||||||
|
input_path = os.environ.get("FILE__" + key, None)
|
||||||
|
if input_path is not None:
|
||||||
|
try:
|
||||||
|
with open(input_path, "r") as input_file:
|
||||||
|
return input_file.read().strip()
|
||||||
|
except IOError as e:
|
||||||
|
logger.error(f"Unable to read value for {key} from {input_path}: {str(e)}")
|
||||||
|
|
||||||
|
return os.environ.get(key, default)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
config = {
|
# Init logger so it can be used
|
||||||
"host": os.environ.get("QBITTORRENT_HOST", ""),
|
|
||||||
"port": os.environ.get("QBITTORRENT_PORT", ""),
|
|
||||||
"username": os.environ.get("QBITTORRENT_USER", ""),
|
|
||||||
"password": os.environ.get("QBITTORRENT_PASS", ""),
|
|
||||||
"exporter_port": int(os.environ.get("EXPORTER_PORT", "8000")),
|
|
||||||
"log_level": os.environ.get("EXPORTER_LOG_LEVEL", "INFO")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Register signal handler
|
|
||||||
signal_handler = SignalHandler()
|
|
||||||
|
|
||||||
# Init logger
|
|
||||||
logHandler = logging.StreamHandler()
|
logHandler = logging.StreamHandler()
|
||||||
formatter = jsonlogger.JsonFormatter(
|
formatter = jsonlogger.JsonFormatter(
|
||||||
"%(asctime) %(levelname) %(message)",
|
"%(asctime) %(levelname) %(message)",
|
||||||
datefmt="%Y-%m-%d %H:%M:%S"
|
datefmt="%Y-%m-%d %H:%M:%S"
|
||||||
)
|
)
|
||||||
logHandler.setFormatter(formatter)
|
logHandler.setFormatter(formatter)
|
||||||
logger = logging.getLogger()
|
|
||||||
logger.addHandler(logHandler)
|
logger.addHandler(logHandler)
|
||||||
|
logger.setLevel("INFO") # default until config is loaded
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"host": get_config_value("QBITTORRENT_HOST", ""),
|
||||||
|
"port": get_config_value("QBITTORRENT_PORT", ""),
|
||||||
|
"username": get_config_value("QBITTORRENT_USER", ""),
|
||||||
|
"password": get_config_value("QBITTORRENT_PASS", ""),
|
||||||
|
"exporter_port": int(get_config_value("EXPORTER_PORT", "8000")),
|
||||||
|
"log_level": get_config_value("EXPORTER_LOG_LEVEL", "INFO"),
|
||||||
|
"metrics_prefix": get_config_value("METRICS_PREFIX", "qbittorrent"),
|
||||||
|
}
|
||||||
|
# set level once config has been loaded
|
||||||
logger.setLevel(config["log_level"])
|
logger.setLevel(config["log_level"])
|
||||||
|
|
||||||
|
# Register signal handler
|
||||||
|
signal_handler = SignalHandler()
|
||||||
|
|
||||||
|
|
||||||
if not config["host"]:
|
if not config["host"]:
|
||||||
logger.error("No host specified, please set QBITTORRENT_HOST environment variable")
|
logger.error("No host specified, please set QBITTORRENT_HOST environment variable")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
6
setup.py
6
setup.py
@@ -6,18 +6,18 @@ with open("README.md", "r") as fh:
|
|||||||
setup(
|
setup(
|
||||||
name='prometheus-qbittorrent-exporter',
|
name='prometheus-qbittorrent-exporter',
|
||||||
packages=['qbittorrent_exporter'],
|
packages=['qbittorrent_exporter'],
|
||||||
version='1.0.0',
|
version='1.2.0',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
description='Prometheus exporter for qbittorrent',
|
description='Prometheus exporter for qbittorrent',
|
||||||
author='Esteban Sanchez',
|
author='Esteban Sanchez',
|
||||||
author_email='esteban.sanchez@gmail.com',
|
author_email='esteban.sanchez@gmail.com',
|
||||||
url='https://github.com/esanchezm/prometheus-qbittorrent-exporter',
|
url='https://github.com/esanchezm/prometheus-qbittorrent-exporter',
|
||||||
download_url='https://github.com/spreaker/prometheus-qbittorrent-exporter/archive/1.0.0.tar.gz',
|
download_url='https://github.com/esanchezm/prometheus-qbittorrent-exporter/archive/1.1.0.tar.gz',
|
||||||
keywords=['prometheus', 'qbittorrent'],
|
keywords=['prometheus', 'qbittorrent'],
|
||||||
classifiers=[],
|
classifiers=[],
|
||||||
python_requires='>=3',
|
python_requires='>=3',
|
||||||
install_requires=['qbittorrent-api==2020.9.9', 'prometheus_client==0.8.0', 'python-json-logger==0.1.5'],
|
install_requires=['attrdict==2.0.1', 'qbittorrent-api==2021.3.18', 'prometheus_client==0.8.0', 'python-json-logger==0.1.5'],
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'qbittorrent-exporter=qbittorrent_exporter.exporter:main',
|
'qbittorrent-exporter=qbittorrent_exporter.exporter:main',
|
||||||
|
|||||||
Reference in New Issue
Block a user