starlette_exporter icon indicating copy to clipboard operation
starlette_exporter copied to clipboard

`from_header` but for `Response`?

Open lainiwa opened this issue 1 year ago • 5 comments

Is there any way to create a label based on response in starlette_exporter? My use-case is adding a hit-or-miss={hit,miss} label based on the x-fastapi-cache header.

lainiwa avatar Oct 10 '23 17:10 lainiwa

@lainiwa unfortunately, not at the moment. The custom labels are evaluated before the endpoint handler is called. Interesting idea- I'll report back if I can think of a good solution.

stephenhillier avatar Oct 12 '23 03:10 stephenhillier

I tested the new helper function, and it seems it's now working for me:

Traceback (most recent call last):
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/fastapi/applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/starlette/applications.py", line 123, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/starlette/middleware/errors.py", line 186, in __call__
    raise exc
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/starlette/middleware/errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/starlette_exporter/middleware.py", line 475, in __call__
    self.request_count.labels(*labels).inc(**extra)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/lainiwa/myproject/backend/.venv/lib/python3.11/site-packages/prometheus_client/metrics.py", line 199, in labels
    raise ValueError('Incorrect label count')
ValueError: Incorrect label count

That's how I was adding the middleware:

app.add_middleware(
    PrometheusMiddleware,
    app_name='api_production',
    prefix='api',
    filter_unhandled_paths=True,
    labels={
        "auth_token_full": lambda request: request.headers.get("authorization", ""),
        # ...
        "cache_status": from_response_header("X-FastAPI-Cache", allowed_values=("HIT", "MISS")),
    },
)
app.add_route("/metrics", handle_metrics)

Is there some obvious problem with it, or would you want me to construct a full minimal reproducible snippet?

lainiwa avatar Jun 20 '24 18:06 lainiwa

@lainiwa thanks for reporting back. I haven't been able to reproduce an error with your example yet but I'll keep looking at it.

I did notice from_response_header("X-FastAPI-Cache", allowed_values=("HIT", "MISS")) did not work for me and I had to replace it with from_response_header("x-fastapi-cache", allowed_values=("HIT", "MISS")) (lowercase header key) so there's at least one bug I can get started on for now.

stephenhillier avatar Jun 23 '24 04:06 stephenhillier

The app I'm testing with is a real simple FastAPI app with the following handler func:

@app.get("/")
def index():
    return JSONResponse({
        "message": "test"
    }, headers={"X-FastAPI-Cache": "HIT"})

I'll see if I can test with a better real-world example.

stephenhillier avatar Jun 23 '24 04:06 stephenhillier

I'm able to reproduce the same error if I raise an unhandled exception in the handler. Do you think that's what's happening in your application? I opened #99 to handle that case, but let me know if you're seeing this happen outside of exceptions as well.

stephenhillier avatar Jun 23 '24 05:06 stephenhillier

Hey, sorry for the slow response. Yes, seems those were unhandled exceptions of the app getting hidden by starlette_exporter. I upgraded 0.22.0 -> 0.23.0 and now the exceptions are being correctly surfaced again. Thank you!

lainiwa avatar Jul 02 '24 11:07 lainiwa