diff --git a/Dockerfile b/Dockerfile index 9f26d82..1e4c5d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM alpine:3.18.4 # Installing required packages FROM alpine/doctl ENV PYTHONUNBUFFERED=1 -RUN apk add --update --no-cache python3 py-pip && ln -sf python3 /usr/bin/python +RUN apk add --update --no-cache python3 py-pip gcc python3-dev musl-dev linux-headers && ln -sf python3 /usr/bin/python #RUN python3 -m ensurepip RUN pip3 install --break-system-packages --no-cache --upgrade pip setuptools diff --git a/README.md b/README.md index 1639c24..fcbaccf 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,12 @@ These are the metrics this program exports, assuming the `METRICS_PREFIX` is `im | `immich_server_stats_videos_growth` | `sum of all videos of all users` | | `immich_server_stats_usage_by_users` | `the disk space each user uses` | | `immich_server_stats_usage_growth` | `sum of disk space taken up by all users` | - + +| `metric name` | `description` | +|---------------------------------------|------------------------------------------------------------------| +| `immich_system_info_loadAverage` | `array of load average (1m, 5m 15m)` | +| `immich_system_info_memory` | `array of memory states (Total, Available, Percent, Used, Free)` | + ## Screenshot diff --git a/grafana/README.md b/grafana/README.md index c31b4c1..d4d1e4d 100644 --- a/grafana/README.md +++ b/grafana/README.md @@ -2,7 +2,7 @@ ## Import -To import the dashboard into your grafana, download the [dashboard.json](https://github.com/friendlyFriend4000/prometheus-immich-exporter/raw/master/grafana/dashboard-immich.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](./dashboard-immich.json) file and import it into your server. Select your prometheus instance and that should be all. The graphs can be customized in their relative time. Mind that it takes time to populate them if you set relative time to monthly or yearly diff --git a/grafana/dashboard-immich.json b/grafana/dashboard-immich.json index f09639c..b5e3602 100644 --- a/grafana/dashboard-immich.json +++ b/grafana/dashboard-immich.json @@ -113,12 +113,14 @@ "fields": "", "values": false }, + "showPercentChange": false, "text": { "titleSize": 6 }, - "textMode": "name" + "textMode": "name", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -183,9 +185,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -245,9 +249,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -307,9 +313,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -369,9 +377,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -431,9 +441,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -454,6 +466,209 @@ "title": "Remaining disk size", "type": "stat" }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "amount of CPU usage over time", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 3 + }, + "id": 51, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "immich_system_info_loadAverage", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{period}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Load Average", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Free memory over time", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 3 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "immich_system_info_memory{type=\"Free\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{type}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Free memory", + "type": "timeseries" + }, { "datasource": { "type": "prometheus", @@ -482,7 +697,7 @@ "h": 4, "w": 6, "x": 0, - "y": 3 + "y": 11 }, "hideTimeOverride": false, "id": 24, @@ -498,9 +713,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -549,7 +766,7 @@ "h": 4, "w": 6, "x": 6, - "y": 3 + "y": 11 }, "hideTimeOverride": false, "id": 26, @@ -565,9 +782,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -611,7 +830,7 @@ "h": 8, "w": 12, "x": 12, - "y": 3 + "y": 11 }, "id": 8, "options": { @@ -684,7 +903,7 @@ "h": 4, "w": 6, "x": 0, - "y": 7 + "y": 15 }, "hideTimeOverride": false, "id": 28, @@ -700,9 +919,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -748,7 +969,7 @@ "h": 4, "w": 6, "x": 6, - "y": 7 + "y": 15 }, "hideTimeOverride": false, "id": 30, @@ -764,9 +985,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -810,7 +1033,7 @@ "h": 4, "w": 6, "x": 0, - "y": 11 + "y": 19 }, "hideTimeOverride": false, "id": 32, @@ -826,9 +1049,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -873,7 +1098,7 @@ "h": 4, "w": 6, "x": 6, - "y": 11 + "y": 19 }, "hideTimeOverride": false, "id": 34, @@ -889,9 +1114,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -936,7 +1163,7 @@ "h": 8, "w": 12, "x": 12, - "y": 11 + "y": 19 }, "id": 4, "options": { @@ -1012,7 +1239,7 @@ "h": 4, "w": 6, "x": 0, - "y": 15 + "y": 23 }, "hideTimeOverride": false, "id": 36, @@ -1028,9 +1255,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -1076,7 +1305,7 @@ "h": 4, "w": 6, "x": 6, - "y": 15 + "y": 23 }, "hideTimeOverride": false, "id": 38, @@ -1092,9 +1321,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -1124,6 +1355,7 @@ "mode": "palette-classic" }, "custom": { + "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", @@ -1175,7 +1407,7 @@ "h": 7, "w": 24, "x": 0, - "y": 19 + "y": 27 }, "hideTimeOverride": false, "id": 22, @@ -1220,6 +1452,7 @@ "mode": "palette-classic" }, "custom": { + "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", @@ -1271,7 +1504,7 @@ "h": 7, "w": 24, "x": 0, - "y": 26 + "y": 34 }, "hideTimeOverride": false, "id": 47, @@ -1332,7 +1565,7 @@ "h": 4, "w": 6, "x": 0, - "y": 33 + "y": 41 }, "hideTimeOverride": false, "id": 42, @@ -1348,9 +1581,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -1396,7 +1631,7 @@ "h": 4, "w": 6, "x": 6, - "y": 33 + "y": 41 }, "hideTimeOverride": false, "id": 40, @@ -1412,9 +1647,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -1457,7 +1694,7 @@ "h": 8, "w": 12, "x": 12, - "y": 33 + "y": 41 }, "id": 6, "options": { @@ -1530,7 +1767,7 @@ "h": 4, "w": 6, "x": 0, - "y": 37 + "y": 45 }, "hideTimeOverride": false, "id": 44, @@ -1546,9 +1783,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -1594,7 +1833,7 @@ "h": 4, "w": 6, "x": 6, - "y": 37 + "y": 45 }, "hideTimeOverride": false, "id": 46, @@ -1610,9 +1849,11 @@ "fields": "", "values": false }, - "textMode": "auto" + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.0.0", "targets": [ { "datasource": { @@ -1642,6 +1883,7 @@ "mode": "palette-classic" }, "custom": { + "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", @@ -1693,7 +1935,7 @@ "h": 7, "w": 24, "x": 0, - "y": 41 + "y": 49 }, "hideTimeOverride": false, "id": 49, @@ -1738,6 +1980,7 @@ "mode": "palette-classic" }, "custom": { + "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", @@ -1789,7 +2032,7 @@ "h": 7, "w": 24, "x": 0, - "y": 48 + "y": 56 }, "hideTimeOverride": false, "id": 50, @@ -1832,13 +2075,13 @@ "list": [] }, "time": { - "from": "now-5m", + "from": "now-15m", "to": "now" }, "timepicker": {}, "timezone": "", "title": "immich", "uid": "ZWWp3aa4k", - "version": 31, + "version": 5, "weekStart": "" -} \ No newline at end of file +} diff --git a/grafana/screenshot.png b/grafana/screenshot.png index 18c5bfd..3b466cf 100644 Binary files a/grafana/screenshot.png and b/grafana/screenshot.png differ diff --git a/immich_exporter/exporter.py b/immich_exporter/exporter.py index 2c20ccb..b98ec15 100644 --- a/immich_exporter/exporter.py +++ b/immich_exporter/exporter.py @@ -5,6 +5,8 @@ import signal import faulthandler import requests +import psutil + from prometheus_client import start_http_server from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, REGISTRY import logging @@ -16,12 +18,22 @@ logger = logging.getLogger() class ImmichMetricsCollector: - def __init__(self, config): self.config = config - def collect(self): + def request(self, endpoint): + response = requests.request( + "GET", + self.combine_url(endpoint), + headers={ + "Accept": "application/json", + "x-api-key": self.config["token"] + } + ) + return response + + def collect(self): metrics = self.get_immich_metrics() for metric in metrics: @@ -40,44 +52,61 @@ class ImmichMetricsCollector: logger.info(prom_metric) def get_immich_metrics(self): - metrics = [] metrics.extend(self.get_immich_server_version_number()) metrics.extend(self.get_immich_storage()) - metrics.extend(self.get_immich_users_stat) - metrics.extend(self.get_immich_users_stat_growth()) + metrics.extend(self.get_immich_users_stat()) metrics.extend(self.get_system_stats()) return metrics - def get_immich_users_stat_growth(self): - + def get_immich_users_stat(self): try: endpoint_user_stats = "/api/server-info/statistics" - response_user_stats = requests.request( - "GET", - self.combine_url(endpoint_user_stats), - headers={'Accept': 'application/json', - "x-api-key": self.config["token"]} - ) + response_user_stats = self.request(endpoint_user_stats).json() except requests.exceptions.RequestException as e: - logger.error(f"Couldn't get server version: {e}") + logger.error(f"API ERROR: can't get server statistic: {e}") - user_data = response_user_stats.json()["usageByUser"] - # photos growth gauge - user_count = len(response_user_stats.json()["usageByUser"]) + user_data = response_user_stats["usageByUser"] + user_count = len(response_user_stats["usageByUser"]) photos_growth_total = 0 videos_growth_total = 0 usage_growth_total = 0 + metrics = [] + for x in range(0, user_count): photos_growth_total += user_data[x]["photos"] - # total video growth videos_growth_total += user_data[x]["videos"] - # total disk growth usage_growth_total += user_data[x]["usage"] + metrics.append( + { + "name": f"{self.config['metrics_prefix']}_server_stats_photos_by_users", + "value": user_data[x]['photos'], + "labels": {"firstName": user_data[x]["userName"].split()[0]}, + "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} " + } + ) + metrics.append( + { + "name": f"{self.config['metrics_prefix']}_server_stats_videos_by_users", + "value": user_data[x]['videos'], + "labels": {"firstName": user_data[x]["userName"].split()[0]}, + "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} " + } + ) + metrics.append( + { + "name": f"{self.config['metrics_prefix']}_server_stats_usage_by_users", + "value": (user_data[x]['usage']), + "labels": { + "firstName": user_data[x]["userName"].split()[0], + }, + "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} " + } + ) - return [ + metrics += [ { "name": f"{self.config['metrics_prefix']}_server_stats_user_count", "value": user_count, @@ -97,113 +126,39 @@ class ImmichMetricsCollector: "name": f"{self.config['metrics_prefix']}_server_stats_usage_growth", "value": usage_growth_total, "help": "videos counter that is added or removed" - } - + }, ] - @property - def get_immich_users_stat(self): - - global response_user_stats - try: - endpoint_user_stats = "/api/server-info/statistics" - response_user_stats = requests.request( - "GET", - self.combine_url(endpoint_user_stats), - headers={'Accept': 'application/json', - "x-api-key": self.config["token"]} - ) - except requests.exceptions.RequestException as e: - logger.error(f"API ERROR: can't get server statistic: {e}") - logger.info(f"API TOKEN CORRECT?") - logger.info(f"API ENDPOINT CHANGED?") - - metrics = [] - # To get the user count an api-endpoint exists but this works too. As a result one less api call is being made - - try: - 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 invalid this will return a KeyError : 'usage by user' - user_data = response_user_stats.json()["usageByUser"] - - for x in range(0, user_count): - metrics.append( - { - "name": f"{self.config['metrics_prefix']}_server_stats_photos_by_users", - "value": user_data[x]['photos'], - "labels": { - "firstName": user_data[x]["userName"].split()[0], - }, - "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} " - } - ) - - # videos - for x in range(0, user_count): - metrics.append( - { - "name": f"{self.config['metrics_prefix']}_server_stats_videos_by_users", - "value": user_data[x]['videos'], - "labels": { - "firstName": user_data[x]["userName"].split()[0], - }, - "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} " - } - ) - # usage - for x in range(0, user_count): - metrics.append( - { - "name": f"{self.config['metrics_prefix']}_server_stats_usage_by_users", - "value": (user_data[x]['usage']), - "labels": { - "firstName": user_data[x]["userName"].split()[0], - }, - "help": f"Number of photos by user {user_data[x]['userName'].split()[0]} " - } - ) - return metrics def get_immich_storage(self): try: endpoint_storage = "/api/server-info/storage" - response_storage = requests.request( - "GET", - self.combine_url(endpoint_storage), - headers={'Accept': 'application/json', - "x-api-key": self.config["token"]} - ) + response_storage = self.request(endpoint_storage).json() except requests.exceptions.RequestException as e: logger.error(f"Couldn't get storage info: {e}") - response_json = response_storage.json() - return [ { "name": f"{self.config['metrics_prefix']}_server_info_diskAvailable", - "value": (response_json["diskAvailableRaw"]), + "value": (response_storage["diskAvailableRaw"]), "help": "Available space on disk", }, { "name": f"{self.config['metrics_prefix']}_server_info_totalDiskSize", - "value": (response_json["diskSizeRaw"]), + "value": (response_storage["diskSizeRaw"]), "help": "total disk size", # "type": "counter" }, { "name": f"{self.config['metrics_prefix']}_server_info_diskUse", - "value": (response_json["diskUseRaw"]), + "value": (response_storage["diskUseRaw"]), "help": "disk space in use", # "type": "counter" }, { "name": f"{self.config['metrics_prefix']}_server_info_diskUsagePercentage", - "value": (response_json["diskUsagePercentage"]), + "value": (response_storage["diskUsagePercentage"]), "help": "disk usage in percent", # "type": "counter" } @@ -220,22 +175,15 @@ class ImmichMetricsCollector: while True: try: - - response_server_version = requests.request( - "GET", - self.combine_url(server_version_endpoint), - headers={'Accept': 'application/json', - "x-api-key": self.config["token"]} - ) + response = self.request(server_version_endpoint).json() except requests.exceptions.RequestException as e: logger.error(f"Couldn't get server version") continue break - server_version_number = (str(response_server_version.json()["major"]) + "." + - str(response_server_version.json()["minor"]) + "." + - str(response_server_version.json()["patch"]) - ) + server_version_number = ( + str(response["major"]) + "." + str(response["minor"]) + "." + str(response["patch"]) + ) return [ { @@ -249,24 +197,55 @@ class ImmichMetricsCollector: def get_system_stats(self): loadAvg = os.getloadavg() + virtualMem = psutil.virtual_memory() return [ { - "name": f"{self.config['metrics_prefix']}_system_info_loadAverage_1", - "value": (loadAvg[0]), + "name": f"{self.config['metrics_prefix']}_system_info_loadAverage", + "value": loadAvg[0], "help": "CPU Load average 1m", - "labels": {"Load Average": "1m"}, + "labels": {"period": "1m"}, }, { - "name": f"{self.config['metrics_prefix']}_system_info_loadAverage_5", - "value": (loadAvg[1]), + "name": f"{self.config['metrics_prefix']}_system_info_loadAverage", + "value": loadAvg[1], "help": "CPU Load average 5m", - "labels": {"Load Average": "5m"}, + "labels": {"period": "5m"}, }, { - "name": f"{self.config['metrics_prefix']}_system_info_loadAverage_15", - "value": (loadAvg[2]), + "name": f"{self.config['metrics_prefix']}_system_info_loadAverage", + "value": loadAvg[2], "help": "CPU Load average 15m", - "labels": {"Load Average": "15m"}, + "labels": {"period": "15m"}, + }, + { + "name": f"{self.config['metrics_prefix']}_system_info_memory", + "value": virtualMem[0], + "help": "Virtual Memory - Total", + "labels": {"type": "Total"}, + }, + { + "name": f"{self.config['metrics_prefix']}_system_info_memory", + "value": virtualMem[1], + "help": "Virtual Memory - Available", + "labels": {"type": "Available"}, + }, + { + "name": f"{self.config['metrics_prefix']}_system_info_memory", + "value": virtualMem[2], + "help": "Virtual Memory - Percent", + "labels": {"type": "Percent"}, + }, + { + "name": f"{self.config['metrics_prefix']}_system_info_memory", + "value": virtualMem[3], + "help": "Virtual Memory - Used", + "labels": {"type": "Used"}, + }, + { + "name": f"{self.config['metrics_prefix']}_system_info_memory", + "value": virtualMem[4], + "help": "Virtual Memory - Free", + "labels": {"type": "Free"}, }, ] @@ -274,7 +253,7 @@ class ImmichMetricsCollector: prefix_url = "http://" base_url = self.config["immich_host"] base_url_port = self.config["immich_port"] - combined_url = prefix_url + base_url + ":" + base_url_port + api_endpoint + combined_url = f"{prefix_url}{base_url}:{base_url_port}{api_endpoint}" return combined_url @@ -312,21 +291,19 @@ def get_config_value(key, default=""): def check_server_up(immichHost, immichPort): - # counter = 0 while True: counter = counter + 1 try: - requests.request( "GET", - "http://" + immichHost + ":" + immichPort + "/api/server-info/ping", + f"http://{immichHost}:{immichPort}/api/server-info/ping", headers={'Accept': 'application/json'} ) except requests.exceptions.RequestException as e: - logger.error(f"CONNECTION ERROR. Cannot reach immich at " + immichHost + ":" + immichPort + "." - f"Is immich up and running?") + logger.error( + f"CONNECTION ERROR. Cannot reach immich at {immichHost}:{immichPort}. Is immich up and running?") if 0 <= counter <= 60: time.sleep(1) elif 11 <= counter <= 300: @@ -335,21 +312,22 @@ def check_server_up(immichHost, immichPort): time.sleep(60) continue break - logger.info(f"Found immich up and running at " + immichHost + ":" + immichPort + ".") - logger.info(f"Attempting to connect to immich") + logger.info(f"Found immich up and running at {immichHost}:{immichPort}.") + logger.info("Attempting to connect to immich") time.sleep(1) - logger.info("Exporter v1.0.9") + logger.info("Exporter 1.2.0") def check_immich_api_key(immichHost, immichPort, immichApiKey): while True: try: - requests.request( "GET", - "http://" + immichHost + ":" + immichPort + "/api/server-info/", - headers={'Accept': 'application/json', - "x-api-key": immichApiKey} + f"http://{immichHost}:{immichPort}/api/server-info/", + headers={ + "Accept": "application/json", + "x-api-key": immichApiKey + } ) except requests.exceptions.RequestException as e: logger.error(f"CONNECTION ERROR. Possible API key error") diff --git a/setup.py b/setup.py index 280b451..af956f5 100644 --- a/setup.py +++ b/setup.py @@ -3,10 +3,12 @@ from setuptools import setup with open("README.md", "r") as fh: long_description = fh.read() +version = '1.2.0' + setup( name='prometheus-immich-exporter', packages=['immich_exporter'], - version='1.1.0', + version=version, long_description=long_description, long_description_content_type="text/markdown", description='Prometheus exporter for immich', @@ -18,7 +20,7 @@ setup( keywords=['prometheus', 'immich'], classifiers=[], python_requires='>=3', - install_requires=['attrdict==2.0.1', 'prometheus_client==0.19.0 ', 'requests==2.31.0', 'python-json-logger==2.0.7'], + install_requires=['attrdict==2.0.1', 'prometheus_client==0.19.0 ', 'requests==2.31.0', 'python-json-logger==2.0.7', 'psutil==5.9.8'], entry_points={ 'console_scripts': [ 'immich_exporter=immich_exporter.exporter:main',