Python client to gather data for Prometheus logging in server with multiple instances and workers.
Project description
PHANOS
Python client to gather data for Prometheus logging in server with multiple instances and workers. Phanos works with synchronous programs and with asynchronous programs implemented by asyncio. Behavior in multithread programs is unspecified.
Profiling
Default metrics
Phanos contains two default metrics. Time profiler measuring execution time of
decorated methods is ON by default. Response size profiler measuring size of methods return value
of root method is OFF by default. Both can be deleted by phanos.profiler.delete_metric(phanos.publisher.TIME_PROFILER)
and phanos.profiler.delete_metric(phanos.publisher.RESPONSE_SIZE)
.
Configuration
There are two options of how to configure profiler. Profiler must be configured by one of these options.
Both options uses these attributes:
-
job
job label for prometheus; usually name of app -
logger
(optional) name of logger; if not specified, Phanos creates its own logger -
time_profile
(optional) by default profiler tracks execution time of profiled function/object -
response_size_profile
(optional) by default profiler will not track size of return value -
handle_records
(optional) by default profiler measures values and handles them; if False then no profiling is made or handled -
error_raised_label
(optional) by default profiler will not add labelerror_raised
to each record; if set, every record will have information if given profiled function/method raised error; if error raised, profiling will be logged even if noLoggerHandler
exists -
handlers
(optional) serialized named handlers to publish profiled records; if no handlers specified then no measurements are made; for handlers description refer to Handlers.class
class handler to initializedhandler_name
handler name required argument of publishers**other arguments
- specific arguments required to construct instance of class f.e.:output
.
With addition of async handlers, async_config
and async_dict_config
methods were added to Profiler
class.
Be wary that config
and dict_config
methods ARE NOT compatible with async handlers, but async_config
and
async_dict_config
ARE compatible with sync handlers, but cannot be used in purely synchronise environment.
Dict Configuration
It is possible to configure profile with configration dictionary with method Profiler.dict_config(settings)
or
Profiler.async_dict_config(settings)
for usage with async handlers. (similar to logging
dictConfig
).
Example of configuration dict:
settings = {
"job": "my_app",
"logger": "my_app_debug_logger",
"time_profile": True,
"response_size_profile": False,
"handle_records": True,
"error_raised_label": False,
"handlers": {
"stdout_handler_ref": {
"class": "phanos.handlers.StreamHandler",
"handler_name": "stdout_handler",
"output": "ext://sys.stdout"
}
}
}
Configuration in code
When configuring in code use Profiler.config
or Profiler.async_config
method to configure profiling.
For handler addition create handler instance first and add it to profiler with Profiler.add_handler
method.
(Cannot add_handler before profiler configuration)
Example of configuration:
import logging
import phanos
# configuration of profiler and handler addition
phanos.profiler.config(
logger=None,
time_profile=True,
response_size_profile=False,
handle_records=True,
error_raised_label=True,
)
log_handler = phanos.publisher.LoggerHandler(
'handler_name',
logger=None,
level=logging.INFO
)
phanos.profiler.add_handler(log_handler)
Usage
-
configure profiler as shown in Configuration
-
decorate methods which you want to profile
@phanos.profile
. (shortcut for@phanos.profiler.profile
). Allways put decorator closest to method definition as possible, because the decorator collides with some other decorators. The decorator must allways be under@classmethod
,@staticmethod
,flask_restx
decorators and possibly others.
import phanos
class SomeClass:
""" Example of @profile decorator placement"""
@staticmethod
@phanos.profile
def some_method():
pass
# is equivalent to
@staticmethod
@phanos.profiler.profile
def some_method():
pass
Handlers
Each handler have handler_name
attribute. This string can be used to delete handlers later
with phanos.profiler.delete_handler(handler_name)
.
Records can be handled by these handlers:
StreamHandler(handler_name, output)
- write records to given output (default issys.stdout
)LoggerHandler(handler_name, logger, level)
- logs string representation of records with given logger and with given level; default level islogging.DEBUG
; if no logger is passed, Phanos creates its own loggerNamedLoggerHandler(handler_name, logger_name, level)
- same as LoggerHandler, butlogger
instance is found bylogging.getLogger(logger_name)
method.ImpProfHandler(handler_name, **rabbit_connection_params, logger)
- sending records to RabbitMQ queue - blocking.AsyncImpProfHandler(handler_name, **rabbit_connection_params, logger)
- sending records to RabbitMQ queue - async.
Phanos metrics:
Basic Prometheus metrics:
- Histogram
- Summary
- Counter
- Info
- Gauge
- Enum
These classes represent basic Prometheus metrics types. For more information about Prometheus metric types, allowed operations, etc. refer to Prometheus documentation.
Custom metrics
TimeProfiler
: metric for measuring time-consuming actions in mS; basically Histogram metric of Prometheus.ResponseSize
: metric for measuring size of return value of method in bytes, designed to measure response size of endpoints; basically Histogram metric of Prometheus.
Creating new custom metric
- new metric class needs to inherit from one of basic Prometheus metrics.
__init__()
method needs to callsuper().__init__()
- implement method for each operation wanted; this method must call one of inherited metrics operations if you want
operation to be stored f.e.
Gauge.dec
; MetricWrapper.cleanup()
is called after all measured metrics are handled; if custom cleanup is needed, implement methodcleanup()
callingsuper().cleanup()
inside
Add metrics automatic measurements
phanos.profiler
contains these four attributes:
before_func: Callable[[Callable[..., Any], Tuple[Any, ...], Dict[str, Any]], None]
: executes before each profiled method/functionbefore_root_func: Callable[[Callable[..., Any], Tuple[Any, ...], Dict[str, Any]], None]
: executes before each profiled root method/function (first method in profiling tree)after_func: Callable[[Any, Tuple[Any, ...], Dict[str, Any]], None]
: executes after each profiled method/functionafter_root_func: Callable[[Any, Tuple[Any, ...], Dict[str, Any]], None]
: executes after each profiled root method/function (first method in profiling tree)
Implement these methods with all needed measurement.
Complete example
import typing
import phanos
# custom metric example
class CustomMetric(phanos.metrics.Counter):
def __init__(self, name, job, units, labels):
super().__init__(name, job, units, labels)
# custom initialization
self.count = 0
def custom_op(self, value: int = 0, label_values: typing.Optional[typing.Dict[str, str]] = None):
self.count += value
self.inc(self.count, label_values)
def helper_method(self):
pass
def cleanup(self) -> None:
super().cleanup()
self.count = 0
my_metric = CustomMetric(name="name", job="MyJob", units="units", labels={"label_name"})
def before_function(func, args, kwargs):
# this operation will be recorded
my_metric.custom_op(2, {"label_name": "label_value"})
# this won't be recorded
my_metric.helper_method()
phanos.profiler.before_func = before_function
What must/can be done:
- custom metric
MetricWrapper.__init__
needsname
,job
,units
arguments passed;labels
andlogger
are optional
- custom measurements
before_*
functions must havefunc
argument, where function which is executed is passed.after_*
function needs to haveresult
argument where function result is passed- all four functions can access
args
andkwargs
of decorated methods. These arguments are passed in packed form.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file phanos-0.3.2.tar.gz
.
File metadata
- Download URL: phanos-0.3.2.tar.gz
- Upload date:
- Size: 36.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.0rc1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5eb069cbb5e8a50fe6cfd3985475eb128bdc36b92c723aea02b2ad6a72c52f48 |
|
MD5 | 042080610c225c27c76d62b22c49ca58 |
|
BLAKE2b-256 | d161be0cd2493df9f115bd79f2d0f0880746b4a233857d5868fa91312933150d |
File details
Details for the file phanos-0.3.2-py3-none-any.whl
.
File metadata
- Download URL: phanos-0.3.2-py3-none-any.whl
- Upload date:
- Size: 24.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.0rc1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 12c9a22f9df7e454e5593ef3c3907889f833e8ef4dc51ced9008255e419a7e37 |
|
MD5 | 8c25e5ef5eba2eeea270d9d5bb9d881a |
|
BLAKE2b-256 | e3fb8486c2e7ef6198fb87606a6b559a7e8c21808083dd3126dc7178e5534fc2 |