diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 4ead663..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,3 +0,0 @@
-[run]
-relative_files = True
-omit = tests/*
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 6a7695c..0000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-version: 2
-updates:
- - package-ecosystem: "pip"
- directory: "/"
- schedule:
- interval: "weekly"
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
deleted file mode 100644
index 5b44549..0000000
--- a/.github/workflows/docker.yml
+++ /dev/null
@@ -1,73 +0,0 @@
-name: Docker
-
-on:
- push:
- branches: [ master ]
- release:
- types: [ created ]
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - name: 'Checkout GitHub Action'
- uses: actions/checkout@v4
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Docker hub meta
- id: meta
- uses: docker/metadata-action@v5
- with:
- flavor: |
- latest=true
- tags: |
- type=semver,pattern=v{{version}}
- type=ref,event=branch
- type=sha
- images: ${{ github.actor }}/prometheus-qbittorrent-exporter
-
- - name: Login to DockerHub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.REGISTRY_USERNAME }}
- password: ${{ secrets.REGISTRY_PASSWORD }}
-
- - name: Build and push docker to DockerHub
- uses: docker/build-push-action@v5
- with:
- push: true
- platforms: linux/amd64,linux/arm64,linux/386
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
-
- - name: GHCR Docker meta
- id: metaghcr
- uses: docker/metadata-action@v5
- with:
- flavor: |
- latest=true
- tags: |
- type=semver,pattern=v{{version}}
- type=ref,event=branch
- type=sha
- images: ghcr.io/${{ github.actor }}/prometheus-qbittorrent-exporter
-
- - name: Login to Github Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build and push docker to Github Container Registry
- uses: docker/build-push-action@v5
- with:
- push: true
- platforms: linux/amd64,linux/arm64,linux/386
- tags: ${{ steps.metaghcr.outputs.tags }}
- labels: ${{ steps.metaghcr.outputs.labels }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
deleted file mode 100644
index d1b7059..0000000
--- a/.github/workflows/lint.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-name: Run Unit Test via Pytest
-
-on:
- pull_request:
- push:
- branches:
- - "master"
-
-jobs:
- lint-and-test:
- runs-on: ubuntu-latest
- permissions:
- pull-requests: write
- contents: write
- checks: write
- strategy:
- matrix:
- python-version: ["3.11"]
-
- steps:
- - uses: actions/checkout@v3
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
- with:
- python-version: ${{ matrix.python-version }}
- - name: Setup PDM
- uses: pdm-project/setup-pdm@v3
- - name: Install dependencies
- run: pdm install
- - name: Lint with black
- uses: psf/black@stable
- with:
- options: "--check --verbose"
- - name: Test with pytest
- run: |
- pdm run pytest --junit-xml=test-results.xml
- - name: Publish Test Results
- uses: EnricoMi/publish-unit-test-result-action@v2
- if: always()
- with:
- files: |
- test-results.xml
- - name: Test with coverage
- run: |
- pdm run coverage run -m pytest -v -s
- - name: Generate Coverage Report
- run: |
- pdm run coverage report -m
- - name: Coverage comment
- id: coverage_comment
- uses: py-cov-action/python-coverage-comment-action@v3
- with:
- GITHUB_TOKEN: ${{ github.token }}
- - name: Store Pull Request comment to be posted
- uses: actions/upload-artifact@v3
- if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
- with:
- name: python-coverage-comment-action
- path: python-coverage-comment-action.txt
diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml
deleted file mode 100644
index 36caa06..0000000
--- a/.github/workflows/pythonpublish.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-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.9'
- - 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/*
diff --git a/.idea/misc.xml b/.idea/misc.xml
index e82613a..154d3e7 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
deleted file mode 100644
index a63f4e4..0000000
--- a/.pre-commit-config.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-repos:
- - repo: local
- hooks:
- - id: black
- name: black
- stages: [commit]
- types: [python]
- entry: pdm run black .
- language: system
- pass_filenames: false
- always_run: true
- - id: ruff
- name: ruff
- stages: [commit]
- types: [python]
- entry: pdm run ruff .
- language: system
- pass_filenames: false
- always_run: true
- fail_fast: true
- - id: pytest
- name: pytest
- stages: [commit]
- types: [python]
- entry: pdm run pytest
- language: system
- pass_filenames: false
- always_run: true
- fail_fast: true
diff --git a/Dockerfile b/Dockerfile
index f58eb14..2a3912f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.16.4
+FROM alpine:3.18.4
# Installing required packages
FROM alpine/doctl
diff --git a/config.env.example b/config.env.example
deleted file mode 100644
index 55bbd2a..0000000
--- a/config.env.example
+++ /dev/null
@@ -1,6 +0,0 @@
-QBITTORRENT_HOST=localhost
-QBITTORRENT_PORT=8080
-QBITTORRENT_USER=admin
-QBITTORRENT_PASS=adminadmin
-EXPORTER_PORT=8000
-METRICS_PREFIX=qbittorrent
\ No newline at end of file
diff --git a/immich_exporter/exporter.py b/immich_exporter/exporter.py
index b3a4afc..4db3f14 100644
--- a/immich_exporter/exporter.py
+++ b/immich_exporter/exporter.py
@@ -49,7 +49,6 @@ class ImmichMetricsCollector:
return metrics
-
def get_immich_users_stat_growth(self):
try:
@@ -63,24 +62,24 @@ class ImmichMetricsCollector:
except requests.exceptions.RequestException as e:
logger.error(f"Couldn't get server version: {e}")
- userData = response_user_stats.json()["usageByUser"]
+ user_data = response_user_stats.json()["usageByUser"]
# photos growth gauge
- userCount = len(response_user_stats.json()["usageByUser"])
+ user_count = len(response_user_stats.json()["usageByUser"])
photos_growth_total = 0
videos_growth_total = 0
usage_growth_total = 0
- for x in range(0, userCount):
- photos_growth_total += userData[x]["photos"]
+ for x in range(0, user_count):
+ photos_growth_total += user_data[x]["photos"]
# total video growth
- videos_growth_total += userData[x]["videos"]
+ videos_growth_total += user_data[x]["videos"]
# total disk growth
- usage_growth_total += userData[x]["usage"]
+ usage_growth_total += user_data[x]["usage"]
return [
{
"name": f"{self.config['metrics_prefix']}_server_stats_user_count",
- "value": userCount,
+ "value": user_count,
"help": "number of users on the immich server"
},
{
@@ -122,53 +121,54 @@ class ImmichMetricsCollector:
# To get the user count an api-endpoint exists but this works too. As a result one less api call is being made
try:
- userCount = len(response_user_stats.json()["usageByUser"])
+ user_count = len(response_user_stats.json()["usageByUser"])
except Exception:
logger.error("Is the Immich api token valid? Traceback:KeyError: 'usageByUser': ")
# json array of all users with stats
- # this line throws an error if api token is wrong. if the token is wrong or inavlid this will return a KeyError : 'usage by user'
- userData = response_user_stats.json()["usageByUser"]
+ # this line throws an error if api token is wrong. if the token is wrong
+ # or invalid this will return a KeyError : 'usage by user'
+ user_data = response_user_stats.json()["usageByUser"]
- for x in range(0, userCount):
+ for x in range(0, user_count):
metrics.append(
{
"name": f"{self.config['metrics_prefix']}_server_stats_photos_by_users",
- "value": userData[x]['photos'],
+ "value": user_data[x]['photos'],
"labels": {
- "firstName": userData[x]["userName"].split()[0],
+ "firstName": user_data[x]["userName"].split()[0],
},
- "help": f"Number of photos by user {userData[x]['userName'].split()[0]} "
+ "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} "
}
)
# videos
- for x in range(0, userCount):
+ for x in range(0, user_count):
metrics.append(
{
"name": f"{self.config['metrics_prefix']}_server_stats_videos_by_users",
- "value": userData[x]['videos'],
+ "value": user_data[x]['videos'],
"labels": {
- "firstName": userData[x]["userName"].split()[0],
+ "firstName": user_data[x]["userName"].split()[0],
},
- "help": f"Number of photos by user {userData[x]['userName'].split()[0]} "
+ "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} "
}
)
# usage
- for x in range(0, userCount):
+ for x in range(0, user_count):
metrics.append(
{
"name": f"{self.config['metrics_prefix']}_server_stats_usage_by_users",
- "value": (userData[x]['usage']),
+ "value": (user_data[x]['usage']),
"labels": {
- "firstName": userData[x]["userName"].split()[0],
+ "firstName": user_data[x]["userName"].split()[0],
},
- "help": f"Number of photos by user {userData[x]['userName'].split()[0]} "
+ "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} "
}
)
@@ -294,11 +294,9 @@ def get_config_value(key, default=""):
def check_server_up(immichHost, immichPort):
-
#
counter = 0
-
while True:
counter = counter + 1
try:
@@ -310,7 +308,7 @@ def check_server_up(immichHost, immichPort):
)
except requests.exceptions.RequestException as e:
logger.error(f"CONNECTION ERROR. Cannot reach immich at " + immichHost + ":" + immichPort + "."
- f"Is immich up and running?")
+ f"Is immich up and running?")
if 0 <= counter <= 60:
time.sleep(1)
elif 11 <= counter <= 300:
@@ -326,13 +324,12 @@ def check_server_up(immichHost, immichPort):
def check_immich_api_key(immichHost, immichPort, immichApiKey):
-
while True:
try:
requests.request(
"GET",
- "http://"+immichHost+":"+immichPort+"/api/server-info/",
+ "http://" + immichHost + ":" + immichPort + "/api/server-info/",
headers={'Accept': 'application/json',
"x-api-key": immichApiKey}
)
@@ -394,9 +391,7 @@ def main():
f"Exporter listening on port {config['exporter_port']}"
)
-
while not signal_handler.is_shutting_down():
time.sleep(1)
logger.info("Exporter has shutdown")
-
diff --git a/logo.png b/logo.png
deleted file mode 100644
index 996f2be..0000000
Binary files a/logo.png and /dev/null differ
diff --git a/pdm.lock b/pdm.lock
deleted file mode 100644
index 62b32fe..0000000
--- a/pdm.lock
+++ /dev/null
@@ -1,284 +0,0 @@
-# This file is @generated by PDM.
-# It is not intended for manual editing.
-
-[metadata]
-groups = ["default", "dev"]
-strategy = ["cross_platform"]
-lock_version = "4.4"
-content_hash = "sha256:474c773ee86217d652b5fc82f921ce2fbb513b244d50fbe82b74ea9e47dad96e"
-
-[[package]]
-name = "black"
-version = "23.11.0"
-requires_python = ">=3.8"
-summary = "The uncompromising code formatter."
-dependencies = [
- "click>=8.0.0",
- "mypy-extensions>=0.4.3",
- "packaging>=22.0",
- "pathspec>=0.9.0",
- "platformdirs>=2",
-]
-files = [
- {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"},
- {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"},
- {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"},
- {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"},
- {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"},
- {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"},
-]
-
-[[package]]
-name = "certifi"
-version = "2023.7.22"
-requires_python = ">=3.6"
-summary = "Python package for providing Mozilla's CA Bundle."
-files = [
- {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
- {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
-]
-
-[[package]]
-name = "charset-normalizer"
-version = "3.2.0"
-requires_python = ">=3.7.0"
-summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-files = [
- {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
- {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
-]
-
-[[package]]
-name = "click"
-version = "8.1.7"
-requires_python = ">=3.7"
-summary = "Composable command line interface toolkit"
-dependencies = [
- "colorama; platform_system == \"Windows\"",
-]
-files = [
- {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
- {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
-]
-
-[[package]]
-name = "colorama"
-version = "0.4.6"
-requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
-summary = "Cross-platform colored terminal text."
-files = [
- {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
- {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
-]
-
-[[package]]
-name = "coverage"
-version = "7.3.2"
-requires_python = ">=3.8"
-summary = "Code coverage measurement for Python"
-files = [
- {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
- {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
- {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
- {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
- {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
- {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
- {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
- {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
- {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
- {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
- {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
- {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
- {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
- {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
- {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
- {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
- {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
- {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
- {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
- {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
- {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
- {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
-]
-
-[[package]]
-name = "idna"
-version = "3.4"
-requires_python = ">=3.5"
-summary = "Internationalized Domain Names in Applications (IDNA)"
-files = [
- {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
- {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
-]
-
-[[package]]
-name = "iniconfig"
-version = "2.0.0"
-requires_python = ">=3.7"
-summary = "brain-dead simple config-ini parsing"
-files = [
- {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
- {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
-]
-
-[[package]]
-name = "isort"
-version = "5.12.0"
-requires_python = ">=3.8.0"
-summary = "A Python utility / library to sort Python imports."
-files = [
- {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
- {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
-]
-
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-requires_python = ">=3.5"
-summary = "Type system extensions for programs checked with the mypy type checker."
-files = [
- {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
- {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
-]
-
-[[package]]
-name = "packaging"
-version = "23.1"
-requires_python = ">=3.7"
-summary = "Core utilities for Python packages"
-files = [
- {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
- {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
-]
-
-[[package]]
-name = "pathspec"
-version = "0.11.2"
-requires_python = ">=3.7"
-summary = "Utility library for gitignore style pattern matching of file paths."
-files = [
- {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
- {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
-]
-
-[[package]]
-name = "platformdirs"
-version = "4.0.0"
-requires_python = ">=3.7"
-summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-files = [
- {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"},
- {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"},
-]
-
-[[package]]
-name = "pluggy"
-version = "1.3.0"
-requires_python = ">=3.8"
-summary = "plugin and hook calling mechanisms for python"
-files = [
- {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
- {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
-]
-
-[[package]]
-name = "prometheus-client"
-version = "0.17.1"
-requires_python = ">=3.6"
-summary = "Python client for the Prometheus monitoring system."
-files = [
- {file = "prometheus_client-0.17.1-py3-none-any.whl", hash = "sha256:e537f37160f6807b8202a6fc4764cdd19bac5480ddd3e0d463c3002b34462101"},
- {file = "prometheus_client-0.17.1.tar.gz", hash = "sha256:21e674f39831ae3f8acde238afd9a27a37d0d2fb5a28ea094f0ce25d2cbf2091"},
-]
-
-[[package]]
-name = "pytest"
-version = "7.4.3"
-requires_python = ">=3.7"
-summary = "pytest: simple powerful testing with Python"
-dependencies = [
- "colorama; sys_platform == \"win32\"",
- "iniconfig",
- "packaging",
- "pluggy<2.0,>=0.12",
-]
-files = [
- {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
- {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
-]
-
-[[package]]
-name = "python-json-logger"
-version = "2.0.7"
-requires_python = ">=3.6"
-summary = "A python library adding a json log formatter"
-files = [
- {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"},
- {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"},
-]
-
-[[package]]
-name = "qbittorrent-api"
-version = "2023.9.53"
-summary = "Python client for qBittorrent v4.1+ Web API."
-dependencies = [
- "packaging",
- "requests>=2.16.0",
- "six",
- "urllib3>=1.24.2",
-]
-files = [
- {file = "qbittorrent-api-2023.9.53.tar.gz", hash = "sha256:fead1b2f55b1227ea088ea7d90b5022d94694bfd9dd9176beb5ad1c195d044ff"},
- {file = "qbittorrent_api-2023.9.53-py2.py3-none-any.whl", hash = "sha256:963ae59d16a9c4a9aa1714fb7f6799539dc2693136cdc0e377daab3612ca775a"},
-]
-
-[[package]]
-name = "requests"
-version = "2.31.0"
-requires_python = ">=3.7"
-summary = "Python HTTP for Humans."
-dependencies = [
- "certifi>=2017.4.17",
- "charset-normalizer<4,>=2",
- "idna<4,>=2.5",
- "urllib3<3,>=1.21.1",
-]
-files = [
- {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
- {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
-]
-
-[[package]]
-name = "six"
-version = "1.16.0"
-requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-summary = "Python 2 and 3 compatibility utilities"
-files = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-
-[[package]]
-name = "urllib3"
-version = "2.0.5"
-requires_python = ">=3.7"
-summary = "HTTP library with thread-safe connection pooling, file post, and more."
-files = [
- {file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"},
- {file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"},
-]
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index 8f79963..0000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,36 +0,0 @@
-[project]
-name = "prometheus-qbittorrent-exporter"
-version = "1.4.0"
-description = "Prometheus exporter for qbittorrent"
-authors = [
- {name = "Esteban Sanchez", email = "esteban.sanchez@gmail.com"},
-]
-dependencies = [
- "prometheus-client>=0.17.1",
- "python-json-logger>=2.0.7",
- "qbittorrent-api>=2023.9.53",
-]
-requires-python = ">=3.11"
-readme = "README.md"
-keywords = ["prometheus", "qbittorrent"]
-license = {text = "GPL-3.0"}
-classifiers = []
-
-[project.urls]
-Homepage = "https://github.com/esanchezm/prometheus-qbittorrent-exporter"
-Downloads = "https://github.com/esanchezm/prometheus-qbittorrent-exporter/archive/1.4.0.tar.gz"
-
-[project.scripts]
-qbittorrent-exporter = "qbittorrent_exporter.exporter:main"
-
-[build-system]
-requires = ["pdm-backend"]
-build-backend = "pdm.backend"
-
-[tool.pdm.dev-dependencies]
-dev = [
- "pytest>=7.4.3",
- "isort>=5.12.0",
- "black>=23.11.0",
- "coverage>=7.3.2",
-]
diff --git a/setup.py b/setup.py
index 0c133dc..280b451 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
setup(
name='prometheus-immich-exporter',
packages=['immich_exporter'],
- version='1.0.9',
+ version='1.1.0',
long_description=long_description,
long_description_content_type="text/markdown",
description='Prometheus exporter for immich',
@@ -18,7 +18,7 @@ setup(
keywords=['prometheus', 'immich'],
classifiers=[],
python_requires='>=3',
- install_requires=['attrdict==2.0.1', 'prometheus_client==0.12.0 ', 'requests==2.28.2', 'python-json-logger==2.0.2'],
+ install_requires=['attrdict==2.0.1', 'prometheus_client==0.19.0 ', 'requests==2.31.0', 'python-json-logger==2.0.7'],
entry_points={
'console_scripts': [
'immich_exporter=immich_exporter.exporter:main',
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/exporter_test.py b/tests/exporter_test.py
deleted file mode 100644
index 7153ab8..0000000
--- a/tests/exporter_test.py
+++ /dev/null
@@ -1,276 +0,0 @@
-import unittest
-from unittest.mock import MagicMock, patch
-
-from prometheus_client.metrics_core import CounterMetricFamily, GaugeMetricFamily
-
-from qbittorrent_exporter.exporter import (
- Metric,
- MetricType,
- QbittorrentMetricsCollector,
-)
-from qbittorrentapi import TorrentStates
-
-
-class TestQbittorrentMetricsCollector(unittest.TestCase):
- @patch("qbittorrent_exporter.exporter.Client")
- def setUp(self, mock_client):
- self.mock_client = mock_client
- self.config = {
- "host": "localhost",
- "port": "8080",
- "username": "user",
- "password": "pass",
- "verify_webui_certificate": False,
- "metrics_prefix": "qbittorrent",
- }
- self.torrentsState = [
- {"name": "Torrent DOWNLOADING 1", "state": TorrentStates.DOWNLOADING},
- {"name": "Torrent UPLOADING 1", "state": TorrentStates.UPLOADING},
- {"name": "Torrent DOWNLOADING 2", "state": TorrentStates.DOWNLOADING},
- {"name": "Torrent UPLOADING 2", "state": TorrentStates.UPLOADING},
- ]
- self.torrentsCategories = [
- {"name": "Torrent Movies 1", "category": "Movies"},
- {"name": "Torrent Music 1", "category": "Music"},
- {"name": "Torrent Movies 2", "category": "Movies"},
- {"name": "Torrent unknown", "category": ""},
- {"name": "Torrent Music 2", "category": "Music"},
- {"name": "Torrent Uncategorized 1", "category": "Uncategorized"},
- ]
- self.collector = QbittorrentMetricsCollector(self.config)
-
- def test_init(self):
- self.assertEqual(self.collector.config, self.config)
- self.mock_client.assert_called_once_with(
- host=self.config["host"],
- port=self.config["port"],
- username=self.config["username"],
- password=self.config["password"],
- VERIFY_WEBUI_CERTIFICATE=self.config["verify_webui_certificate"],
- )
-
- def test_collect_gauge(self):
- mock_metric = Metric(
- name="test_gauge",
- metric_type=MetricType.GAUGE,
- help_text="Test Gauge",
- labels={"label1": "value1"},
- value=10,
- )
- self.collector.get_qbittorrent_metrics = MagicMock(return_value=[mock_metric])
-
- result = next(self.collector.collect())
-
- self.assertIsInstance(result, GaugeMetricFamily)
- self.assertEqual(result.name, "test_gauge")
- self.assertEqual(result.documentation, "Test Gauge")
- self.assertEqual(result.samples[0].labels, {"label1": "value1"})
- self.assertEqual(result.samples[0].value, 10)
-
- def test_collect_counter(self):
- mock_metric = Metric(
- name="test_counter",
- metric_type=MetricType.COUNTER,
- help_text="Test Counter",
- labels={"label2": "value2"},
- value=230,
- )
- self.collector.get_qbittorrent_metrics = MagicMock(return_value=[mock_metric])
-
- result = next(self.collector.collect())
-
- self.assertIsInstance(result, CounterMetricFamily)
- self.assertEqual(result.name, "test_counter")
- self.assertEqual(result.documentation, "Test Counter")
- self.assertEqual(result.samples[0].labels, {"label2": "value2"})
- self.assertEqual(result.samples[0].value, 230)
-
- def test_get_qbittorrent_metrics(self):
- metrics = self.collector.get_qbittorrent_metrics()
- self.assertNotEqual(len(metrics), 0)
-
- def test_fetch_categories(self):
- # Mock the client.torrent_categories.categories attribute
- self.collector.client.torrent_categories.categories = {
- "category1": {"name": "Category 1"},
- "category2": {"name": "Category 2"},
- "category3": {"name": "Category 3"},
- }
-
- categories = self.collector._fetch_categories()
- self.assertIsInstance(categories, dict)
- self.assertNotEqual(len(categories), 0)
- self.assertEqual(categories["category1"]["name"], "Category 1")
- self.assertEqual(categories["category2"]["name"], "Category 2")
- self.assertEqual(categories["category3"]["name"], "Category 3")
-
- def test_fetch_categories_exception(self):
- self.collector.client.torrent_categories.categories = Exception(
- "Error fetching categories"
- )
- categories = self.collector._fetch_categories()
- self.assertEqual(categories, {})
-
- def test_fetch_torrents_success(self):
- # Mock the return value of self.client.torrents.info()
- self.collector.client.torrents.info.return_value = [
- {"name": "Torrent 1", "size": 100},
- {"name": "Torrent 2", "size": 200},
- {"name": "Torrent 3", "size": 300},
- ]
-
- expected_result = [
- {"name": "Torrent 1", "size": 100},
- {"name": "Torrent 2", "size": 200},
- {"name": "Torrent 3", "size": 300},
- ]
-
- result = self.collector._fetch_torrents()
- self.assertEqual(result, expected_result)
-
- def test_fetch_torrents_exception(self):
- # Mock an exception being raised by self.client.torrents.info()
- self.collector.client.torrents.info.side_effect = Exception("Connection error")
-
- expected_result = []
-
- result = self.collector._fetch_torrents()
- self.assertEqual(result, expected_result)
-
- def test_filter_torrents_by_state(self):
- expected = [
- {"name": "Torrent DOWNLOADING 1", "state": TorrentStates.DOWNLOADING},
- {"name": "Torrent DOWNLOADING 2", "state": TorrentStates.DOWNLOADING},
- ]
- result = self.collector._filter_torrents_by_state(
- TorrentStates.DOWNLOADING, self.torrentsState
- )
- self.assertEqual(result, expected)
-
- expected = [
- {"name": "Torrent UPLOADING 1", "state": TorrentStates.UPLOADING},
- {"name": "Torrent UPLOADING 2", "state": TorrentStates.UPLOADING},
- ]
- result = self.collector._filter_torrents_by_state(
- TorrentStates.UPLOADING, self.torrentsState
- )
- self.assertEqual(result, expected)
-
- expected = []
- result = self.collector._filter_torrents_by_state(
- TorrentStates.ERROR, self.torrentsState
- )
- self.assertEqual(result, expected)
-
- def test_filter_torrents_by_category(self):
- expected_result = [
- {"name": "Torrent Movies 1", "category": "Movies"},
- {"name": "Torrent Movies 2", "category": "Movies"},
- ]
- result = self.collector._filter_torrents_by_category(
- "Movies", self.torrentsCategories
- )
- self.assertEqual(result, expected_result)
-
- expected_result = [
- {"name": "Torrent unknown", "category": ""},
- {"name": "Torrent Uncategorized 1", "category": "Uncategorized"},
- ]
- result = self.collector._filter_torrents_by_category(
- "Uncategorized", self.torrentsCategories
- )
- self.assertEqual(result, expected_result)
-
- expected_result = []
- result = self.collector._filter_torrents_by_category(
- "Books", self.torrentsCategories
- )
- self.assertEqual(result, expected_result)
-
- def test_construct_metric_with_valid_state_and_category(self):
- state = "downloading"
- category = "movies"
- count = 10
-
- metric = self.collector._construct_metric(state, category, count)
-
- self.assertEqual(metric.name, "qbittorrent_torrents_count")
- self.assertEqual(metric.value, count)
- self.assertEqual(metric.labels["status"], state)
- self.assertEqual(metric.labels["category"], category)
- self.assertEqual(
- metric.help_text,
- f"Number of torrents in status {state} under category {category}",
- )
-
- def test_construct_metric_with_empty_state_and_category(self):
- state = ""
- category = ""
- count = 5
-
- metric = self.collector._construct_metric(state, category, count)
-
- self.assertEqual(metric.name, "qbittorrent_torrents_count")
- self.assertEqual(metric.value, count)
- self.assertEqual(metric.labels["status"], state)
- self.assertEqual(metric.labels["category"], category)
- self.assertEqual(
- metric.help_text, "Number of torrents in status under category "
- )
-
- def test_get_qbittorrent_status_metrics(self):
- self.collector.client.transfer.info = {"connection_status": "connected"}
- self.collector.client.app.version = "1.2.3"
-
- expected_metrics = [
- Metric(
- name="qbittorrent_up",
- value=True,
- labels={"version": "1.2.3"},
- help_text=(
- "Whether the qBittorrent server is answering requests from this"
- " exporter. A `version` label with the server version is added."
- ),
- ),
- Metric(
- name="qbittorrent_connected",
- value=True,
- labels={},
- help_text=(
- "Whether the qBittorrent server is connected to the Bittorrent"
- " network."
- ),
- ),
- Metric(
- name="qbittorrent_firewalled",
- value=False,
- labels={},
- help_text=(
- "Whether the qBittorrent server is connected to the Bittorrent"
- " network but is behind a firewall."
- ),
- ),
- Metric(
- name="qbittorrent_dht_nodes",
- value=0,
- labels={},
- help_text="Number of DHT nodes connected to.",
- ),
- Metric(
- name="qbittorrent_dl_info_data",
- value=0,
- labels={},
- help_text="Data downloaded since the server started, in bytes.",
- metric_type=MetricType.COUNTER,
- ),
- Metric(
- name="qbittorrent_up_info_data",
- value=0,
- labels={},
- help_text="Data uploaded since the server started, in bytes.",
- metric_type=MetricType.COUNTER,
- ),
- ]
-
- metrics = self.collector._get_qbittorrent_status_metrics()
- self.assertEqual(metrics, expected_metrics)
diff --git a/tests/metric_test.py b/tests/metric_test.py
deleted file mode 100644
index 7c597ee..0000000
--- a/tests/metric_test.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import unittest
-
-from qbittorrent_exporter.exporter import Metric, MetricType
-
-
-class TestMetric(unittest.TestCase):
- def test_metric_initialization(self):
- metric = Metric(name="test_metric", value=10)
- self.assertEqual(metric.name, "test_metric")
- self.assertEqual(metric.value, 10)
- self.assertEqual(metric.labels, {})
- self.assertEqual(metric.help_text, "")
- self.assertEqual(metric.metric_type, MetricType.GAUGE)
diff --git a/unraid/prometheus-immich-exporter.xml b/unraid/prometheus-immich-exporter.xml
index 706bf0e..b78a32c 100644
--- a/unraid/prometheus-immich-exporter.xml
+++ b/unraid/prometheus-immich-exporter.xml
@@ -22,7 +22,7 @@
https://www.paypal.com/donate/?hosted_button_id=DPDKED3T3BFV8
8000
-
+
\ No newline at end of file