prometheus-nixos-exporter: add nix 2.19.0 compat
The output of `nix path-info --json` changed from a list to an object in nix 2.19.0. Add a simple version detection, so we can support both output formats. Fixes: #346
Martin Weinelt committed
Feb 3, 2024 at 17:45 UTC
c1e5ad598da171864e6f3d7a05c477fc29e19958
2 files changed
+34
-10
modules/prometheus/default.nix
+3
-2
@@ -28,8 +28,9 @@
28
Restart = "always";
29
RestartSec = "60s";
30
ExecStart = let
31
- python = pkgs.python3.withPackages (p: [
32
- p.prometheus_client
31
+ python = pkgs.python3.withPackages (ps: with ps; [
32
+ packaging
33
+ prometheus-client
34
]);
35
in ''
36
${python}/bin/python ${./nixos-exporter.py}
modules/prometheus/nixos-exporter.py
+31
-8
@@ -1,15 +1,33 @@
1
#!/usr/bin/env nix-shell
2
-#!nix-shell -i python3 -p python3 -p python3Packages.prometheus_client
2
+#!nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ prometheus-client packaging ])"
3
4
5
import subprocess
6
import json
7
-from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily
8
-from prometheus_client import CollectorRegistry, generate_latest, start_http_server
9
-from pprint import pprint
7
+import sys
8
import time
9
+from packaging.version import Version
10
+from prometheus_client.core import GaugeMetricFamily
11
+from prometheus_client import CollectorRegistry, start_http_server
12
+
13
14
class NixosSystemCollector:
15
+ def __init__(self):
16
+ nix_version = self.get_nix_version()
17
+
18
+ # https://github.com/NixOS/nix/pull/9242
19
+ self.nix_path_info_returns_object = nix_version >= Version("2.19.0")
20
+
21
+ def get_nix_version(self):
22
+ result = subprocess.run(["nix", "--version"], stdout=subprocess.PIPE)
23
+
24
+ if result.returncode == 0:
25
+ response = result.stdout.decode().strip()
26
+ return Version(response.split()[-1])
27
+ else:
28
+ print("Failed to determine nix version", file=sys.stderr)
29
+ sys.exit(1)
30
+
31
def collect(self):
32
# note: Gauges because of rollbacks.
33
current_system = GaugeMetricFamily(
@@ -40,14 +58,19 @@ class NixosSystemCollector:
58
return None
59
60
def get_time(self, path):
43
- # nix path-info --json /run/booted-system | jq .[0].registrationTime
61
result = subprocess.run(
45
- [ "nix", "path-info", "--json", path ],
46
- stdout=subprocess.PIPE
62
+ ["nix", "path-info", "--json", path], stdout=subprocess.PIPE
63
)
64
if result.returncode == 0:
65
parsed = json.loads(result.stdout)
50
- return parsed[0]['registrationTime']
66
+
67
+ if self.nix_path_info_returns_object:
68
+ # nix path-info --json /run/booted-system | jq .[].registrationTime
69
+ for path_info in parsed.values():
70
+ return path_info["registrationTime"]
71
+ else:
72
+ # nix path-info --json /run/booted-system | jq .[0].registrationTime
73
+ return parsed[0]["registrationTime"]
74
75
return 0
76