-
Notifications
You must be signed in to change notification settings - Fork 651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TraceId, SpanId 0 in logs from exception handler for Exception class - FastAPI app #3477
Comments
I do have the exact same problem and thought I was doing something wrong, thanks, you saved me a few hours of debugging by posting this :-)! |
Also have the same problem. |
I'm having the same issue with the gRPC instrumentator. This is pretty bad, because the most valuable logs for me are the ones related to exceptions, if I can't have the context there it means I'm in the dark when trying to debug them. |
Is there any progress on this? |
I've met same issue. But I have possible solution. solutionjust use otel-intrumentation-asgi (link) instead of otel-instumentation-fastapi from fastapi import FastAPI
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
app = FastAPI(...)
# add your FastAPI application routes and settings here
# you need initialized TracerProvider
tracer_provider: TracerProvider = ...
app = OpenTelemetryMiddleware(app, tracer_provider=tracer_provider) Explaining
When starlette handles http request it builds middlewares (source). When building, it places So, all you need is to put OpenTelemetryMiddleware as top middleware. So, wrap your fastapi asgi with OpenTelemetryMiddleware and it will work correctly |
@amit12297 @rikkkx can you please open PR with your fix? |
I had the same issue using My solution was similar to @rikkkx 's (thanks!), but I didn't remove The FastAPI initialization was the following. Note that from fastapi import FastAPI
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
app = FastAPI(...)
# add your FastAPI application routes and settings here
app = OpenTelemetryMiddleware(app) The issue I noticed with this approach is that the HTTP request spans got duplicated (2 extra spans) due to ASGI instrumentation and I couldn't find a way to disable it easily - probably filtering out spans would do the work, but it would make |
After using this workaround for a while, I noticed that using ASGI lib as a wrapper causes a high cardinality on the span name attribute because the parameters received on the URL will be the name of the root span. See an example in the image below. I found a solution by injecting the ASGI middleware through FastAPI, as follows: from fastapi import FastAPI
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
from opentelemetry.instrumentation.fastapi import (
_excluded_urls_from_env,
_get_default_span_details,
)
app = FastAPI(...)
# add your FastAPI application routes and settings here
# Adds ASGI OTel middleware with FastAPI's add_middleware:
app.add_middleware(
OpenTelemetryMiddleware,
default_span_details=_get_default_span_details, # Uses FastAPI's span details builder to set span name
excluded_urls=_excluded_urls_from_env, # bonus: make it able to exclude URLs through the env var OTEL_PYTHON_EXCLUDED_URLS
) |
Describe your environment
python = 3.10.12
fastapi = 0.92.0
uvicorn = 0.20.0
opentelemetry-distro = 0.41b0
Steps to reproduce
When we log from exception_handler in FastAPI, traceId and spanId is coming as 0. Here is an example:
I have created a github repo to demonstrate the issue. Please checkout: https://github.com/amit12297/python-otel-log-issue and follow the readme
What is the expected behavior?
Actual(Non-zero) traceId and spanId in logs from exception handler
What is the actual behavior?
traceId=0 and spanId=0 in logs from exception handler
Additional context
As you can see in the code above I have registered an exception handler for the base exception class
FastAPI checks if any handler is registered for 500/Exception, if yes then it sets that as handler for ServerErrorMiddleware.
Here is the FastAPI code:
As far as I know, ServerErrorMiddleware is the outermost middleware.
When there is an error, context gets detached by OpentelemetryMiddleware before control reaches ServerErrorMiddleware's exception handler that I registered. Hence when the log is written it does not get traceId and spanId.
I tested this out, and made changes in
opentelemetry/trace/init.py -> use_span function
and
opentelemetry/instrumentation/asgi/init.py -> call function
in my local machine. Basically I am not detaching the context if there is an exception.
After these changes I am getting actual traceId and spanId.
But I am not sure, if the solution I have used is correct or not. Request inputs from python and OTEL experts out here.
The text was updated successfully, but these errors were encountered: