-
Notifications
You must be signed in to change notification settings - Fork 25
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
Serialize pydantic events before creating OTEL spans #64
Changes from 3 commits
df5b145
0d7c2c1
a0fb7fb
a2f9dff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -9,6 +9,7 @@ | |||||
from fastapi_events.otel import HAS_OTEL_INSTALLED, propagate, trace | ||||||
from fastapi_events.otel.attributes import SpanAttributes | ||||||
from fastapi_events.utils import strtobool | ||||||
from pydantic import BaseModel | ||||||
|
||||||
logger = logging.getLogger(__name__) | ||||||
|
||||||
|
@@ -39,6 +40,9 @@ def create_span_for_handle_fn( | |||||
|
||||||
links, context = [], None | ||||||
|
||||||
if isinstance(payload, BaseModel): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, thanks for your contribution :) Even though the package is called Instead of importing BaseModel from pydantic, I suggest using duck typing to maximise backward compatibility. Also, IIRC, the I'd suggest something like: if hasattr(payload, "model_dump"): # handle Pydantic v2
payload = payload.model_dump()
elif hasattr(payload, "dict"): # handles Pydantic v1
payload = payload.dict() In fact, we have similar logic handling both pydantic versions and the absence of pydantic in the dispatcher just fyi:
Once you update the changes, I'll be sure to have it merged asap. Thanks again for your contribution :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I updated the changes as you recommended. Duck typing seemed less verbose in this case than duplicating the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, it works for me |
||||||
payload = payload.model_dump() | ||||||
|
||||||
# Extract span from remote context | ||||||
remote_ctx = propagate.extract(payload) | ||||||
if use_span_linking: | ||||||
|
@@ -85,6 +89,9 @@ def inject_traceparent(payload: Dict): | |||||
logger.debug("Unable to inject traceparent. OTEL is not installed.") | ||||||
return | ||||||
|
||||||
if isinstance(payload, BaseModel): | ||||||
payload = payload.model_dump() | ||||||
|
||||||
if not isinstance(payload, dict): | ||||||
logger.debug("Unable to inject traceparent. Payload is not a dict") | ||||||
return | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why this type check was needed here, and whether injecting traceparent is needed for every payload or only some.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@melvinkcx I don't see the removal of this typing check breaking anything, but let me know please if i'm missing something.
Also, in this PR we're serializing the Pydantic payload for OTEL inside both
create_span_for_handle_fn()
andinject_traceparent()
. Do you think there's a performance penalty here that is worth spending the time to optimize?Thank you for this great library :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, the
isinstance(payload, dict)
was added just in case people are using a custom class instance as payload. In this case, we should avoid injecting traceparent, since it most likely wont work.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the performance penalty, I see your point. I don't have any numbers on hand as for how much performance penalty it introduces, but I wouldn't mind us fixing it