Replace three custom Prometheus textfile collector scripts with
dedicated community-maintained exporters:
- jellyfin-collector.nix (25 LoC shell) -> rebelcore/jellyfin_exporter
Metric: jellyfin_active_streams -> count(jellyfin_now_playing_state)
Bonus: per-session labels (user, title, device, codec info)
- qbittorrent-collector.nix (40 LoC shell) -> anriha/qbittorrent-metrics-exporter
Metric: qbittorrent_{download,upload}_bytes_per_second -> qbit_{dl,up}speed
Bonus: per-torrent metrics with category/tag aggregation
- intel-gpu-collector.nix + .py (130 LoC Python) -> mike1808/igpu-exporter
Metric: intel_gpu_engine_busy_percent -> igpu_engines_busy_percent
Bonus: persistent daemon vs oneshot timer, no streaming JSON parser
All three run as persistent daemons scraped by Prometheus, replacing
the textfile-collector pattern of systemd timers writing .prom files.
Dashboard PromQL queries updated to match new metric names.
113 lines
4.2 KiB
Nix
113 lines
4.2 KiB
Nix
{
|
|
config,
|
|
pkgs,
|
|
inputs,
|
|
service_configs,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
jellyfinExporterPort = service_configs.ports.private.jellyfin_exporter.port;
|
|
qbitExporterPort = service_configs.ports.private.qbittorrent_exporter.port;
|
|
igpuExporterPort = service_configs.ports.private.igpu_exporter.port;
|
|
in
|
|
{
|
|
# -- Jellyfin Prometheus Exporter --
|
|
# Replaces custom jellyfin-collector.nix textfile timer.
|
|
# Exposes per-session metrics (jellyfin_now_playing_state) and library stats.
|
|
systemd.services.jellyfin-exporter =
|
|
lib.mkIf (config.services.grafana.enable && config.services.jellyfin.enable)
|
|
{
|
|
description = "Prometheus exporter for Jellyfin";
|
|
after = [
|
|
"network.target"
|
|
"jellyfin.service"
|
|
];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig = {
|
|
ExecStart = lib.getExe (
|
|
pkgs.writeShellApplication {
|
|
name = "jellyfin-exporter-wrapper";
|
|
runtimeInputs = [ pkgs.jellyfin-exporter ];
|
|
text = ''
|
|
exec jellyfin_exporter \
|
|
--jellyfin.address=http://127.0.0.1:${toString service_configs.ports.private.jellyfin.port} \
|
|
--jellyfin.token="$(cat "$CREDENTIALS_DIRECTORY/jellyfin-api-key")" \
|
|
--web.listen-address=127.0.0.1:${toString jellyfinExporterPort}
|
|
'';
|
|
}
|
|
);
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
DynamicUser = true;
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
MemoryDenyWriteExecute = true;
|
|
LoadCredential = "jellyfin-api-key:${config.age.secrets.jellyfin-api-key.path}";
|
|
};
|
|
};
|
|
|
|
# -- qBittorrent Prometheus Exporter --
|
|
# Replaces custom qbittorrent-collector.nix textfile timer.
|
|
# Exposes per-torrent metrics (qbit_dlspeed, qbit_upspeed) and aggregate stats.
|
|
# qBittorrent runs in a VPN namespace; the exporter reaches it via namespace address.
|
|
systemd.services.qbittorrent-exporter =
|
|
lib.mkIf (config.services.grafana.enable && config.services.qbittorrent.enable)
|
|
{
|
|
description = "Prometheus exporter for qBittorrent";
|
|
after = [
|
|
"network.target"
|
|
"qbittorrent.service"
|
|
];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig = {
|
|
ExecStart =
|
|
lib.getExe' inputs.qbittorrent-metrics-exporter.packages.${pkgs.system}.default
|
|
"qbittorrent-metrics-exporter";
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
DynamicUser = true;
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
};
|
|
environment = {
|
|
HOST = "127.0.0.1";
|
|
PORT = toString qbitExporterPort;
|
|
SCRAPE_INTERVAL = "15";
|
|
BACKEND = "in-memory";
|
|
# qBittorrent has AuthSubnetWhitelist=0.0.0.0/0, so no real password needed.
|
|
# The exporter still expects the env var to be set.
|
|
QBITTORRENT_PASSWORD = "unused";
|
|
QBITTORRENT_USERNAME = "admin";
|
|
TORRENT_HOSTS = "qbit:main=http://${config.vpnNamespaces.wg.namespaceAddress}:${toString config.services.qbittorrent.webuiPort}|http://${config.vpnNamespaces.wg.namespaceAddress}:${toString config.services.qbittorrent.webuiPort}";
|
|
RUST_LOG = "warn";
|
|
};
|
|
};
|
|
|
|
# -- Intel GPU Prometheus Exporter --
|
|
# Replaces custom intel-gpu-collector.nix + intel-gpu-collector.py textfile timer.
|
|
# Exposes engine busy%, frequency, and RC6 metrics via /metrics.
|
|
# Requires privileged access to GPU debug interfaces (intel_gpu_top).
|
|
systemd.services.igpu-exporter = lib.mkIf config.services.grafana.enable {
|
|
description = "Prometheus exporter for Intel integrated GPU";
|
|
wantedBy = [ "multi-user.target" ];
|
|
path = [ pkgs.intel-gpu-tools ];
|
|
serviceConfig = {
|
|
ExecStart = lib.getExe pkgs.igpu-exporter;
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
# intel_gpu_top requires root-level access to GPU debug interfaces
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
};
|
|
environment = {
|
|
PORT = toString igpuExporterPort;
|
|
REFRESH_PERIOD_MS = "30000";
|
|
};
|
|
};
|
|
}
|