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: Use monotonic clock to compute durations #2441

Merged
merged 2 commits into from
Feb 27, 2020

Conversation

rhcarvalho
Copy link
Contributor

@rhcarvalho rhcarvalho commented Feb 20, 2020

A monotonic clock is monotonically increasing and not subject to system
clock adjustments or system clock skew. The difference between any two
chronologically recorded time values returned from the Performance.now()
method MUST never be negative if the two time values have the same time
origin.

The same guarantee above does not exist for the difference between two
calls to new Date().getTime() as used by timestampWithMs().

Resources:

https://stackoverflow.com/questions/7272395/monotonically-increasing-time-in-javascript
https://caniuse.com/#search=performance.now
https://www.w3.org/TR/hr-time/
https://www.w3.org/TR/hr-time-2/
https://nodejs.org/api/perf_hooks.html


Know limitation

At present, we only address timestamp computation within a single span.
A more complete patch should compute all durations in a transaction using a monotonic clock and set all timestamps relative to a single reading of a wall clock time source.

@@ -261,7 +272,9 @@ export class Span implements SpanInterface, SpanContext {
return undefined;
}

this.timestamp = timestampWithMs();
// TODO: Fallback to timestampWithMs() when performance.now is unavailable.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggestions for how to do this welcome.

Could use a polyfill for performance.now or conditionally set _startTimestampMonotonic to some sentinel value and check it here.

Copy link
Member

Choose a reason for hiding this comment

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

It looks like the policy for the JS SDK is to not polyfill anything older than Edge (i.e. IE 11 and older): #2003

So, I think we should be safe in not worrying about this 👍

Comment on lines +87 to +110
* Works with mostly any browser version released since 2012.
* https://caniuse.com/#search=performance.now
*
* Works with Node.js v8.5.0 or higher.
* https://nodejs.org/api/perf_hooks.html#perf_hooks_performance_now
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Couldn't find what platform versions we support. What are we targeting?
I see a Travis job with Node 8, namely v8.17.0.
I also see Node 6, v6.17.1. Likely no performance.now there.

What about browser support?

@rhcarvalho
Copy link
Contributor Author

Related: getsentry/sentry-python#631

@dashed
Copy link
Member

dashed commented Feb 20, 2020

I'm not opposed to this 👍

@dashed
Copy link
Member

dashed commented Feb 21, 2020

@rhcarvalho you probably need the following to address the travis build failures:

import { isNodeEnv } from '@sentry/utils';
const { performance } = isNodeEnv() ? require('perf_hooks') : window.performance;

@rhcarvalho
Copy link
Contributor Author

@rhcarvalho you probably need the following to address the travis build failures:

import { isNodeEnv } from '@sentry/utils';
const { performance } = isNodeEnv() ? require('perf_hooks') : window.performance;

Thanks @dashed! That helps :) I missed this step for node.

I read that performance is global in WebWorkers (https://www.w3.org/TR/hr-time-2/#extensions-to-windoworworkerglobalscope-mixin), I think we need to account for that usage too, don't we?

@dashed
Copy link
Member

dashed commented Feb 21, 2020

@rhcarvalho I think so. But I'm not familiar with WebWorkers unfortunately.

A monotonic clock is monotonically increasing and not subject to system
clock adjustments or system clock skew. The difference between any two
chronologically recorded time values returned from the Performance.now()
method MUST never be negative if the two time values have the same time
origin.

The same guarantee above does not exist for the difference between two
calls to `new Date().getTime()` as used by `timestampWithMs()`.

Resources:

https://stackoverflow.com/questions/7272395/monotonically-increasing-time-in-javascript
https://caniuse.com/#search=performance.now
https://www.w3.org/TR/hr-time/#sec-monotonic-clock
@getsentry-bot
Copy link
Contributor

getsentry-bot commented Feb 26, 2020

Fails
🚫

TSLint failed: @sentry/hub

  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[20, 11]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[20, 29]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[21, 12]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[112, 55]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[294, 30]: Unsafe use of expression of type 'any'.
🚫

TSLint failed: @sentry/apm

  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[20, 11]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[20, 29]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[21, 12]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[112, 55]: Unsafe use of expression of type 'any'.
  • ERROR: /home/travis/build/getsentry/sentry-javascript/packages/apm/src/span.ts[294, 30]: Unsafe use of expression of type 'any'.
Warnings
⚠️ Please add a changelog entry for your changes.
Messages
📖

@sentry/browser bundle gzip'ed minified size: (ES6: 15.7197 kB) (ES5: 16.7012 kB)

Generated by 🚫 dangerJS against b549180

@rhcarvalho
Copy link
Contributor Author

For Node.js we need perf_hooks which is available starting with Node v8.5.0
https://nodejs.org/api/perf_hooks.html#perf_hooks_performance_now

For this to move forward we need either a hack to use a different timer or drop Node 6 support #2455.

@dashed
Copy link
Member

dashed commented Feb 26, 2020

@rhcarvalho I'm highly confident that Node.js 6 support can be safely dropped as per https://github.com/nodejs/Release#end-of-life-releases

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.

4 participants