package.build.cjs.time.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
Utilities for all Sentry JavaScript SDKs
Object.defineProperty(exports, '__esModule', { value: true });
const worldwide = require('./worldwide.js');
const ONE_SECOND_IN_MS = 1000;
/**
* A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
* for accessing a high-resolution monotonic clock.
*/
/**
* Returns a timestamp in seconds since the UNIX epoch using the Date API.
*
* TODO(v8): Return type should be rounded.
*/
function dateTimestampInSeconds() {
return Date.now() / ONE_SECOND_IN_MS;
}
/**
* Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
* support the API.
*
* Wrapping the native API works around differences in behavior from different browsers.
*/
function createUnixTimestampInSecondsFunc() {
const { performance } = worldwide.GLOBAL_OBJ ;
if (!performance || !performance.now) {
return dateTimestampInSeconds;
}
// Some browser and environments don't have a timeOrigin, so we fallback to
// using Date.now() to compute the starting time.
const approxStartingTimeOrigin = Date.now() - performance.now();
const timeOrigin = performance.timeOrigin == undefined ? approxStartingTimeOrigin : performance.timeOrigin;
// performance.now() is a monotonic clock, which means it starts at 0 when the process begins. To get the current
// wall clock time (actual UNIX timestamp), we need to add the starting time origin and the current time elapsed.
//
// TODO: This does not account for the case where the monotonic clock that powers performance.now() drifts from the
// wall clock time, which causes the returned timestamp to be inaccurate. We should investigate how to detect and
// correct for this.
// See: https://github.com/getsentry/sentry-javascript/issues/2590
// See: https://github.com/mdn/content/issues/4713
// See: https://dev.to/noamr/when-a-millisecond-is-not-a-millisecond-3h6
return () => {
return (timeOrigin + performance.now()) / ONE_SECOND_IN_MS;
};
}
/**
* Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the
* availability of the Performance API.
*
* BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is
* asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The
* skew can grow to arbitrary amounts like days, weeks or months.
* See https://github.com/getsentry/sentry-javascript/issues/2590.
*/
const timestampInSeconds = createUnixTimestampInSecondsFunc();
/**
* Internal helper to store what is the source of browserPerformanceTimeOrigin below. For debugging only.
*/
exports._browserPerformanceTimeOriginMode = void 0;
/**
* The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
* performance API is available.
*/
const browserPerformanceTimeOrigin = (() => {
// Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
// performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
// data as reliable if they are within a reasonable threshold of the current time.
const { performance } = worldwide.GLOBAL_OBJ ;
if (!performance || !performance.now) {
exports._browserPerformanceTimeOriginMode = 'none';
return undefined;
}
const threshold = 3600 * 1000;
const performanceNow = performance.now();
const dateNow = Date.now();
// if timeOrigin isn't available set delta to threshold so it isn't used
const timeOriginDelta = performance.timeOrigin
? Math.abs(performance.timeOrigin + performanceNow - dateNow)
: threshold;
const timeOriginIsReliable = timeOriginDelta < threshold;
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
// Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always
// a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the
// Date API.
// eslint-disable-next-line deprecation/deprecation
const navigationStart = performance.timing && performance.timing.navigationStart;
const hasNavigationStart = typeof navigationStart === 'number';
// if navigationStart isn't available set delta to threshold so it isn't used
const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;
const navigationStartIsReliable = navigationStartDelta < threshold;
if (timeOriginIsReliable || navigationStartIsReliable) {
// Use the more reliable time origin
if (timeOriginDelta <= navigationStartDelta) {
exports._browserPerformanceTimeOriginMode = 'timeOrigin';
return performance.timeOrigin;
} else {
exports._browserPerformanceTimeOriginMode = 'navigationStart';
return navigationStart;
}
}
// Either both timeOrigin and navigationStart are skewed or neither is available, fallback to Date.
exports._browserPerformanceTimeOriginMode = 'dateNow';
return dateNow;
})();
exports.browserPerformanceTimeOrigin = browserPerformanceTimeOrigin;
exports.dateTimestampInSeconds = dateTimestampInSeconds;
exports.timestampInSeconds = timestampInSeconds;
//# sourceMappingURL=time.js.map