Skip to content

Types of Metrics¤

  • Gauge stores single numerical values which can go up and down. Implements set method to set the metric values.
  • Counter is a cumulative metric whose values can increase or decrease. Implements add and sub methods.
  • Event per Second Counter (EPSCounter) divides all values by delta time.
  • DutyCycle measures the fraction of a period in which a signal/system is active https://en.wikipedia.org/wiki/Duty_cycle
  • AggregationCounter allows to set values based on an aggregation function. max function is default.
  • Histogram represents cumulative histogram with set method.

Counter, AggregationCounter, and Histogram come also in variants respecting dynamic tags. (See section Dynamic Tags)

asab.metrics.metrics.Gauge ¤

Bases: Metric

Source code in asab/metrics/metrics.py
class Gauge(Metric):

	def add_field(self, tags):
		field = {
			"tags": tags,
			"values": self.Init.copy() if self.Init is not None else dict(),
			"measured_at": self.App.time()
		}
		self.Storage['fieldset'].append(field)
		self._field = field
		return field

	def set(self, name: str, value):
		"""
		The function sets a value for a given value name and updates the 'measured_at' field with
		the current time.

		Args:
			name (str): The name of the value to be set.
			value: The value that you want to set for the given name in the field.
		"""
		self._field['values'][name] = value
		self._field['measured_at'] = self.App.time()

set(name, value) ¤

The function sets a value for a given value name and updates the 'measured_at' field with the current time.

Parameters:

Name Type Description Default
name str

The name of the value to be set.

required
value

The value that you want to set for the given name in the field.

required
Source code in asab/metrics/metrics.py
def set(self, name: str, value):
	"""
	The function sets a value for a given value name and updates the 'measured_at' field with
	the current time.

	Args:
		name (str): The name of the value to be set.
		value: The value that you want to set for the given name in the field.
	"""
	self._field['values'][name] = value
	self._field['measured_at'] = self.App.time()

asab.metrics.metrics.Counter ¤

Bases: Metric

Source code in asab/metrics/metrics.py
class Counter(Metric):

	def add_field(self, tags):
		field = {
			"tags": tags,
			"values": self.Init.copy() if self.Init is not None else dict(),
			"actuals": self.Init.copy() if self.Init is not None else dict(),
			"measured_at": self.App.time()
		}
		self.Storage['fieldset'].append(field)
		self._actuals = field['actuals']
		self._field = field
		return field

	def add(self, name: str, value, init_value: dict = None):
		"""
		The `add` function adds a specified value to a counter, and if the counter does not exist, it
		creates it and initializes it with an optional initial value.

		Args:
			name (str): Value name to which the `value` will be added.
			value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented.
			init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
				of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
				will be added to the `value` parameter and the result will be assigned as the value of the counter.
		"""
		try:
			self._actuals[name] += value
		except KeyError:
			if init_value is not None:
				self._actuals[name] = init_value + value
			else:
				self._actuals[name] = value
		if not self.Storage.get("reset"):
			self._field['measured_at'] = self.App.time()

	def sub(self, name: str, value, init_value: dict = None):
		"""
		The function subtracts a value from a variable and updates the 'measured_at' field.

		Args:
			name (str): The name of the variable or field that you want to subtract the value from.
			value: Value that needs to be added to the counter. It is the	amount by which the counter will be incremented.
			init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
				of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
				will be added to the `value` parameter and the result will be assigned as the value of the counter.
		"""

		try:
			self._actuals[name] -= value
		except KeyError:
			if init_value is not None:
				self._actuals[name] = init_value - value
			else:
				self._actuals[name] = -value
		if not self.Storage.get("reset"):
			self._field['measured_at'] = self.App.time()

	def flush(self, now):
		if self.Storage.get("reset") is True:
			self._field['measured_at'] = now
			for field in self.Storage['fieldset']:
				field['values'] = field['actuals']
				if self.Init is not None:
					field['actuals'] = self.Init.copy()
				else:
					field['actuals'] = dict()
				self._actuals = field['actuals']
		else:
			for field in self.Storage['fieldset']:
				field['values'] = field['actuals'].copy()

add(name, value, init_value=None) ¤

The add function adds a specified value to a counter, and if the counter does not exist, it creates it and initializes it with an optional initial value.

Parameters:

Name Type Description Default
name str

Value name to which the value will be added.

required
value

Value that needs to be added to the counter. It is the amount by which the counter will be incremented.

required
init_value dict

The init_value parameter is an optional parameter that specifies the initial value of the counter if it doesn't already exist in the counter values. If init_value is provided, it will be added to the value parameter and the result will be assigned as the value of the counter.

None
Source code in asab/metrics/metrics.py
def add(self, name: str, value, init_value: dict = None):
	"""
	The `add` function adds a specified value to a counter, and if the counter does not exist, it
	creates it and initializes it with an optional initial value.

	Args:
		name (str): Value name to which the `value` will be added.
		value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented.
		init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
			of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
			will be added to the `value` parameter and the result will be assigned as the value of the counter.
	"""
	try:
		self._actuals[name] += value
	except KeyError:
		if init_value is not None:
			self._actuals[name] = init_value + value
		else:
			self._actuals[name] = value
	if not self.Storage.get("reset"):
		self._field['measured_at'] = self.App.time()

sub(name, value, init_value=None) ¤

The function subtracts a value from a variable and updates the 'measured_at' field.

Parameters:

Name Type Description Default
name str

The name of the variable or field that you want to subtract the value from.

required
value

Value that needs to be added to the counter. It is the amount by which the counter will be incremented.

required
init_value dict

The init_value parameter is an optional parameter that specifies the initial value of the counter if it doesn't already exist in the counter values. If init_value is provided, it will be added to the value parameter and the result will be assigned as the value of the counter.

None
Source code in asab/metrics/metrics.py
def sub(self, name: str, value, init_value: dict = None):
	"""
	The function subtracts a value from a variable and updates the 'measured_at' field.

	Args:
		name (str): The name of the variable or field that you want to subtract the value from.
		value: Value that needs to be added to the counter. It is the	amount by which the counter will be incremented.
		init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
			of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
			will be added to the `value` parameter and the result will be assigned as the value of the counter.
	"""

	try:
		self._actuals[name] -= value
	except KeyError:
		if init_value is not None:
			self._actuals[name] = init_value - value
		else:
			self._actuals[name] = -value
	if not self.Storage.get("reset"):
		self._field['measured_at'] = self.App.time()

asab.metrics.metrics.EPSCounter ¤

Bases: Counter

Event per Second Counter Divides the count of event by a time difference between measurements. It effectively produces the EPS metric. The type of the metric is an integer (int).

Source code in asab/metrics/metrics.py
class EPSCounter(Counter):
	"""
	Event per Second Counter
	Divides the count of event by a time difference between measurements.
	It effectively produces the EPS metric.
	The type of the metric is an integer (int).
	"""

	def __init__(self, init_values=None):
		if init_values is not None:
			init_values = {k: int(v) for k, v in init_values.items()}
		super().__init__(init_values=init_values)
		self.LastTime = time.time()

	def flush(self, now):
		self._field['measured_at'] = now

		delta = now - self.LastTime
		if delta <= 0.0:
			return

		reset = self.Storage.get("reset")

		for field in self.Storage['fieldset']:
			field['values'] = {
				k: int(v / delta)
				for k, v in self._actuals.items()
			}

			if reset is True:
				if self.Init is not None:
					field['actuals'] = self.Init.copy()
				else:
					field['actuals'] = dict()
				self._actuals = field["actuals"]

				self.LastTime = now

asab.metrics.metrics.DutyCycle ¤

Bases: Metric

https://en.wikipedia.org/wiki/Duty_cycle

Source code in asab/metrics/metrics.py
class DutyCycle(Metric):
	'''
	https://en.wikipedia.org/wiki/Duty_cycle
	'''


	def __init__(self, app, init_values=None):
		super().__init__()
		self.App = app
		now = self.App.time()
		self.EmptyValue = {
			"on_off": None,
			"timestamp": now,
			"off_cycle": 0.0,
			"on_cycle": 0.0
		}

		self.Init = dict()

		if init_values is not None:
			for k, v in init_values.items():
				value = self.EmptyValue.copy()
				value["on_off"] = v
				self.Init[k] = value

	def add_field(self, tags):
		field = {
			"tags": tags,
			"actuals": self.Init.copy(),
			"values": dict(),
			"measured_at": self.App.time()
		}
		self.Storage['fieldset'].append(field)
		self._field = field
		return field


	def set(self, name: str, on_off: bool):
		"""
		The function `set` updates the state of a variable, tracking the duration of on and off cycles.

		Args:
			name (str): Name of the value that you want to set.
			on_off (bool): The `on_off` parameter is a boolean value that represents whether something is
			turned on. It is used to set the state of a particular item or feature.

		"""
		now = self.App.time()
		values = self._field["actuals"].get(name)
		if values is None:
			value = self.EmptyValue.copy()
			value["on_off"] = on_off
			value["timestamp"] = now
			self._field["actuals"][name] = value
			return

		if values.get("on_off") == on_off:
			return  # No change

		d = now - values.get("timestamp")
		off_cycle = values.get("off_cycle")
		on_cycle = values.get("on_cycle")
		if on_off:
			# From off to on
			off_cycle += d
		else:
			# From on to off
			on_cycle += d

		values["on_off"] = on_off
		values["timestamp"] = now
		values["off_cycle"] = off_cycle
		values["on_cycle"] = on_cycle


	def flush(self, now):
		self._field['measured_at'] = now
		for field in self.Storage["fieldset"]:
			actuals = field.get("actuals")
			for v_name, values in actuals.items():
				d = now - values.get("timestamp")
				off_cycle = values.get("off_cycle")
				on_cycle = values.get("on_cycle")
				if values.get("on_off"):
					on_cycle += d
				else:
					off_cycle += d

			full_cycle = on_cycle + off_cycle
			if full_cycle > 0.0:
				field["values"][v_name] = on_cycle / full_cycle

			new_value = self.EmptyValue.copy()
			new_value["on_off"] = values.get("on_off")
			new_value["timestamp"] = now

			field["actuals"][v_name] = new_value

set(name, on_off) ¤

The function set updates the state of a variable, tracking the duration of on and off cycles.

Parameters:

Name Type Description Default
name str

Name of the value that you want to set.

required
on_off bool

The on_off parameter is a boolean value that represents whether something is

required
Source code in asab/metrics/metrics.py
def set(self, name: str, on_off: bool):
	"""
	The function `set` updates the state of a variable, tracking the duration of on and off cycles.

	Args:
		name (str): Name of the value that you want to set.
		on_off (bool): The `on_off` parameter is a boolean value that represents whether something is
		turned on. It is used to set the state of a particular item or feature.

	"""
	now = self.App.time()
	values = self._field["actuals"].get(name)
	if values is None:
		value = self.EmptyValue.copy()
		value["on_off"] = on_off
		value["timestamp"] = now
		self._field["actuals"][name] = value
		return

	if values.get("on_off") == on_off:
		return  # No change

	d = now - values.get("timestamp")
	off_cycle = values.get("off_cycle")
	on_cycle = values.get("on_cycle")
	if on_off:
		# From off to on
		off_cycle += d
	else:
		# From on to off
		on_cycle += d

	values["on_off"] = on_off
	values["timestamp"] = now
	values["off_cycle"] = off_cycle
	values["on_cycle"] = on_cycle

asab.metrics.metrics.AggregationCounter ¤

Bases: Counter

Sets value aggregated with the last one. Takes a function object as the aggregator argument. The aggregation function can take two arguments only. Maximum is used as a default aggregation function.

Source code in asab/metrics/metrics.py
class AggregationCounter(Counter):
	'''
	Sets value aggregated with the last one.
	Takes a function object as the `aggregator` argument.
	The aggregation function can take two arguments only.
	Maximum is used as a default aggregation function.
	'''
	def __init__(self, init_values=None, aggregator=max):
		super().__init__(init_values=init_values)
		self.Aggregator = aggregator

	def set(self, name, value):
		"""
		The function sets a value in a dictionary, updating it if the key already exists, and also updates a
		'measured_at' field if a certain condition is met.

		Args:
			name: Name of the value being set.
			value: Value that you want to set for the given name.
		"""
		if not self.Storage.get("reset"):
			self._field['measured_at'] = self.App.time()
		try:
			self._actuals[name] = self.Aggregator(value, self._actuals[name])
		except KeyError:
			self._actuals[name] = value

	def add(self, name, value):
		raise NotImplementedError("Do not use add() method with AggregationCounter. Use set() instead.")

	def sub(self, name, value):
		raise NotImplementedError("Do not use sub() method with AggregationCounter. Use set() instead.")

set(name, value) ¤

The function sets a value in a dictionary, updating it if the key already exists, and also updates a 'measured_at' field if a certain condition is met.

Parameters:

Name Type Description Default
name

Name of the value being set.

required
value

Value that you want to set for the given name.

required
Source code in asab/metrics/metrics.py
def set(self, name, value):
	"""
	The function sets a value in a dictionary, updating it if the key already exists, and also updates a
	'measured_at' field if a certain condition is met.

	Args:
		name: Name of the value being set.
		value: Value that you want to set for the given name.
	"""
	if not self.Storage.get("reset"):
		self._field['measured_at'] = self.App.time()
	try:
		self._actuals[name] = self.Aggregator(value, self._actuals[name])
	except KeyError:
		self._actuals[name] = value

asab.metrics.metrics.Histogram ¤

Bases: Metric

Creates cumulative histograms.

Source code in asab/metrics/metrics.py
class Histogram(Metric):
	"""
	Creates cumulative histograms.
	"""
	def __init__(self, buckets: list, init_values=None):
		super().__init__(init_values)
		_buckets = [float(b) for b in buckets]

		if _buckets != sorted(buckets):
			raise ValueError("Buckets not in sorted order")

		if _buckets and _buckets[-1] != float("inf"):
			_buckets.append(float("inf"))

		if len(_buckets) < 2:
			raise ValueError("Must have at least two buckets")

		self.InitBuckets = {b: dict() for b in _buckets}
		self.Count = 0
		self.Sum = 0.0
		self.InitHistogram = {
			"buckets": self.InitBuckets,
			"sum": 0.0,
			"count": 0
		}

		if self.Init:
			for value_name, value in self.Init.items():
				for upper_bound in self.InitHistogram["buckets"]:
					if value <= upper_bound:
						self.InitHistogram["buckets"][upper_bound][value_name] = 1
				self.InitHistogram["sum"] += value
				self.InitHistogram["count"] += 1

	def add_field(self, tags):
		field = {
			"tags": tags,
			"values": copy.deepcopy(self.InitHistogram),
			"actuals": copy.deepcopy(self.InitHistogram),
			"measured_at": self.App.time()
		}
		self.Storage['fieldset'].append(field)
		self._actuals = field['actuals']
		self._field = field
		return field

	def flush(self, now):
		if self.Storage.get("reset") is True:
			self._field['measured_at'] = now
			for field in self.Storage['fieldset']:
				field['values'] = field['actuals']
				field['actuals'] = copy.deepcopy(self.InitHistogram)
				self._actuals = field['actuals']
		else:
			for field in self.Storage['fieldset']:
				field['values'] = copy.deepcopy(field['actuals'])

	def set(self, value_name, value):
		"""
		The function updates the values of the histogram based on the input value and value name.

		Args:
			value_name: String that represents the name of the value being set.
			value: Value that needs to be set.
		"""
		if not self.Storage.get("reset"):
			self._field['measured_at'] = self.App.time()
		buckets = self._actuals["buckets"]
		summary = self._actuals["sum"]
		count = self._actuals["count"]
		for upper_bound in buckets:
			if value <= upper_bound:
				if buckets[upper_bound].get(value_name) is None:
					buckets[upper_bound][value_name] = 1
				else:
					buckets[upper_bound][value_name] += 1
		self._actuals["sum"] = summary + value
		self._actuals["count"] = count + 1

set(value_name, value) ¤

The function updates the values of the histogram based on the input value and value name.

Parameters:

Name Type Description Default
value_name

String that represents the name of the value being set.

required
value

Value that needs to be set.

required
Source code in asab/metrics/metrics.py
def set(self, value_name, value):
	"""
	The function updates the values of the histogram based on the input value and value name.

	Args:
		value_name: String that represents the name of the value being set.
		value: Value that needs to be set.
	"""
	if not self.Storage.get("reset"):
		self._field['measured_at'] = self.App.time()
	buckets = self._actuals["buckets"]
	summary = self._actuals["sum"]
	count = self._actuals["count"]
	for upper_bound in buckets:
		if value <= upper_bound:
			if buckets[upper_bound].get(value_name) is None:
				buckets[upper_bound][value_name] = 1
			else:
				buckets[upper_bound][value_name] += 1
	self._actuals["sum"] = summary + value
	self._actuals["count"] = count + 1

asab.metrics.metrics.CounterWithDynamicTags ¤

Bases: MetricWithDynamicTags

Source code in asab/metrics/metrics.py
class CounterWithDynamicTags(MetricWithDynamicTags):


	def add_field(self, tags):
		field = {
			"tags": tags,
			"values": self.Init.copy() if self.Init is not None else dict(),
			"actuals": self.Init.copy() if self.Init is not None else dict(),
			"expires_at": self.App.time() + self.Expiration,
			"measured_at": self.App.time()
		}
		self.Storage['fieldset'].append(field)
		return field

	def add(self, name, value, tags):
		"""
		The `add` function adds a specified value to a counter, and if the counter does not exist, it
		creates it and initializes it with an optional initial value.

		Args:
			name (str): Value name to which the `value` will be added.
			value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented.
			init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
				of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
				will be added to the `value` parameter and the result will be assigned as the value of the counter.
			tags (dict): Dynamic tags appliying to this value.
		"""

		field = self.locate_field(tags)
		actuals = field['actuals']
		try:
			actuals[name] += value
		except KeyError:
			actuals[name] = value

		if self.Storage.get("reset") is False:
			field['measured_at'] = self.App.time()

		field["expires_at"] = self.App.time() + self.Expiration

	def sub(self, name, value, tags):
		"""
		The function subtracts a value from a variable and updates the 'measured_at' field.

		Args:
			name (str): The name of the variable or field that you want to subtract the value from.
			value: Value that needs to be added to the counter. It is the	amount by which the counter will be incremented.
			init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
				of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
				will be added to the `value` parameter and the result will be assigned as the value of the counter.
			tags (dict): Dynamic tags appliying to this value.
		"""

		field = self.locate_field(tags)
		actuals = field['actuals']
		try:
			actuals[name] -= value
		except KeyError:
			actuals[name] = -value

		if self.Storage.get("reset") is False:
			field['measured_at'] = self.App.time()

		field["expires_at"] = self.App.time() + self.Expiration

	def flush(self, now):
		# Filter expired fields
		for field in self.Storage["fieldset"][::-1]:
			if field["expires_at"] < now:
				self.Storage["fieldset"].remove(field)

		if self.Storage.get("reset") is True:
			for field in self.Storage['fieldset']:
				field['values'] = field['actuals']
				if self.Init is not None:
					field['actuals'] = self.Init.copy()
				else:
					field['actuals'] = dict()
				field['measured_at'] = self.App.time()
		else:
			for field in self.Storage['fieldset']:
				field['values'] = field['actuals'].copy()

add(name, value, tags) ¤

The add function adds a specified value to a counter, and if the counter does not exist, it creates it and initializes it with an optional initial value.

Parameters:

Name Type Description Default
name str

Value name to which the value will be added.

required
value

Value that needs to be added to the counter. It is the amount by which the counter will be incremented.

required
init_value dict

The init_value parameter is an optional parameter that specifies the initial value of the counter if it doesn't already exist in the counter values. If init_value is provided, it will be added to the value parameter and the result will be assigned as the value of the counter.

required
tags dict

Dynamic tags appliying to this value.

required
Source code in asab/metrics/metrics.py
def add(self, name, value, tags):
	"""
	The `add` function adds a specified value to a counter, and if the counter does not exist, it
	creates it and initializes it with an optional initial value.

	Args:
		name (str): Value name to which the `value` will be added.
		value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented.
		init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
			of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
			will be added to the `value` parameter and the result will be assigned as the value of the counter.
		tags (dict): Dynamic tags appliying to this value.
	"""

	field = self.locate_field(tags)
	actuals = field['actuals']
	try:
		actuals[name] += value
	except KeyError:
		actuals[name] = value

	if self.Storage.get("reset") is False:
		field['measured_at'] = self.App.time()

	field["expires_at"] = self.App.time() + self.Expiration

sub(name, value, tags) ¤

The function subtracts a value from a variable and updates the 'measured_at' field.

Parameters:

Name Type Description Default
name str

The name of the variable or field that you want to subtract the value from.

required
value

Value that needs to be added to the counter. It is the amount by which the counter will be incremented.

required
init_value dict

The init_value parameter is an optional parameter that specifies the initial value of the counter if it doesn't already exist in the counter values. If init_value is provided, it will be added to the value parameter and the result will be assigned as the value of the counter.

required
tags dict

Dynamic tags appliying to this value.

required
Source code in asab/metrics/metrics.py
def sub(self, name, value, tags):
	"""
	The function subtracts a value from a variable and updates the 'measured_at' field.

	Args:
		name (str): The name of the variable or field that you want to subtract the value from.
		value: Value that needs to be added to the counter. It is the	amount by which the counter will be incremented.
		init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value
			of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it
			will be added to the `value` parameter and the result will be assigned as the value of the counter.
		tags (dict): Dynamic tags appliying to this value.
	"""

	field = self.locate_field(tags)
	actuals = field['actuals']
	try:
		actuals[name] -= value
	except KeyError:
		actuals[name] = -value

	if self.Storage.get("reset") is False:
		field['measured_at'] = self.App.time()

	field["expires_at"] = self.App.time() + self.Expiration

asab.metrics.metrics.AggregationCounterWithDynamicTags ¤

Bases: CounterWithDynamicTags

Source code in asab/metrics/metrics.py
class AggregationCounterWithDynamicTags(CounterWithDynamicTags):


	def __init__(self, init_values=None, aggregator=max):
		super().__init__(init_values=init_values)
		self.Aggregator = aggregator

	def set(self, name, value, tags):
		"""
		The function sets a value for a given name and tags in a field, updates the measured_at and
		expires_at timestamps, and handles resetting the field if necessary.

		Args:
			name (str): String that represents the name of the value being set.
			value: Value that you want to set for a specific field.
			tags (dict): Dictionary of tags that are used to locate a specific field.
		"""
		field = self.locate_field(tags)
		actuals = field['actuals']
		try:
			actuals[name] = self.Aggregator(value, actuals[name])
		except KeyError:
			actuals[name] = value

		if self.Storage.get("reset") is False:
			field['measured_at'] = self.App.time()

		field["expires_at"] = self.App.time() + self.Expiration

	def add(self, name, value, tags):
		raise NotImplementedError("Do not use add() method with AggregationCounter. Use set() instead.")

	def sub(self, name, value, tags):
		raise NotImplementedError("Do not use sub() method with AggregationCounter. Use set() instead.")

set(name, value, tags) ¤

The function sets a value for a given name and tags in a field, updates the measured_at and expires_at timestamps, and handles resetting the field if necessary.

Parameters:

Name Type Description Default
name str

String that represents the name of the value being set.

required
value

Value that you want to set for a specific field.

required
tags dict

Dictionary of tags that are used to locate a specific field.

required
Source code in asab/metrics/metrics.py
def set(self, name, value, tags):
	"""
	The function sets a value for a given name and tags in a field, updates the measured_at and
	expires_at timestamps, and handles resetting the field if necessary.

	Args:
		name (str): String that represents the name of the value being set.
		value: Value that you want to set for a specific field.
		tags (dict): Dictionary of tags that are used to locate a specific field.
	"""
	field = self.locate_field(tags)
	actuals = field['actuals']
	try:
		actuals[name] = self.Aggregator(value, actuals[name])
	except KeyError:
		actuals[name] = value

	if self.Storage.get("reset") is False:
		field['measured_at'] = self.App.time()

	field["expires_at"] = self.App.time() + self.Expiration

asab.metrics.metrics.HistogramWithDynamicTags ¤

Bases: MetricWithDynamicTags

Creates cumulative histograms with dynamic tags

Source code in asab/metrics/metrics.py
class HistogramWithDynamicTags(MetricWithDynamicTags):
	"""
	Creates cumulative histograms with dynamic tags
	"""

	def __init__(self, buckets: list, init_values=None):
		super().__init__(init_values)
		_buckets = [float(b) for b in buckets]

		if _buckets != sorted(buckets):
			raise ValueError("Buckets not in sorted order")

		if _buckets and _buckets[-1] != float("inf"):
			_buckets.append(float("inf"))

		if len(_buckets) < 2:
			raise ValueError("Must have at least two buckets")

		self.InitBuckets = {b: dict() for b in _buckets}
		self.Count = 0
		self.Sum = 0.0
		self.InitHistogram = {
			"buckets": self.InitBuckets,
			"sum": 0.0,
			"count": 0
		}

		if self.Init:
			for value_name, value in self.Init.items():
				for upper_bound in self.InitHistogram["buckets"]:
					if value <= upper_bound:
						self.InitHistogram["buckets"][upper_bound][value_name] = 1
				self.InitHistogram["sum"] += value
				self.InitHistogram["count"] += 1

	def add_field(self, tags):
		field = {
			"tags": tags,
			"values": copy.deepcopy(self.InitHistogram),
			"actuals": copy.deepcopy(self.InitHistogram),
			"expires_at": self.App.time() + self.Expiration,
			"measured_at": self.App.time()
		}
		self.Storage['fieldset'].append(field)
		return field

	def flush(self, now):
		# Filter expired fields
		for field in self.Storage["fieldset"][::-1]:
			if field["expires_at"] < now:
				self.Storage["fieldset"].remove(field)

		if self.Storage.get("reset") is True:
			for field in self.Storage['fieldset']:
				field['values'] = field['actuals']
				field['actuals'] = copy.deepcopy(self.InitHistogram)
				field['measured_at'] = self.App.time()
		else:
			for field in self.Storage['fieldset']:
				field['values'] = copy.deepcopy(field['actuals'])

	def set(self, value_name, value, tags: dict):
		"""
		The function updates the values of the histogram based on the input value and value name.

		Args:
			value_name (str): String that represents the name of the value being set.
			value: Value that needs to be set.
			tags (dict): Dynamic tags appliying to this value.
		"""
		field = self.locate_field(tags)
		buckets = field.get("actuals").get("buckets")
		summary = field.get("actuals").get("sum")
		count = field.get("actuals").get("count")
		for upper_bound in buckets:
			if value <= upper_bound:
				if buckets[upper_bound].get(value_name) is None:
					buckets[upper_bound][value_name] = 1
				else:
					buckets[upper_bound][value_name] += 1
		field.get("actuals")["sum"] = summary + value
		field.get("actuals")["count"] = count + 1

		if self.Storage.get("reset") is False:
			field['measured_at'] = self.App.time()

		field["expires_at"] = self.App.time() + self.Expiration

set(value_name, value, tags) ¤

The function updates the values of the histogram based on the input value and value name.

Parameters:

Name Type Description Default
value_name str

String that represents the name of the value being set.

required
value

Value that needs to be set.

required
tags dict

Dynamic tags appliying to this value.

required
Source code in asab/metrics/metrics.py
def set(self, value_name, value, tags: dict):
	"""
	The function updates the values of the histogram based on the input value and value name.

	Args:
		value_name (str): String that represents the name of the value being set.
		value: Value that needs to be set.
		tags (dict): Dynamic tags appliying to this value.
	"""
	field = self.locate_field(tags)
	buckets = field.get("actuals").get("buckets")
	summary = field.get("actuals").get("sum")
	count = field.get("actuals").get("count")
	for upper_bound in buckets:
		if value <= upper_bound:
			if buckets[upper_bound].get(value_name) is None:
				buckets[upper_bound][value_name] = 1
			else:
				buckets[upper_bound][value_name] += 1
	field.get("actuals")["sum"] = summary + value
	field.get("actuals")["count"] = count + 1

	if self.Storage.get("reset") is False:
		field['measured_at'] = self.App.time()

	field["expires_at"] = self.App.time() + self.Expiration