Skip to content
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

Merged
merged 4 commits into from
Aug 6, 2024

Conversation

ebr
Copy link
Contributor

@ebr ebr commented Jul 22, 2024

OpenTelemetry propagate.extract() method is unable to handle Pydantic models, so they must be serialized before creating spans. Looks like the issue was introduced with #57 and only appears when Pydantic model schema dump is turned off.

In this PR we also determine the event name before creating the span. Otherwise all dispatch spans are named Event None dispatched - now the actual event name is set instead of None.

Fixes #63

@@ -290,7 +292,7 @@ class UserCreated(pydantic.BaseModel):
)

# OTEL
if payload and isinstance(payload, dict):
Copy link
Contributor Author

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.

Copy link
Contributor Author

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() and inject_traceparent() . Do you think there's a performance penalty here that is worth spending the time to optimize?

Thank you for this great library :)

Copy link
Owner

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.

Copy link
Owner

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

@@ -39,6 +40,9 @@ def create_span_for_handle_fn(

links, context = [], None

if isinstance(payload, BaseModel):
Copy link
Owner

@melvinkcx melvinkcx Jul 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks for your contribution :)

Even though the package is called fastapi_events, I know there are some users using it without FastAPI and Pydantic. So, importing pydantic will break those use cases.

Instead of importing BaseModel from pydantic, I suggest using duck typing to maximise backward compatibility.

Also, IIRC, the model_dump method was introduced in Pydantic v2. It replaced the dict() method in v1.

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 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 HAS_PYDANTIC... logic from the dispatcher, but i'd be fine with either approach.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, it works for me

@melvinkcx melvinkcx self-requested a review August 3, 2024 15:05
@melvinkcx melvinkcx merged commit 0c6b8d6 into melvinkcx:dev Aug 6, 2024
2 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

OpenTelemetry breaks when events are Pydantic models
2 participants