@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
1 lines • 7.96 kB
Source Map (JSON)
{"version":3,"file":"time.js","sources":["../../../src/utils/time.ts"],"sourcesContent":["import { GLOBAL_OBJ } from './worldwide';\n\nconst ONE_SECOND_IN_MS = 1000;\n\n/**\n * A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}\n * for accessing a high-resolution monotonic clock.\n */\ninterface Performance {\n /**\n * The millisecond timestamp at which measurement began, measured in Unix time.\n */\n timeOrigin: number;\n /**\n * Returns the current millisecond timestamp, where 0 represents the start of measurement.\n */\n now(): number;\n}\n\n/**\n * Returns a timestamp in seconds since the UNIX epoch using the Date API.\n */\nexport function dateTimestampInSeconds(): number {\n return Date.now() / ONE_SECOND_IN_MS;\n}\n\n/**\n * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not\n * support the API.\n *\n * Wrapping the native API works around differences in behavior from different browsers.\n */\nfunction createUnixTimestampInSecondsFunc(): () => number {\n const { performance } = GLOBAL_OBJ as typeof GLOBAL_OBJ & { performance?: Performance };\n // Some browser and environments don't have a performance or timeOrigin, so we fallback to\n // using Date.now() to compute the starting time.\n if (!performance?.now || !performance.timeOrigin) {\n return dateTimestampInSeconds;\n }\n\n const timeOrigin = performance.timeOrigin;\n\n // performance.now() is a monotonic clock, which means it starts at 0 when the process begins. To get the current\n // wall clock time (actual UNIX timestamp), we need to add the starting time origin and the current time elapsed.\n //\n // TODO: This does not account for the case where the monotonic clock that powers performance.now() drifts from the\n // wall clock time, which causes the returned timestamp to be inaccurate. We should investigate how to detect and\n // correct for this.\n // See: https://github.com/getsentry/sentry-javascript/issues/2590\n // See: https://github.com/mdn/content/issues/4713\n // See: https://dev.to/noamr/when-a-millisecond-is-not-a-millisecond-3h6\n return () => {\n return (timeOrigin + performance.now()) / ONE_SECOND_IN_MS;\n };\n}\n\nlet _cachedTimestampInSeconds: (() => number) | undefined;\n\n/**\n * Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the\n * availability of the Performance API.\n *\n * BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is\n * asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The\n * skew can grow to arbitrary amounts like days, weeks or months.\n * See https://github.com/getsentry/sentry-javascript/issues/2590.\n */\nexport function timestampInSeconds(): number {\n // We store this in a closure so that we don't have to create a new function every time this is called.\n const func = _cachedTimestampInSeconds ?? (_cachedTimestampInSeconds = createUnixTimestampInSecondsFunc());\n return func();\n}\n\n/**\n * Cached result of getBrowserTimeOrigin.\n */\nlet cachedTimeOrigin: [number | undefined, string] | undefined;\n\n/**\n * Gets the time origin and the mode used to determine it.\n */\nfunction getBrowserTimeOrigin(): [number | undefined, string] {\n // Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or\n // performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin\n // data as reliable if they are within a reasonable threshold of the current time.\n\n const { performance } = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n if (!performance?.now) {\n return [undefined, 'none'];\n }\n\n const threshold = 3600 * 1000;\n const performanceNow = performance.now();\n const dateNow = Date.now();\n\n // if timeOrigin isn't available set delta to threshold so it isn't used\n const timeOriginDelta = performance.timeOrigin\n ? Math.abs(performance.timeOrigin + performanceNow - dateNow)\n : threshold;\n const timeOriginIsReliable = timeOriginDelta < threshold;\n\n // While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin\n // is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.\n // Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always\n // a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the\n // Date API.\n // eslint-disable-next-line deprecation/deprecation\n const navigationStart = performance.timing?.navigationStart;\n const hasNavigationStart = typeof navigationStart === 'number';\n // if navigationStart isn't available set delta to threshold so it isn't used\n const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;\n const navigationStartIsReliable = navigationStartDelta < threshold;\n\n if (timeOriginIsReliable || navigationStartIsReliable) {\n // Use the more reliable time origin\n if (timeOriginDelta <= navigationStartDelta) {\n return [performance.timeOrigin, 'timeOrigin'];\n } else {\n return [navigationStart, 'navigationStart'];\n }\n }\n\n // Either both timeOrigin and navigationStart are skewed or neither is available, fallback to Date.\n return [dateNow, 'dateNow'];\n}\n\n/**\n * The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the\n * performance API is available.\n */\nexport function browserPerformanceTimeOrigin(): number | undefined {\n if (!cachedTimeOrigin) {\n cachedTimeOrigin = getBrowserTimeOrigin();\n }\n\n return cachedTimeOrigin[0];\n}\n"],"names":["GLOBAL_OBJ"],"mappings":";;;;AAEA,MAAM,gBAAA,GAAmB,IAAI;;AAE7B;AACA;AACA;AACA;;AAYA;AACA;AACA;AACO,SAAS,sBAAsB,GAAW;AACjD,EAAE,OAAO,IAAI,CAAC,GAAG,EAAC,GAAI,gBAAgB;AACtC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gCAAgC,GAAiB;AAC1D,EAAE,MAAM,EAAE,WAAA,EAAY,GAAIA,oBAAA;AAC1B;AACA;AACA,EAAE,IAAI,CAAC,WAAW,EAAE,GAAA,IAAO,CAAC,WAAW,CAAC,UAAU,EAAE;AACpD,IAAI,OAAO,sBAAsB;AACjC;;AAEA,EAAE,MAAM,UAAA,GAAa,WAAW,CAAC,UAAU;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,OAAO,MAAM;AACf,IAAI,OAAO,CAAC,UAAA,GAAa,WAAW,CAAC,GAAG,EAAE,IAAI,gBAAgB;AAC9D,GAAG;AACH;;AAEA,IAAI,yBAAyB;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,GAAW;AAC7C;AACA,EAAE,MAAM,IAAA,GAAO,yBAAA,KAA8B,yBAAA,GAA4B,gCAAgC,EAAE,CAAC;AAC5G,EAAE,OAAO,IAAI,EAAE;AACf;;AAEA;AACA;AACA;AACA,IAAI,gBAAgB;;AAEpB;AACA;AACA;AACA,SAAS,oBAAoB,GAAiC;AAC9D;AACA;AACA;;AAEA,EAAE,MAAM,EAAE,WAAA,EAAY,GAAIA,oBAAA;AAC1B,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;AACzB,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;AAC9B;;AAEA,EAAE,MAAM,SAAA,GAAY,IAAA,GAAO,IAAI;AAC/B,EAAE,MAAM,cAAA,GAAiB,WAAW,CAAC,GAAG,EAAE;AAC1C,EAAE,MAAM,OAAA,GAAU,IAAI,CAAC,GAAG,EAAE;;AAE5B;AACA,EAAE,MAAM,eAAA,GAAkB,WAAW,CAAC;AACtC,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,UAAA,GAAa,cAAA,GAAiB,OAAO;AAChE,MAAM,SAAS;AACf,EAAE,MAAM,oBAAA,GAAuB,eAAA,GAAkB,SAAS;;AAE1D;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,MAAM,eAAA,GAAkB,WAAW,CAAC,MAAM,EAAE,eAAe;AAC7D,EAAE,MAAM,kBAAA,GAAqB,OAAO,eAAA,KAAoB,QAAQ;AAChE;AACA,EAAE,MAAM,oBAAA,GAAuB,kBAAA,GAAqB,IAAI,CAAC,GAAG,CAAC,eAAA,GAAkB,cAAA,GAAiB,OAAO,CAAA,GAAI,SAAS;AACpH,EAAE,MAAM,yBAAA,GAA4B,oBAAA,GAAuB,SAAS;;AAEpE,EAAE,IAAI,oBAAA,IAAwB,yBAAyB,EAAE;AACzD;AACA,IAAI,IAAI,eAAA,IAAmB,oBAAoB,EAAE;AACjD,MAAM,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,YAAY,CAAC;AACnD,WAAW;AACX,MAAM,OAAO,CAAC,eAAe,EAAE,iBAAiB,CAAC;AACjD;AACA;;AAEA;AACA,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;AAC7B;;AAEA;AACA;AACA;AACA;AACO,SAAS,4BAA4B,GAAuB;AACnE,EAAE,IAAI,CAAC,gBAAgB,EAAE;AACzB,IAAI,gBAAA,GAAmB,oBAAoB,EAAE;AAC7C;;AAEA,EAAE,OAAO,gBAAgB,CAAC,CAAC,CAAC;AAC5B;;;;;;"}