This commit is contained in:
@@ -6,22 +6,25 @@ from typing import (
|
||||
Any, Callable, Dict, Iterable, List, Literal, Optional, Sequence, Tuple,
|
||||
Type, TypeVar, Union,
|
||||
)
|
||||
import warnings
|
||||
|
||||
from . import values # retain this import style for testability
|
||||
from .context_managers import ExceptionCounter, InprogressTracker, Timer
|
||||
from .metrics_core import (
|
||||
Metric, METRIC_LABEL_NAME_RE, METRIC_NAME_RE,
|
||||
RESERVED_METRIC_LABEL_NAME_RE,
|
||||
)
|
||||
from .metrics_core import Metric
|
||||
from .registry import Collector, CollectorRegistry, REGISTRY
|
||||
from .samples import Exemplar, Sample
|
||||
from .utils import floatToGoString, INF
|
||||
from .validation import (
|
||||
_validate_exemplar, _validate_labelnames, _validate_metric_name,
|
||||
)
|
||||
|
||||
T = TypeVar('T', bound='MetricWrapperBase')
|
||||
F = TypeVar("F", bound=Callable[..., Any])
|
||||
|
||||
|
||||
def _build_full_name(metric_type, name, namespace, subsystem, unit):
|
||||
if not name:
|
||||
raise ValueError('Metric name should not be empty')
|
||||
full_name = ''
|
||||
if namespace:
|
||||
full_name += namespace + '_'
|
||||
@@ -37,31 +40,6 @@ def _build_full_name(metric_type, name, namespace, subsystem, unit):
|
||||
return full_name
|
||||
|
||||
|
||||
def _validate_labelname(l):
|
||||
if not METRIC_LABEL_NAME_RE.match(l):
|
||||
raise ValueError('Invalid label metric name: ' + l)
|
||||
if RESERVED_METRIC_LABEL_NAME_RE.match(l):
|
||||
raise ValueError('Reserved label metric name: ' + l)
|
||||
|
||||
|
||||
def _validate_labelnames(cls, labelnames):
|
||||
labelnames = tuple(labelnames)
|
||||
for l in labelnames:
|
||||
_validate_labelname(l)
|
||||
if l in cls._reserved_labelnames:
|
||||
raise ValueError('Reserved label metric name: ' + l)
|
||||
return labelnames
|
||||
|
||||
|
||||
def _validate_exemplar(exemplar):
|
||||
runes = 0
|
||||
for k, v in exemplar.items():
|
||||
_validate_labelname(k)
|
||||
runes += len(k)
|
||||
runes += len(v)
|
||||
if runes > 128:
|
||||
raise ValueError('Exemplar labels have %d UTF-8 characters, exceeding the limit of 128')
|
||||
|
||||
|
||||
def _get_use_created() -> bool:
|
||||
return os.environ.get("PROMETHEUS_DISABLE_CREATED_SERIES", 'False').lower() not in ('true', '1', 't')
|
||||
@@ -110,8 +88,8 @@ class MetricWrapperBase(Collector):
|
||||
|
||||
def collect(self) -> Iterable[Metric]:
|
||||
metric = self._get_metric()
|
||||
for suffix, labels, value, timestamp, exemplar in self._samples():
|
||||
metric.add_sample(self._name + suffix, labels, value, timestamp, exemplar)
|
||||
for suffix, labels, value, timestamp, exemplar, native_histogram_value in self._samples():
|
||||
metric.add_sample(self._name + suffix, labels, value, timestamp, exemplar, native_histogram_value)
|
||||
return [metric]
|
||||
|
||||
def __str__(self) -> str:
|
||||
@@ -138,8 +116,7 @@ class MetricWrapperBase(Collector):
|
||||
self._documentation = documentation
|
||||
self._unit = unit
|
||||
|
||||
if not METRIC_NAME_RE.match(self._name):
|
||||
raise ValueError('Invalid metric name: ' + self._name)
|
||||
_validate_metric_name(self._name)
|
||||
|
||||
if self._is_parent():
|
||||
# Prepare the fields needed for child metrics.
|
||||
@@ -210,6 +187,11 @@ class MetricWrapperBase(Collector):
|
||||
return self._metrics[labelvalues]
|
||||
|
||||
def remove(self, *labelvalues: Any) -> None:
|
||||
if 'prometheus_multiproc_dir' in os.environ or 'PROMETHEUS_MULTIPROC_DIR' in os.environ:
|
||||
warnings.warn(
|
||||
"Removal of labels has not been implemented in multi-process mode yet.",
|
||||
UserWarning)
|
||||
|
||||
if not self._labelnames:
|
||||
raise ValueError('No label names were set when constructing %s' % self)
|
||||
|
||||
@@ -218,10 +200,15 @@ class MetricWrapperBase(Collector):
|
||||
raise ValueError('Incorrect label count (expected %d, got %s)' % (len(self._labelnames), labelvalues))
|
||||
labelvalues = tuple(str(l) for l in labelvalues)
|
||||
with self._lock:
|
||||
del self._metrics[labelvalues]
|
||||
if labelvalues in self._metrics:
|
||||
del self._metrics[labelvalues]
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Remove all labelsets from the metric"""
|
||||
if 'prometheus_multiproc_dir' in os.environ or 'PROMETHEUS_MULTIPROC_DIR' in os.environ:
|
||||
warnings.warn(
|
||||
"Clearing labels has not been implemented in multi-process mode yet",
|
||||
UserWarning)
|
||||
with self._lock:
|
||||
self._metrics = {}
|
||||
|
||||
@@ -236,8 +223,8 @@ class MetricWrapperBase(Collector):
|
||||
metrics = self._metrics.copy()
|
||||
for labels, metric in metrics.items():
|
||||
series_labels = list(zip(self._labelnames, labels))
|
||||
for suffix, sample_labels, value, timestamp, exemplar in metric._samples():
|
||||
yield Sample(suffix, dict(series_labels + list(sample_labels.items())), value, timestamp, exemplar)
|
||||
for suffix, sample_labels, value, timestamp, exemplar, native_histogram_value in metric._samples():
|
||||
yield Sample(suffix, dict(series_labels + list(sample_labels.items())), value, timestamp, exemplar, native_histogram_value)
|
||||
|
||||
def _child_samples(self) -> Iterable[Sample]: # pragma: no cover
|
||||
raise NotImplementedError('_child_samples() must be implemented by %r' % self)
|
||||
@@ -282,6 +269,12 @@ class Counter(MetricWrapperBase):
|
||||
# Count only one type of exception
|
||||
with c.count_exceptions(ValueError):
|
||||
pass
|
||||
|
||||
You can also reset the counter to zero in case your logical "process" restarts
|
||||
without restarting the actual python process.
|
||||
|
||||
c.reset()
|
||||
|
||||
"""
|
||||
_type = 'counter'
|
||||
|
||||
@@ -300,6 +293,11 @@ class Counter(MetricWrapperBase):
|
||||
_validate_exemplar(exemplar)
|
||||
self._value.set_exemplar(Exemplar(exemplar, amount, time.time()))
|
||||
|
||||
def reset(self) -> None:
|
||||
"""Reset the counter to zero. Use this when a logical process restarts without restarting the actual python process."""
|
||||
self._value.set(0)
|
||||
self._created = time.time()
|
||||
|
||||
def count_exceptions(self, exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]] = Exception) -> ExceptionCounter:
|
||||
"""Count exceptions in a block of code or function.
|
||||
|
||||
@@ -684,6 +682,8 @@ class Info(MetricWrapperBase):
|
||||
if self._labelname_set.intersection(val.keys()):
|
||||
raise ValueError('Overlapping labels for Info metric, metric: {} child: {}'.format(
|
||||
self._labelnames, val))
|
||||
if any(i is None for i in val.values()):
|
||||
raise ValueError('Label value cannot be None')
|
||||
with self._lock:
|
||||
self._value = dict(val)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user