Closed alegtk closed 6 months ago
I did it like this, seems to work fine
# Make a lifespan function that can do the .expose() that was previously done in the @app.on_event("startup")
@asynccontextmanager
async def lifespan(app: FastAPI):
instrumentator.expose(app)
yield
app = FastAPI(
...
lifespan=lifespan, # include the lifespan func in the FastAPI init call
)
instrumentator = Instrumentator().instrument(app) # Initialize the instrumentator
@NiclasLindqvist I confirm your assertion! Thank you for clearing my mistake.
Now I see what was the difference from our previous code to that on the manuals that is equivalent to your sample. One should instantiate the Instrumentator outside the lifespan
coroutine. We were doing it all at once, instantianting and pipelining the expose
method.
Maybe there is a drawback for some because the instrumentator object must be on the same scope as the coroutine. Perhaps one can solve this using FastAPI inherited state
attribute as in
app = FastAPI(lifespan=...)
app.state.instr = Instrumentator(
excluded_handlers=["/readiness", "/liveness", "/metrics"],
).instrument(app)
I came across the same issue today. I had to use a different solution because i am using an app-factory and came up with the following, which keeps the global namespace clean:
from fastapi import FastAPI
from prometheus_fastapi_instrumentator import Instrumentator
def create_lifespan_handler(instrumentator: Instrumentator):
"""
Create a FastAPI lifespan handler for the application
@param instrumentator: A prometheus instrumentator used to expose metrics
"""
@asynccontextmanager
async def lifespan(app: FastAPI):
instrumentator.expose(app)
yield
return lifespan
def create_app():
instrumentator = Instrumentator()
app = FastAPI(
...,
lifespan=create_lifespan_handler(instrumentator),
)
instrumentator.expose(app)
return app
In the absence of a better place to collaborate (got a 404 on the contributing.md), I'm placing some findings here. We've a system that was using FastAPI v0.85. In the event of a maintenance it was natural to evolve dependencies and got v0.110.0. It looks like FastAPI changed the way it works with middleware since we started getting the message bellow.
Cannot add middleware after an application has started
Doing some research one can see that
on_event
is deprecated in favour oflifespan
.on_event
was the place we chose to init the instrumentator. I'm not sure if there is a way to keep this paradigm. The finding is that we can still successfully start the instrumentator outsidelifespan
as is the first suggested method in the manuals.Maybe it's worth mentioning this at the readme.