Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/prometheus_client/values.py: 17%

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

87 statements  

1import os 

2from threading import Lock 

3import warnings 

4 

5from .mmap_dict import mmap_key, MmapedDict 

6 

7 

8class MutexValue: 

9 """A float protected by a mutex.""" 

10 

11 _multiprocess = False 

12 

13 def __init__(self, typ, metric_name, name, labelnames, labelvalues, help_text, **kwargs): 

14 self._value = 0.0 

15 self._exemplar = None 

16 self._lock = Lock() 

17 

18 def inc(self, amount): 

19 with self._lock: 

20 self._value += amount 

21 

22 def set(self, value, timestamp=None): 

23 with self._lock: 

24 self._value = value 

25 

26 def set_exemplar(self, exemplar): 

27 with self._lock: 

28 self._exemplar = exemplar 

29 

30 def get(self): 

31 with self._lock: 

32 return self._value 

33 

34 def get_exemplar(self): 

35 with self._lock: 

36 return self._exemplar 

37 

38 

39def MultiProcessValue(process_identifier=os.getpid): 

40 """Returns a MmapedValue class based on a process_identifier function. 

41 

42 The 'process_identifier' function MUST comply with this simple rule: 

43 when called in simultaneously running processes it MUST return distinct values. 

44 

45 Using a different function than the default 'os.getpid' is at your own risk. 

46 """ 

47 files = {} 

48 values = [] 

49 pid = {'value': process_identifier()} 

50 # Use a single global lock when in multi-processing mode 

51 # as we presume this means there is no threading going on. 

52 # This avoids the need to also have mutexes in __MmapDict. 

53 lock = Lock() 

54 

55 class MmapedValue: 

56 """A float protected by a mutex backed by a per-process mmaped file.""" 

57 

58 _multiprocess = True 

59 

60 def __init__(self, typ, metric_name, name, labelnames, labelvalues, help_text, multiprocess_mode='', **kwargs): 

61 self._params = typ, metric_name, name, labelnames, labelvalues, help_text, multiprocess_mode 

62 # This deprecation warning can go away in a few releases when removing the compatibility 

63 if 'prometheus_multiproc_dir' in os.environ and 'PROMETHEUS_MULTIPROC_DIR' not in os.environ: 

64 os.environ['PROMETHEUS_MULTIPROC_DIR'] = os.environ['prometheus_multiproc_dir'] 

65 warnings.warn("prometheus_multiproc_dir variable has been deprecated in favor of the upper case naming PROMETHEUS_MULTIPROC_DIR", DeprecationWarning) 

66 with lock: 

67 self.__check_for_pid_change() 

68 self.__reset() 

69 values.append(self) 

70 

71 def __reset(self): 

72 typ, metric_name, name, labelnames, labelvalues, help_text, multiprocess_mode = self._params 

73 if typ == 'gauge': 

74 file_prefix = typ + '_' + multiprocess_mode 

75 else: 

76 file_prefix = typ 

77 if file_prefix not in files: 

78 filename = os.path.join( 

79 os.environ.get('PROMETHEUS_MULTIPROC_DIR'), 

80 '{}_{}.db'.format(file_prefix, pid['value'])) 

81 

82 files[file_prefix] = MmapedDict(filename) 

83 self._file = files[file_prefix] 

84 self._key = mmap_key(metric_name, name, labelnames, labelvalues, help_text) 

85 self._value, self._timestamp = self._file.read_value(self._key) 

86 

87 def __check_for_pid_change(self): 

88 actual_pid = process_identifier() 

89 if pid['value'] != actual_pid: 

90 pid['value'] = actual_pid 

91 # There has been a fork(), reset all the values. 

92 for f in files.values(): 

93 f.close() 

94 files.clear() 

95 for value in values: 

96 value.__reset() 

97 

98 def inc(self, amount): 

99 with lock: 

100 self.__check_for_pid_change() 

101 self._value += amount 

102 self._timestamp = 0.0 

103 self._file.write_value(self._key, self._value, self._timestamp) 

104 

105 def set(self, value, timestamp=None): 

106 with lock: 

107 self.__check_for_pid_change() 

108 self._value = value 

109 self._timestamp = timestamp or 0.0 

110 self._file.write_value(self._key, self._value, self._timestamp) 

111 

112 def set_exemplar(self, exemplar): 

113 # TODO: Implement exemplars for multiprocess mode. 

114 return 

115 

116 def get(self): 

117 with lock: 

118 self.__check_for_pid_change() 

119 return self._value 

120 

121 def get_exemplar(self): 

122 # TODO: Implement exemplars for multiprocess mode. 

123 return None 

124 

125 return MmapedValue 

126 

127 

128def get_value_class(): 

129 # Should we enable multi-process mode? 

130 # This needs to be chosen before the first metric is constructed, 

131 # and as that may be in some arbitrary library the user/admin has 

132 # no control over we use an environment variable. 

133 if 'prometheus_multiproc_dir' in os.environ or 'PROMETHEUS_MULTIPROC_DIR' in os.environ: 

134 return MultiProcessValue() 

135 else: 

136 return MutexValue 

137 

138 

139ValueClass = get_value_class()