Skip to content

Commit ddcc305

Browse files
authored
fix: bind max_fds before using it in the process collector (#1231)
Signed-off-by: PerryLink <255665900+PerryLink@users.noreply.github.com> Co-authored-by: PerryLink <255665900+PerryLink@users.noreply.github.com>
1 parent 2301464 commit ddcc305

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

‎prometheus_client/process_collector.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def collect(self) -> Iterable[Metric]:
7979
except OSError:
8080
pass
8181

82+
max_fds: Optional[GaugeMetricFamily] = None
8283
try:
8384
with open(os.path.join(pid, 'limits'), 'rb') as limits:
8485
for line in limits:
@@ -90,7 +91,9 @@ def collect(self) -> Iterable[Metric]:
9091
open_fds = GaugeMetricFamily(self._prefix + 'open_fds',
9192
'Number of open file descriptors.',
9293
len(os.listdir(os.path.join(pid, 'fd'))))
93-
result.extend([open_fds, max_fds])
94+
result.append(open_fds)
95+
if max_fds is not None:
96+
result.append(max_fds)
9497
except OSError:
9598
pass
9699

‎tests/test_process_collector.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import tempfile
23
import unittest
34

45
from prometheus_client import CollectorRegistry, ProcessCollector
@@ -47,6 +48,27 @@ def test_working_584(self):
4748
self.assertEqual(None, self.registry.get_sample_value('process_max_fds'))
4849
self.assertEqual(None, self.registry.get_sample_value('process_open_fds'))
4950

51+
def test_limits_without_max_open_files(self):
52+
# A readable limits file is not guaranteed to contain the
53+
# "Max open files" line, see
54+
# https://github.com/home-assistant/core/issues/140045. The collector
55+
# used to raise UnboundLocalError (and with it break the import of
56+
# prometheus_client), instead of just omitting process_max_fds.
57+
with tempfile.TemporaryDirectory() as tmpdir:
58+
proc = os.path.join(tmpdir, 'proc')
59+
os.makedirs(os.path.join(proc, '123', 'fd'))
60+
with open(os.path.join(proc, 'stat'), 'wb') as stat:
61+
stat.write(b'btime 1234567890\n')
62+
with open(os.path.join(proc, '123', 'limits'), 'wb') as limits:
63+
limits.write(b'Limit Soft Limit Hard Limit Units\n'
64+
b'Max cpu time unlimited unlimited seconds\n'
65+
b'Max open fides 2048 4096 files\n')
66+
registry = CollectorRegistry(auto_describe=True)
67+
ProcessCollector(proc=proc, pid=lambda: 123, registry=registry)
68+
69+
self.assertEqual(0.0, registry.get_sample_value('process_open_fds'))
70+
self.assertEqual(None, registry.get_sample_value('process_max_fds'))
71+
5072
def test_working_fake_pid(self):
5173
collector = ProcessCollector(proc=self.test_proc, pid=lambda: 123, registry=self.registry)
5274
collector._ticks = 100

0 commit comments

Comments
 (0)