Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prometheus_client/process_collector.py: 82%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

66 statements  

1import os 

2from typing import Callable, Iterable, Optional, Union 

3 

4from .metrics_core import CounterMetricFamily, GaugeMetricFamily, Metric 

5from .registry import Collector, CollectorRegistry, REGISTRY 

6 

7try: 

8 import resource 

9 

10 _PAGESIZE = resource.getpagesize() 

11except ImportError: 

12 # Not Unix 

13 _PAGESIZE = 4096 

14 

15 

16class ProcessCollector(Collector): 

17 """Collector for Standard Exports such as cpu and memory.""" 

18 

19 def __init__(self, 

20 namespace: str = '', 

21 pid: Callable[[], Union[int, str]] = lambda: 'self', 

22 proc: str = '/proc', 

23 registry: Optional[CollectorRegistry] = REGISTRY): 

24 self._namespace = namespace 

25 self._pid = pid 

26 self._proc = proc 

27 if namespace: 

28 self._prefix = namespace + '_process_' 

29 else: 

30 self._prefix = 'process_' 

31 self._ticks = 100.0 

32 try: 

33 self._ticks = os.sysconf('SC_CLK_TCK') 

34 except (ValueError, TypeError, AttributeError, OSError): 

35 pass 

36 

37 self._pagesize = _PAGESIZE 

38 

39 # This is used to test if we can access /proc. 

40 self._btime = 0 

41 try: 

42 self._btime = self._boot_time() 

43 except OSError: 

44 pass 

45 if registry: 

46 registry.register(self) 

47 

48 def _boot_time(self): 

49 with open(os.path.join(self._proc, 'stat'), 'rb') as stat: 

50 for line in stat: 

51 if line.startswith(b'btime '): 

52 return float(line.split()[1]) 

53 

54 def collect(self) -> Iterable[Metric]: 

55 if not self._btime: 

56 return [] 

57 

58 pid = os.path.join(self._proc, str(self._pid()).strip()) 

59 

60 result = [] 

61 try: 

62 with open(os.path.join(pid, 'stat'), 'rb') as stat: 

63 parts = (stat.read().split(b')')[-1].split()) 

64 

65 vmem = GaugeMetricFamily(self._prefix + 'virtual_memory_bytes', 

66 'Virtual memory size in bytes.', value=float(parts[20])) 

67 rss = GaugeMetricFamily(self._prefix + 'resident_memory_bytes', 'Resident memory size in bytes.', 

68 value=float(parts[21]) * self._pagesize) 

69 start_time_secs = float(parts[19]) / self._ticks 

70 start_time = GaugeMetricFamily(self._prefix + 'start_time_seconds', 

71 'Start time of the process since unix epoch in seconds.', 

72 value=start_time_secs + self._btime) 

73 utime = float(parts[11]) / self._ticks 

74 stime = float(parts[12]) / self._ticks 

75 cpu = CounterMetricFamily(self._prefix + 'cpu_seconds_total', 

76 'Total user and system CPU time spent in seconds.', 

77 value=utime + stime) 

78 result.extend([vmem, rss, start_time, cpu]) 

79 except OSError: 

80 pass 

81 

82 try: 

83 with open(os.path.join(pid, 'limits'), 'rb') as limits: 

84 for line in limits: 

85 if line.startswith(b'Max open file'): 

86 max_fds = GaugeMetricFamily(self._prefix + 'max_fds', 

87 'Maximum number of open file descriptors.', 

88 value=float(line.split()[3])) 

89 break 

90 open_fds = GaugeMetricFamily(self._prefix + 'open_fds', 

91 'Number of open file descriptors.', 

92 len(os.listdir(os.path.join(pid, 'fd')))) 

93 result.extend([open_fds, max_fds]) 

94 except OSError: 

95 pass 

96 

97 return result 

98 

99 

100PROCESS_COLLECTOR = ProcessCollector() 

101"""Default ProcessCollector in default Registry REGISTRY."""