Twisted Support#
The Twisted-related APIs can be found within the prometheus_async.tx
package.
Decorator Wrappers#
- prometheus_async.tx.time(metric: Observer) Callable[[Callable[P, D]], Callable[P, D]] #
- prometheus_async.tx.time(metric: Observer, deferred: D) D
Call
metric.observe(time)
with runtime in seconds.Can be used as a decorator as well as on
Deferred
s.Works with both sync and async results.
- Returns
function or
Deferred
.
The fact it’s accepting Deferred
s is useful in conjunction with twisted.web
views that don’t allow to return a Deferred
:
from prometheus_client import Histogram
from prometheus_async.tx import time
from twisted.internet.task import deferLater
from twisted.web.resource import Resource
from twisted.web.server import NOT_DONE_YET
from twisted.internet import reactor
REQ_TIME = Histogram("req_time_seconds", "time spent in requests")
class DelayedResource(Resource):
def _delayedRender(self, request):
request.write("<html><body>Sorry to keep you waiting.</body></html>")
request.finish()
def render_GET(self, request):
d = deferLater(reactor, 5, lambda: request)
time(REQ_TIME, d.addCallback(self._delayedRender))
return NOT_DONE_YET
- prometheus_async.tx.count_exceptions(metric: Incrementer, *, exc: type[BaseException] = <class 'BaseException'>) Callable[P, C] #
- prometheus_async.tx.count_exceptions(metric: Incrementer, deferred: D, *, exc: type[BaseException] = <class 'BaseException'>) D
Call
metric.inc()
whenever exc is caught.Can be used as a decorator or on a
Deferred
.- Returns
function (if decorator) or
Deferred
.
- prometheus_async.tx.track_inprogress(metric: Gauge) Callable[P, C] #
- prometheus_async.tx.track_inprogress(metric: Gauge, deferred: D) D
Call
metrics.inc()
on entry andmetric.dec()
on exit.Can be used as a decorator or on a
Deferred
.- Returns
function (if decorator) or
Deferred
.
Metric Exposure#
prometheus_client, the underlying Prometheus client library, exposes a twisted.web.resource.Resource
– namely prometheus_client.twisted.MetricsResource
– that makes it extremely easy to expose your metrics.
from prometheus_client.twisted import MetricsResource
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor
root = Resource()
root.putChild(b"metrics", MetricsResource())
factory = Site(root)
reactor.listenTCP(8000, factory)
reactor.run()
As a slightly more in-depth example, the following exposes the application’s metrics under /metrics
and sets up a prometheus_client.Counter
for inbound HTTP requests.
It also uses Klein to set up the routes instead of relying directly on twisted.web
for routing.
from prometheus_client.twisted import MetricsResource
from twisted.web.server import Site
from twisted.internet import reactor
from klein import Klein
from prometheus_client import Counter
INBOUND_REQUESTS = Counter(
"inbound_requests_total",
"Counter (int) of inbound http requests",
["endpoint", "method"]
)
app = Klein()
@app.route("/metrics")
def metrics(request):
INBOUND_REQUESTS.labels("/metrics", "GET").inc()
return MetricsResource()
factory = Site(app.resource())
reactor.listenTCP(8000, factory)
reactor.run()