_prometheus.py (5368B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\monolithmetrics\_prometheus.py 2 from __future__ import print_function 3 import re 4 import sys 5 import logging 6 from monolithconfig import on_client 7 prometheus_client = None 8 prometheus_registry = None 9 prometheus_port = 0 10 logger = logging.getLogger(__name__) 11 metric_name_regex = re.compile('[^a-zA-Z0-9_:]') 12 _metric_name_cache = {} 13 label_name_regex = re.compile('[^a-zA-Z0-9_]') 14 _label_name_cache = {} 15 _declared_metrics = {} 16 _metrics_id_cache = {} 17 18 def ugly_unittest_import_hack(): 19 import blue 20 import imp 21 import os 22 import platform 23 platform_name = 'Windows' if platform.system() == 'Windows' else 'macOS' 24 platform_arch = 'universal' if platform.system() == 'Darwin' else 'x64' 25 platform_toolset = 'v141' if platform.system() == 'Windows' else 'AppleClang' 26 module_name = 'prometheus_module.so' if platform.system() == 'Darwin' else 'prometheus_module.pyd' 27 module_path = os.path.join(blue.paths.ResolvePath(u'root:/'), '..', 'vendor', 'CCP', 'eve-monolith-prometheus', '74e681fa0f5d8974d593deba964dece93a5aae91', 'bin', platform_name, platform_arch, platform_toolset, module_name) 28 return imp.load_dynamic('prometheus_module', module_path) 29 30 31 if not on_client(): 32 try: 33 import prometheus_module 34 prometheus_client = prometheus_module 35 except ImportError: 36 prometheus_client = ugly_unittest_import_hack() 37 38 prometheus_registry = prometheus_client.MetricRegistry() 39 for i in range(9100, 10000): 40 serving = prometheus_registry.Serve(str(i)) 41 if serving: 42 prometheus_port = i 43 break 44 45 if prometheus_port == 0: 46 msg = 'Prometheus client failed to open a port' 47 logger.error(msg) 48 print(msg) 49 else: 50 msg = 'Prometheus client available on port {}'.format(prometheus_port) 51 logger.info(msg) 52 print(msg) 53 54 def _format_metric_name(metric): 55 if metric not in _metric_name_cache: 56 _metric_name_cache[metric] = metric_name_regex.sub('_', metric) 57 return _metric_name_cache.get(metric) 58 59 60 def _format_label_name(label): 61 if label not in _label_name_cache: 62 _label_name_cache[label] = label_name_regex.sub('_', label) 63 return _label_name_cache.get(label) 64 65 66 def _tags_to_label_dict(tags): 67 if tags is None: 68 return {} 69 result = {} 70 for tag in tags: 71 split = tag.split(':') 72 name = split[0] 73 name = _format_label_name(name) 74 result[name] = split[1] 75 76 return result 77 78 79 def _get_metric_hash(metric, labels = None): 80 hash_key = metric 81 if labels is not None: 82 if len(labels) <= 3: 83 hash_key = tuple(sorted(labels.keys())) + (metric,) 84 else: 85 hash_key = frozenset(labels.keys() + [metric]) 86 return _get_metric_hash_cached(hash_key) 87 88 89 def _get_metric_hash_cached(cached_hash_key): 90 if cached_hash_key not in _metrics_id_cache: 91 _metrics_id_cache[cached_hash_key] = hash(cached_hash_key) 92 return _metrics_id_cache[cached_hash_key] 93 94 95 def _get_prometheus_data(metric, tags): 96 labels_dict = _tags_to_label_dict(tags) 97 metric_id = _get_metric_hash(metric, labels_dict) 98 name = _format_metric_name(metric) 99 return (metric_id, name, labels_dict) 100 101 102 def gauge(metric, value, tags = None): 103 if not prometheus_client: 104 return 105 try: 106 metric_id, name, labels = _get_prometheus_data(metric, tags) 107 if metric_id not in _declared_metrics: 108 new_gauge = prometheus_registry.MakeGauge(name, labels=labels.keys()) 109 _declared_metrics[metric_id] = new_gauge 110 prom_gauge = _declared_metrics[metric_id] 111 prom_gauge.WithLabelValues(labels).Set(value) 112 except Exception: 113 logger.error('[prom] gauge metric failed', exc_info=sys.exc_info(), extra={'metric': metric, 114 'value': value, 115 'tags': tags}) 116 117 118 def increment(metric, value = 1, tags = None): 119 if not prometheus_client: 120 return 121 try: 122 metric_id, name, labels = _get_prometheus_data(metric, tags) 123 if metric_id not in _declared_metrics: 124 new_counter = prometheus_registry.MakeCounter(name, labels=labels.keys()) 125 _declared_metrics[metric_id] = new_counter 126 prom_counter = _declared_metrics[metric_id] 127 prom_counter.WithLabelValues(labels).Increment(value) 128 except Exception: 129 logger.error('[prom] counter metric failed', exc_info=sys.exc_info(), extra={'metric': metric, 130 'value': value, 131 'tags': tags}) 132 133 134 def histogram(metric, value, tags = None, buckets = None): 135 if not prometheus_client: 136 return 137 try: 138 metric_id, name, labels = _get_prometheus_data(metric, tags) 139 if metric_id not in _declared_metrics: 140 new_histogram = prometheus_registry.MakeHistogram(name, labels=labels.keys(), boundaries=list(buckets) or [0.1, 141 0.5, 142 1.0, 143 10.0]) 144 _declared_metrics[metric_id] = new_histogram 145 prom_histogram = _declared_metrics[metric_id] 146 prom_histogram.WithLabelValues(labels).Observe(value) 147 except Exception: 148 logger.error('[prom] histogram metric failed', exc_info=sys.exc_info(), extra={'metric': metric, 149 'value': value, 150 'tags': tags}) 151 152 153 def event(title, text = '', tags = None): 154 pass