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

Provide default argument to json.dumps in compute_tracestate_value #1318

Merged
merged 2 commits into from
Jan 25, 2022

Conversation

tomchuk
Copy link
Contributor

@tomchuk tomchuk commented Jan 24, 2022

Granted, this is a bit of an edge-case, but I'll explain the rationale.

In our Django application, we define MERCURIAL_TAG in our settings. To compute this we subprocess out to hg. As you can imagine, this is quite expensive and has a significant impact on application startup time. So we've wrapped this in django.utils.functional.lazy() so that it's only evaluated when it's needed, not every time the app starts or every time a uwsgi worker is recycled.

The issue is, we primarily use this setting by passing it to sentry_sdk.init(). When the Sentry SDK goes to report an error, compute_tracestate_value() calls json.dumps() which blows up with a whole stack of TypeError: Object of type __proxy__ is not JSON serializable as the _got_request_exception signal fires over and over.

image

I've added a default=safe_str to json.dumps() to make sure that whatever weird thing some random idiot (read: me) passes to to sentry_sdk.init() is properly converted to a string.

I've left the type hint intact as (typing.Mapping[str, str]) -> str as it's probably worth maintaining the expectation that this is the case.

@sl0thentr0py
Copy link
Member

@tomchuk thx for the PR! Looks fine in principle but I'm not sure I understand your usage.
I assume you pass that lazy function to sentry_sdk.init(release=???) somehow but I don't see how that would work in general. A lot of other things in the SDK also depend on that release config option being a string.

@sl0thentr0py sl0thentr0py self-requested a review January 25, 2022 12:58
@tomchuk
Copy link
Contributor Author

tomchuk commented Jan 25, 2022

@sl0thentr0py - You are correct, I'm using this lazy string for the version argument to sentry_sdk.init(). Remarkably, this seems to be the only place where this lazy string object affects things, though we don't use Sentry's performance product so there may be some code paths there I'm not exercising. It basically comes down to json's _iterencode doing a bunch of isinstance checks while encoding. If you just blindly treat it as a string, it behaves just like a string.

Eg:

In [1]: settings.MERCURIAL_REV
Out[1]: 'da15c89d169f'

In [2]: type(settings.MERCURIAL_REV)
Out[2]: django.utils.functional.lazy.<locals>.__proxy__

In [3]: "one" + settings.MERCURIAL_REV
Out[3]: 'oneda15c89d169f'

In [4]: settings.MERCURIAL_REV.encode("utf-8")
Out[4]: b'da15c89d169f'

In [5]: isinstance(settings.MERCURIAL_REV, str)
Out[5]: False

@sl0thentr0py sl0thentr0py enabled auto-merge (squash) January 25, 2022 16:47
@sl0thentr0py sl0thentr0py disabled auto-merge January 25, 2022 20:08
@sl0thentr0py sl0thentr0py merged commit 4ce0a1d into getsentry:master Jan 25, 2022
@tomchuk tomchuk deleted the tracestate_json branch February 9, 2022 20:34
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.

2 participants