I've used decorators that execute the route function and then fire a call back at the end. Here's a quick example of "metrics at the start of a request and at the end.

```
from functools import wraps
from random import randint
import time

from klein import Klein
from twisted.internet import defer, reactor

def startMetric(f):
    @wraps(f)
    def deco(*args, **kw):
        req = args[1]
        print(f"[x] start:{time.time()} path:{req.path.decode('utf8')}")
        result = defer.maybeDeferred(f, *args, **kw)
        result.addBoth(endMetric, req)
        return result
    return deco

def endMetric(result, req):
    print(f"[x] end:{time.time()} path:{req.path.decode('utf8')} status:{req.code}")
    return result

class MyApp:

    rtr = Klein()

    @rtr.route("/hello")
    @startMetric
    def hello(self, req):
        d = defer.Deferred()
        delay = randint(1, 5)
        reactor.callLater(delay, d.callback, f"delay:{delay}")
        req.setResponseCode(403, b"whoopsie")
        return d

def main():
    app = MyApp()
    app.rtr.run("localhost", 9999)

main()
```






On Mon, Mar 1, 2021, 15:52 Robert DiFalco <robert.difalco@gmail.com> wrote:
Is this the right place to ask klein questions? I'm writing a metrics plugin for Klein and I can't figure out how to inject a metrics handler so that I can get route, path, duration, and status code. What I'm doing now sucks because Klein and twisted interact in complex ways on Failure and status codes. 
# Replace the klein _call with the metrics generating call
_app._call = _callWithMetrics
Rather than replace _call with my version of _call I was hoping there was a cleaner way to get the start and stop with the result code of a route invocation. Thoughts? 



_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python