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

fix(core): Normalize trace context #5171

Merged
merged 8 commits into from Jun 3, 2022

Conversation

lforst
Copy link
Member

@lforst lforst commented May 27, 2022

Trace context is currently not normalized before being sent, however the data field in trace context is "free form" and user provided, so we need to at least normalize that. We're also fixing a bug in dropUndefinedKeys where references to the original object were kept in the "cloned"/returned object.

Most likely resolves #2809

Ref: https://getsentry.atlassian.net/browse/WEB-940


This is probably not the cleanest solution. I evaluated doing the normalization a bit deeper in the stack, but ran into problems with not having the normalizeDepth options available and more importantly trace context data being mutated again after the normalization.

@github-actions
Copy link
Contributor

github-actions bot commented May 27, 2022

size-limit report 📦

Path Size
@sentry/browser - ES5 CDN Bundle (gzipped + minified) 19.43 KB (-3.53% 🔽)
@sentry/browser - ES5 CDN Bundle (minified) 60.2 KB (-6.83% 🔽)
@sentry/browser - ES6 CDN Bundle (gzipped + minified) 18.24 KB (-3.32% 🔽)
@sentry/browser - ES6 CDN Bundle (minified) 53.82 KB (-7.15% 🔽)
@sentry/browser - Webpack (gzipped + minified) 19.99 KB (-13.96% 🔽)
@sentry/browser - Webpack (minified) 65.19 KB (-20.22% 🔽)
@sentry/react - Webpack (gzipped + minified) 20.02 KB (-14.01% 🔽)
@sentry/nextjs Client - Webpack (gzipped + minified) 43.76 KB (-8.93% 🔽)
@sentry/browser + @sentry/tracing - ES5 CDN Bundle (gzipped + minified) 25.46 KB (-2.38% 🔽)
@sentry/browser + @sentry/tracing - ES6 CDN Bundle (gzipped + minified) 23.98 KB (-2.04% 🔽)

Copy link
Contributor

@vladanpaunovic vladanpaunovic left a comment

Choose a reason for hiding this comment

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

Normalizing data looks good to me.

I am afraid that this won't resolve the actual issue as in my test app, I am already normalizing the data and still getting the same error.

@lforst
Copy link
Member Author

lforst commented May 30, 2022

I am afraid that this won't resolve the actual issue as in my test app, I am already normalizing the data and still getting the same error.

That would suck. IIRC we identified the error happening in axio's non-error callback. Can you try normalizing the response object here before passing it to startChild? If that doesn't resolve the issue we need to keep investigating.

Edit: Discussed the issue with @vladanpaunovic in person and wrapping the response in normalize resolved the issue. This makes us confident that this change will indeed fix the underlying issue.

@lforst lforst changed the base branch from 7.x to master May 30, 2022 13:31
@lforst lforst force-pushed the lforst-fix-unnormalized-tracecontext branch from 29f0932 to 17af3a0 Compare May 30, 2022 13:32
Copy link
Member

@lobsterkatie lobsterkatie left a comment

Choose a reason for hiding this comment

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

This looks good!

// event.spans[].data may contain circular/dangerous data so we need to normalize it
if (event.spans) {
normalized.spans = event.spans.map(span => {
// We cannot use the spread operator on span here because that overwrites the `toJSON` method
Copy link
Member

Choose a reason for hiding this comment

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

Is this because the toJSON method is non-enumerable, and spread only copies over enumerable properties? If so, can we change the comment to say that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, good point, thanks! --> 50b4b33


expect(eventData.contexts).toMatchObject({
trace: {
data: { lays: { contains: { lays: { contains: '[Circular ~]' } } } },
Copy link
Member

Choose a reason for hiding this comment

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

Why does this go two layers deep before noticing the circularity?

Copy link
Member Author

Choose a reason for hiding this comment

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

When I first wrote the test I didn't really care but now I looked a little bit closer and noticed that this is actually a pretty bad bug within dropUndefinedKeys which I produced in #5163.

I adjusted tests to test for the faulty behaviour (06a2b2d) and probably fixed it (3223048). Sadly it's not very straight forward. May I ask you to take another look at the changes? Sorry about the confusion.

Copy link
Member Author

Choose a reason for hiding this comment

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

For future readers. This was now done in #5201

@lforst lforst requested a review from lobsterkatie June 1, 2022 09:59
}

// event.spans[].data may contain circular/dangerous data so we need to normalize it
if (event.spans) {
Copy link
Member

Choose a reason for hiding this comment

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

should we gate this with a tracing debug flag?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wouldn't do that. The tracing flag currently only guards code that sets up automatic instrumentation, i.e. side effect code that makes use of tracing. This allows tracing to be treeshaken if it's not in use. It can still be used, even if the flag is set to false. If we guard this here and users call startTransaction and pass in circular data, they're not gonna have a good time. Good consideration though.

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense!

@@ -4,7 +4,6 @@ import { WrappedFunction } from '@sentry/types';

import { htmlTreeAsString } from './browser';
import { isElement, isError, isEvent, isInstanceOf, isPlainObject, isPrimitive } from './is';
import { memoBuilder, MemoFunc } from './memo';
Copy link
Member

Choose a reason for hiding this comment

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

maybe we can eliminate this since it's only used in 2 places? Can do in another PR

Copy link
Member Author

Choose a reason for hiding this comment

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

We might be able to. Agree that when we get to it we should do this in another PR.

@lforst lforst force-pushed the lforst-fix-unnormalized-tracecontext branch from 6710bac to 4d6a919 Compare June 3, 2022 12:00
@lforst lforst merged commit 453b7ad into master Jun 3, 2022
@lforst lforst deleted the lforst-fix-unnormalized-tracecontext branch June 3, 2022 12:16
@timfish
Copy link
Collaborator

timfish commented Jun 16, 2022

It looks like this change completely clears out other contexts if contexts.trace exists:

if (event.contexts && event.contexts.trace) {
normalized.contexts = {};
normalized.contexts.trace = event.contexts.trace;

Running the Electron e2e tests after this change and all the device/os/etc contexts are stripped out. Is this intensional?

@lobsterkatie
Copy link
Member

No, and I am actually in the process of fixing it for other reasons. Stay tuned!

@lforst
Copy link
Member Author

lforst commented Jun 16, 2022

It looks like this change completely clears out other contexts if contexts.trace

Oh god. Looking at this is painful. Stupid mistake, sorry about that. Btw it appears #5218 also aims to fix this (?).

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.

TypeError: Converting circular structure to JSON
5 participants