Metrics service

Metrics document state of the application in a timescale manner. For further analysis, connect your ASAB application to a time-series database. ASAB could feed metrica into InfluxDB and Prometheus.

Use of a Metrics Service

Create new metrics using MetricsService.

Example of counter initialization:

class MyApplication(asab.Application):
    async def initialize(self):
        from asab.metrics import Module
        self.add_module(Module)
        self.MetricsService = self.get_service('asab.MetricsService')
        self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0})

if __name__ == '__main__':
    app = MyApplication()
    app.run()

See full example here: https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py

Lisf 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 https://en.wikipedia.org/wiki/Duty_cycle
  • AggregationCounter allows to set() values based on an aggregation function. max() function is default.

All metrics types inherit from Metric class.

Enable logging of metrics

Metrics can be displayed in the log of the ASAB application. In order to enable this, enter following lines in the configuration:

[logging]
levels=
   asab.metrics INFO

InfluxDB

Metrics can be collected in Influx time-series database.

Example of your ASAB application configuration enabeling Influx connection.

[asab:metrics]
target=influxdb

[asab:metrics:influxdb]
url=http://localhost:8086/
db=mydb

InfluxDB 2.0 API parameters:

  • url - [required] url string of your influxDB
  • bucket - [required] the destination bucket for writes
  • org - [required] the parameter value specifies the destination organization for writes
  • orgid - [optional] the parameter value specifies the ID of the destination organization for writes
    (NOTE: If both orgID and org are specified, org takes precedence)
  • token - [required] API token to authenticate to the InfluxDB

InfluxDB <1.8 API parameters:

  • url - [required] url string of your influxDB
  • username - [required] name of influxDB user
  • password - [required] password of influxDB user

Prometheus

Prometheus is another time-series database supported by ASAB. Prometheus accesses asab/v1/metrics endpoint of ASAB ApiService. Thus, connecting ASAB to Prometheus requires APIService initialization. ASAB metrics are presented to Prometheus in OpenMetrics standard format (https://openmetrics.io/). To satisfy the OpenMetrics format required by Prometheus, you should follow instructions below:

  • Metrics names must fit regex [a-zA-Z:][a-zA-Z0-9_:]*. (Any other characters are replaced by underscore. Leading underscores and numbers are stripped. These changes are proceeded without warning.)
  • Metrics names MUST NOT end with “total” or “created”.
  • Tags SHOULD contain items “unit” and “help” providing metadata to Prometheus.
  • Values MUST be float or integer.

Example of your ASAB application configuration to enable Prometheus connection:

[asab:metrics]
target=prometheus

[asab:metrics:prometheus]

Example of prometheus.yaml configuration file:

global:
  scrape_interval: 15s
  scrape_timeout: 10s
  evaluation_interval: 15s
scrape_configs:
- job_name: 'metrics_example'
  metrics_path: '/asab/v1/metrics'
  scrape_interval: 10s
  static_configs:
  - targets: ['127.0.0.1:8080']

ASAB Metrics Interpretation

To understand better how to interpret the ASAB metrics, you need to know a little bit more about the role of Metrics Service. Not only it creates new metrics, but Metrics Service also periodically collects their values and sends them to selected databases. Every 60 seconds in the application lifetime, Metrics Service gathers values of all ASAB metrics using flush() method implemented by each metric object. All Counters (and metric types that inherit from Counter) reset at this event to their initial values by default. Interpretation of ASAB Counters is affected by their resetable nature. Even though they monotonously increase, reseting every minute gives them different meaning. In a long term observation (that’s how you most probably monitor the metric in time-series databases), these metrics count events per minute. Thus, resetable Counters are presented to Prometheus database as gauge type metrics. Set the reset argument to False when creating new Counter to disable Counter reseting. This periodic “flush” cycle also causes 60s delay of metric propagation into supported time-series databases.

Web Requests Metrics

There are default metrics in ASAB framework. WebService class automatically provides with metrics counting web requests. There are 4 Counters quantifying requests to all ASAB endpoints.

  • web_requests - Counts requests to asab endpoints as events per minute.
  • web_requests_duration - Counts total requests duration to asab endpoints per minute.
  • web_requests_duration_min - Counts minimal request duration to asab endpoints per minute.
  • web_requests_duration_max - Counts maximum request duration to asab endpoints per minute.

MetricsService

class asab.metrics.MetricsService(app, service_name)[source]

Bases: asab.abc.service.Service

create_gauge(metric_name, tags=None, init_values=None)[source]

Creates Gauge object.

create_counter(metric_name, tags=None, init_values=None, reset: bool = True)[source]

Creates Counter object.

create_eps_counter(metric_name, tags=None, init_values=None, reset: bool = True)[source]

Creates EPSCounter object.

create_duty_cycle(loop, metric_name, tags=None, init_values=None)[source]

Creates DutyCycle object.

create_agg_counter(metric_name, tags=None, init_values=None, reset: bool = True, agg=<built-in function max>)[source]

Creates AggregationCounter object.

Metrics

Gauge

class asab.metrics.Gauge(name: str, tags: dict, init_values=None)[source]

Bases: asab.metrics.metrics.Metric

Initial values must be provided when defining the metrics. Argument init_values is a dictionary with initial values and value names as keys.

set(name, value)[source]
Parameters:
  • name – name of the value
  • value – value itself

Counter

class asab.metrics.Counter(name, tags, init_values=None, reset: bool = True)[source]

Bases: asab.metrics.metrics.Metric

Initial values (init_values - dictionary of inital values with value names as keys) can be provided when initializing the metrics or added with add() or sub() methods. If reset is True, Counter resets every 60 seconds.

add(name, value, init_value=None)[source]
Parameters:
  • name – name of the counter
  • value – value to be added to the counter
  • init_value – init value, when the counter name is not yet set up (f. e. by init_values in the constructor)

Adds to the counter specified by name the value. If name is not in Counter Values, it will be added to Values.

sub(name, value, init_value=None)[source]
Parameters:
  • name – name of the counter
  • value – value to be subtracted from the counter
  • init_value – init value, when the counter name is not yet set up (f. e. by init_values in the constructor)

Subtracts to the counter specified by name the value. If name is not in Counter Values, it will be added to Values.

EPSCounter

class asab.metrics.EPSCounter(name, tags, init_values=None, reset: bool = True)[source]

Bases: asab.metrics.metrics.Counter

Event per Second Counter Divides all values by delta time

DutyCycle

class asab.metrics.DutyCycle(loop, name: str, tags: dict, init_values=None)[source]

Bases: asab.metrics.metrics.Metric

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

now = self.Loop.time() d = now - self.LastReadyStateSwitch self.LastReadyStateSwitch = now

To initialize DutyCycle, provide application loop (asab.Application.Loop) as this object tracks time of the application.

AggregationCounter

class asab.metrics.AggregationCounter(name, tags, init_values=None, reset: bool = True, agg=<built-in function max>)[source]

Bases: asab.metrics.metrics.Counter

Takes a function object as the agg argument. The aggregation function can take two arguments only. Maximum is used as a default aggregation function.

Values (their names and init_values) can be provided when initializing the metrics or added with set() method. add() and sub() methods are not implemented.

set(name, value, init_value=None)[source]

Applies aggregation function on recent Counter value and value in argument and sets the result as new value of the Counter.

Parameters:
  • name (str) – name of the value
  • value (int) – value itself
  • init-value (dict) – initial value, required when the counter name is not yet set up (i. e. by init_values in the constructor)

Metric

Abstract class

class asab.metrics.Metric(name: str, tags: dict)[source]

Bases: abc.ABC

Parameters:
  • name (str) – name of the metric
  • tags (dict) – “host” tag is provided by default. “help” and “unit” tags are used as metadata by Prometheus database
flush() → dict[source]

Allows MetricsService to collect metrics values.

get_open_metric() → str[source]

Parses metric data into OpenMetrics format and returns it as string. This format is required by Prometheus database.

rest_get() → dict[source]

Provides information about current metric state.