For a web application the natural unit of tracing is the request: one HTTP request, its method, path and status, and every observed call made while handling it, as one tree. The config file from last time cannot give you that on its own, and it is worth being clear about why before showing what does.

A WSGI application looks like any other callable, but it routes the interesting facts around the return value. The status and headers travel through the start_response callback rather than being returned. The body is an iterable that the server consumes after the call has returned, so a streaming application does most of its work after a call event would already have closed. And when a view raises, the framework catches the exception and turns it into a 500 response before any wrapper on the application ever sees it. A binding on the application callable would record a call that returned an iterable and raised nothing, which is true and useless.

The shop behind Flask

Here is the shop from the earlier posts behind a small Flask application. A /quote/<item> route renders a template, a /order route places an order through the OrderService from before, and a /health route exists because every deployed service has one.