Skip to main content

A Python metrics library

Project description

Pylemetry

uv Ruff image image image Release

Add metrics to your Python applications with Pylemetry

Currently, three meters are supported, Counter, Gauge, and Timer

Counter

The counter meter allows you to keep track of the number of times a block of code is executed. A Counter can be created either directly

from pylemetry.meters import Counter


def some_method() -> None:
    counter = Counter()

    for _ in range(100):
        counter.add()  # counter += 1 is also supported

    counter.get_count()  # 100

or via a decorator

from pylemetry import registry
from pylemetry.decorators import count


@count()
def some_method() -> None:
    ...


@count("named_counter")
def another_method() -> None:
    ...


def main() -> None:
    for _ in range(100):
        some_method()
        another_method()

    counter = registry.get_counter("some_method")
    counter.get_count()  # 100

    counter = registry.get_counter("named_counter")
    counter.get_count()  # 100

When using this meter via a decorator, the meter gets added to the global registry, with the method name it's decorating as the meter name. Alternatively, you can provide a name for the meter as a parameter to the decorator

Gauge

A Gauge meter allows you to keep track of varying metrics, e.g. memory usage or items on a queue. This meter currently isn't supported as a decorator

from pylemetry import registry
from pylemetry.meters import Gauge


def some_method() -> None:
    gauge = Gauge()
    
    registry.add_gauge("sample_gauge", gauge)

The Gauge supports incrementing, decrementing, and setting a value directly

from pylemetry import registry


gauge = registry.get_gauge("sample_gauge")

gauge.add(10)
gauge += 1.5
gauge.get_value()  # 11.5

gauge.subtract(10)
gauge -= 8.5
gauge.get_value()  # -7

gauge.set_value(7.5)
gauge.get_value()  # 7.5

Timer

A Timer meter allows for tracking the time taken for a block of code. This can be done either directly

from pylemetry.meters import Timer


def some_method() -> None:
    timer = Timer()

    for _ in range(100):
        with timer.time():
            ...

    timer.get_count()  # 100
    timer.get_mean_tick_time()  # Mean execution time of the code block

or via a decorator

from pylemetry import registry
from pylemetry.decorators import time


@time()
def some_method() -> None:
    ...


@time("named_timer")
def another_method() -> None:
    ...


def main() -> None:
    for _ in range(100):
        some_method()
        another_method()
        
    timer = registry.get_timer("some_method")
    timer.get_count()  # 100
    timer.get_mean_tick_time()  # Mean execution time of the some_method function
    timer.get_max_tick_time()  # Maximum execution time of the some_method function
    timer.get_min_tick_time()  # Minimum execution time of the some_method function

    timer = registry.get_timer("named_timer")
    timer.get_count()  # 100
    ...

When using this meter via a decorator, the meter gets added to the global registry, with the method name it's decorating as the meter name. Alternatively, you can provide a name for the meter as a parameter to the decorator

The Registry

Pylemetry maintains a global registry of meters, allowing you to share a meter across multiple files, or reference metrics from a central location. This registry is also used to keep track of all metrics created by decorators, with those meters registered using the method name they are decorating

from pylemetry import registry
from pylemetry.meters import Counter, Gauge, Timer


counter = Counter()
gauge = Gauge()
timer = Timer()

registry.add_counter("example", counter)
registry.add_gauge("example", gauge)
registry.add_timer("example", timer)

Each meter type has an add_meter, get_meter and remove_meter method to manage meters in the registry, each requiring a unique meter name.

The registry can be cleared through the clear() method

Reporting

Periodic reporting of all meters in the registry can be achieved using the LoggingReporter. This reporter periodically logs messages to a provided logger with a given message format and interval.

Message Formatting

The message format allows for substitutions for metric values with the following options

Substitution Key Effect
name Name of the meter being logged
value Value of the meter, count for Counter and Timer meters, value for Gauge meters
min Minimum value of the meter, equivalent to the value substitution for Counter and Gauge meters, min_tick_time for Timer metes
max Maximum value of the meter, equivalent to the value substitution for Counter and Gauge meters, max_tick_time for Timer metes
avg Mean average value of the meter, equivalent to the value substitution for Counter and Gauge meters, mean_tick_time for Timer metes

As an example, a Counter meter named sample_counter with a value of 10

message_format = "Meter: {name} - Value: {value}"

This message format would evaluate to Meter: sample_counter - Value: 10

It is possible to include braces {} in the message using the same rules as Python string formatting by doubling up the brace you want to escape.

message_format = "{{'name': '{name}', 'value': {value}, 'extra': 'abc123'}}"

This message format would evaluate to {'name': 'sample_counter', 'value': 10, 'extra': 'abc123'}

LoggingReporter

The LoggingReporter takes a provided logger, log level, message format, and interval, and logs formatted messages for all meters in the registry to the provided logger at the specified log level every n seconds where n is the provided interval.

Any logger can be used with the LoggingReporter so long as it conforms to the Loggable protocol defined in pylemetry.reporters.logging. The Python built in logging logger conforms to this, as do several alternate logging packages such as Loguru

An additional parameter ReportingType is required to determine whether to log cumulatively, or per interval. When ReportingType.CUMULATIVE is provided then all logs for all meters will include values for the meter's entire lifespan. If ReportingType.INTERVAL is provided, all meters will log only the changes in that meter since the most recent interval was marked, either manually or by the most recent log flush

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pylemetry-1.0.0.tar.gz (35.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pylemetry-1.0.0-py3-none-any.whl (14.5 kB view details)

Uploaded Python 3

File details

Details for the file pylemetry-1.0.0.tar.gz.

File metadata

  • Download URL: pylemetry-1.0.0.tar.gz
  • Upload date:
  • Size: 35.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.22

File hashes

Hashes for pylemetry-1.0.0.tar.gz
Algorithm Hash digest
SHA256 df54ac3cb0feac57d8ffee3f23ebeac49be789ce2a09c21a42addcd747dc1f20
MD5 e84ecec481c447c813719df136f04ae6
BLAKE2b-256 5738831625ee22b9d712fbfd5956b1f6691e01e5938fcf437b5c93c8c1d64b30

See more details on using hashes here.

File details

Details for the file pylemetry-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pylemetry-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.22

File hashes

Hashes for pylemetry-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 56e60b22ec8472e7a0a1585e9df0fe6398b50e4379bb96d6758382b20c2c249c
MD5 ff211f7112d8fb529c0896a55a9123a3
BLAKE2b-256 89114431ba253bc33fea8d44fd0f3e09a1ab0db782d5d27b9993f0874f4e0598

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page