Skip to content

Conversation

@kamilogorek
Copy link
Contributor

Reference: https://forum.sentry.io/t/bad-sorting-of-manual-breadcrumbs/3630

At first, I fixed it in the JS SDK getsentry/sentry-javascript#1308, however, after rethinking it, I believe we should do this here, so it's fixed for every SDK instead.

It's out of order, because timestamp is one of the parameters that can be passed to captureBreadcrumb, yet we push them at the end of the breadcrumbs array as they happen.

@MaxBittker
Copy link
Contributor

Awesome, not sure what percentage of events will be effected, but this seems much more correct.

How well does this deal with undefined timestamps - is there a risk that any of the major sdks are sending differently formed data for this key here? or do we normalize them on the server?

the percy snapshot breadcrumbs have been re-ordered - the exceptions seem to all get moved to the top. is this just a problem with that hardcoded mock data we should fix?

@kamilogorek
Copy link
Contributor Author

I somehow don't have access to Percy to verify this. I checked components that render breadcrumbs and they don't handle missing data, so I assumed they have to be unified at one point if we already allowed that. We might have to double-check it.

@dcramer can you give me Percy access?

Copy link
Contributor

@benvinegar benvinegar left a comment

Choose a reason for hiding this comment

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

.sort needs to return -1, 0, or 1.

// reverse array to get consistent idx between collapsed/expanded state
// (indexes begin and increment from last breadcrumb)
return crumbs
.sort((a, b) => a.timestamp > b.timestamp)
Copy link
Contributor

Choose a reason for hiding this comment

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

The results in Percy suggest this isn't sorting correctly.

.sort should return -1, 0, or 1. Is it possible this is the cause?

@kamilogorek
Copy link
Contributor Author

@MaxBittker about undefined timestamps, it cannot happen, we have a check for this -

def normalize_crumb(cls, crumb):
ty = crumb.get('type') or 'default'
ts = parse_timestamp(crumb.get('timestamp'))
if ts is None:
raise InterfaceValidationError('Unable to determine timestamp ' 'for crumb')
rv = {
'type': ty,
'timestamp': to_timestamp(ts),
}

@benvinegar true/false implicitly coerces to 1/0 and we care only about whether we return 1 or not in this case.

The issue, however, is much more complicated than this and took me a while to find the main cause. The first crumb, which is the main exception is simply created not on the same day.

Issue flow:

tl;dr (as I believe it works): created sample event uses fixed timestamp, where breadcrumbs are updated based on the current date (which can be seen on Percy's screenshots)

Also, how about doing this operation in the interface instead of UI?

def to_python(cls, data):
values = []
for crumb in data.get('values') or ():
try:
values.append(cls.normalize_crumb(crumb))
except InterfaceValidationError:
# TODO(dcramer): we dont want to discard the entirety of data
# when one breadcrumb errors, but it'd be nice if we could still
# record an error
continue
return cls(values=values)

@mitsuhiko
Copy link
Contributor

I'm still super -1 on this. What if we only sort a certain subset of breadcrumbs? JavaScript time is fundamentally nonmonotonic and local so breadcrumbs are likely to be fucked whenever the system time readjusts or we get to a timezone change.

Copy link
Contributor

@mitsuhiko mitsuhiko left a comment

Choose a reason for hiding this comment

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

I really do not want to do this. We could offer it as an option (toggle between order of submission / timestamp) optionally.

@kamilogorek
Copy link
Contributor Author

I'm totally fine keeping it in dataCallback of JS SDK as well and won't hesitate to close this pr.

@benvinegar
Copy link
Contributor

benvinegar commented May 11, 2018

@benvinegar true/false implicitly coerces to 1/0 and we care only about whether we return 1 or not in this case.

It's not that it coerces to 1/0. My understanding is that 1 and 0 is not enough to produce stable results depending on the browser's internal sorting algorithm, which is not standardized.

More here: https://stackoverflow.com/questions/234683/javascript-array-sort-implementation/234777#234777

For example, this occurs in Chrome right now:

[5, 8, 7, 1, 2, 3, 4, 6, 9, 10, 11, 12, 13].sort(function(a, b) {
    return a > b; // true/false ... 1/0
});
// => [4, 5, 3, 1, 2, 6, 7, 8, 9, 10, 11, 12, 13] // not sorted

@kamilogorek kamilogorek deleted the sort-breadcrumbs branch June 15, 2018 12:30
@kamilogorek
Copy link
Contributor Author

Not relevant anymore due to v4 SDK.

@github-actions github-actions bot locked and limited conversation to collaborators Dec 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants