diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 0b4fb9faa195..5feb7d3d972e 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -19,6 +19,7 @@ import { logger, parseRetryAfterHeader, PromiseBuffer, + secToMs, SentryError, } from '@sentry/utils'; @@ -209,7 +210,7 @@ export abstract class BaseTransport implements Transport { for (const limit of rlHeader.trim().split(',')) { const parameters = limit.split(':', 2); const headerDelay = parseInt(parameters[0], 10); - const delay = (!isNaN(headerDelay) ? headerDelay : 60) * 1000; // 60sec default + const delay = secToMs(!isNaN(headerDelay) ? headerDelay : 60); // 60sec default for (const category of parameters[1].split(';')) { this._rateLimits[category || 'all'] = new Date(now + delay); } diff --git a/packages/ember/addon/instance-initializers/sentry-performance.ts b/packages/ember/addon/instance-initializers/sentry-performance.ts index c77e9a80738e..3f67ee14d232 100644 --- a/packages/ember/addon/instance-initializers/sentry-performance.ts +++ b/packages/ember/addon/instance-initializers/sentry-performance.ts @@ -5,7 +5,7 @@ import * as Sentry from '@sentry/browser'; import { Span, Transaction, Integration } from '@sentry/types'; import { EmberRunQueues } from '@ember/runloop/-private/types'; import { getActiveTransaction } from '..'; -import { browserPerformanceTimeOrigin, getGlobalObject, timestampWithMs } from '@sentry/utils'; +import { browserPerformanceTimeOrigin, getGlobalObject, timestampWithMs, secToMs, msToSec } from '@sentry/utils'; import { macroCondition, isTesting, getOwnConfig } from '@embroider/macros'; import { EmberSentryConfig, GlobalConfig, OwnConfig } from '../types'; @@ -29,10 +29,7 @@ export function initialize(appInstance: ApplicationInstance): void { } function getBackburner() { - if (run.backburner) { - return run.backburner; - } - return _backburner; + return run.backburner || _backburner; } function getTransitionInformation(transition: any, router: any) { @@ -170,7 +167,7 @@ function _instrumentEmberRunloop(config: EmberSentryConfig) { const now = timestampWithMs(); const minQueueDuration = minimumRunloopQueueDuration ?? 5; - if ((now - currentQueueStart) * 1000 >= minQueueDuration) { + if (secToMs(now - currentQueueStart) >= minQueueDuration) { activeTransaction ?.startChild({ op: `ui.ember.runloop.${queue}`, @@ -326,8 +323,8 @@ function _instrumentInitialLoad(config: EmberSentryConfig) { const measures = performance.getEntriesByName(measureName); const measure = measures[0]; - const startTimestamp = (measure.startTime + browserPerformanceTimeOrigin!) / 1000; - const endTimestamp = startTimestamp + measure.duration / 1000; + const startTimestamp = msToSec(measure.startTime + browserPerformanceTimeOrigin!); + const endTimestamp = startTimestamp + msToSec(measure.duration); const transaction = getActiveTransaction(); const span = transaction?.startChild({ diff --git a/packages/node/src/transports/base/index.ts b/packages/node/src/transports/base/index.ts index 42376ec653e5..eab4ad989506 100644 --- a/packages/node/src/transports/base/index.ts +++ b/packages/node/src/transports/base/index.ts @@ -10,7 +10,14 @@ import { Transport, TransportOptions, } from '@sentry/types'; -import { eventStatusFromHttpCode, logger, parseRetryAfterHeader, PromiseBuffer, SentryError } from '@sentry/utils'; +import { + eventStatusFromHttpCode, + logger, + parseRetryAfterHeader, + PromiseBuffer, + secToMs, + SentryError, +} from '@sentry/utils'; import * as fs from 'fs'; import * as http from 'http'; import * as https from 'https'; @@ -161,7 +168,7 @@ export abstract class BaseTransport implements Transport { for (const limit of rlHeader.trim().split(',')) { const parameters = limit.split(':', 2); const headerDelay = parseInt(parameters[0], 10); - const delay = (!isNaN(headerDelay) ? headerDelay : 60) * 1000; // 60sec default + const delay = secToMs(!isNaN(headerDelay) ? headerDelay : 60); // 60sec default for (const category of (parameters[1] && parameters[1].split(';')) || ['all']) { // categoriesAllowed is added here to ensure we are only storing rate limits for categories we support in this // sdk and any categories that are not supported will not be added redundantly to the rateLimits object diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index 6001613a91de..008dbe522822 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -11,7 +11,7 @@ import { } from '@sentry/node'; import { extractTraceparentData } from '@sentry/tracing'; import { Integration } from '@sentry/types'; -import { isString, logger } from '@sentry/utils'; +import { isString, logger, msToSec } from '@sentry/utils'; // NOTE: I have no idea how to fix this right now, and don't want to waste more time, as it builds just fine — Kamil // eslint-disable-next-line import/no-unresolved import { Context, Handler } from 'aws-lambda'; @@ -257,7 +257,7 @@ export function wrapHandler( context.callbackWaitsForEmptyEventLoop = options.callbackWaitsForEmptyEventLoop; // In seconds. You cannot go any more granular than this in AWS Lambda. - const configuredTimeout = Math.ceil(tryGetRemainingTimeInMillis(context) / 1000); + const configuredTimeout = msToSec(Math.ceil(tryGetRemainingTimeInMillis(context))); const configuredTimeoutMinutes = Math.floor(configuredTimeout / 60); const configuredTimeoutSeconds = configuredTimeout % 60; diff --git a/packages/tracing/src/browser/browsertracing.ts b/packages/tracing/src/browser/browsertracing.ts index 4218f8e84fd7..dfc78eacaa61 100644 --- a/packages/tracing/src/browser/browsertracing.ts +++ b/packages/tracing/src/browser/browsertracing.ts @@ -1,10 +1,10 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration, Transaction, TransactionContext } from '@sentry/types'; -import { getGlobalObject, logger } from '@sentry/utils'; +import { getGlobalObject, logger, secToMs } from '@sentry/utils'; import { startIdleTransaction } from '../hubextensions'; import { DEFAULT_IDLE_TIMEOUT, IdleTransaction } from '../idletransaction'; -import { extractTraceparentData, secToMs } from '../utils'; +import { extractTraceparentData } from '../utils'; import { registerBackgroundTabDetection } from './backgroundtab'; import { MetricsInstrumentation } from './metrics'; import { diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index 867849966516..6c72412f31a2 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -1,11 +1,17 @@ /* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Measurements, SpanContext } from '@sentry/types'; -import { browserPerformanceTimeOrigin, getGlobalObject, htmlTreeAsString, isNodeEnv, logger } from '@sentry/utils'; +import { + browserPerformanceTimeOrigin, + getGlobalObject, + htmlTreeAsString, + isNodeEnv, + logger, + msToSec, +} from '@sentry/utils'; import { Span } from '../span'; import { Transaction } from '../transaction'; -import { msToSec } from '../utils'; import { getCLS, LayoutShift } from './web-vitals/getCLS'; import { getFID } from './web-vitals/getFID'; import { getLCP, LargestContentfulPaint } from './web-vitals/getLCP'; diff --git a/packages/tracing/src/idletransaction.ts b/packages/tracing/src/idletransaction.ts index 07839d6c6616..1e46763cd06e 100644 --- a/packages/tracing/src/idletransaction.ts +++ b/packages/tracing/src/idletransaction.ts @@ -1,6 +1,6 @@ import { Hub } from '@sentry/hub'; import { TransactionContext } from '@sentry/types'; -import { logger, timestampWithMs } from '@sentry/utils'; +import { logger, msToSec, timestampWithMs } from '@sentry/utils'; import { FINISH_REASON_TAG, IDLE_TRANSACTION_FINISH_REASONS } from './constants'; import { Span, SpanRecorder } from './span'; @@ -219,7 +219,7 @@ export class IdleTransaction extends Transaction { const timeout = this._idleTimeout; // We need to add the timeout here to have the real endtimestamp of the transaction // Remember timestampWithMs is in seconds, timeout is in ms - const end = timestampWithMs() + timeout / 1000; + const end = timestampWithMs() + msToSec(timeout); setTimeout(() => { if (!this._finished) { diff --git a/packages/tracing/src/utils.ts b/packages/tracing/src/utils.ts index 0e2ea9ed694b..dcb4a3a521bd 100644 --- a/packages/tracing/src/utils.ts +++ b/packages/tracing/src/utils.ts @@ -52,21 +52,5 @@ export function getActiveTransaction(maybeHub?: Hub): T | return scope && (scope.getTransaction() as T | undefined); } -/** - * Converts from milliseconds to seconds - * @param time time in ms - */ -export function msToSec(time: number): number { - return time / 1000; -} - -/** - * Converts from seconds to milliseconds - * @param time time in seconds - */ -export function secToMs(time: number): number { - return time * 1000; -} - // so it can be used in manual instrumentation without necessitating a hard dependency on @sentry/utils export { stripUrlQueryAndFragment } from '@sentry/utils'; diff --git a/packages/utils/src/misc.ts b/packages/utils/src/misc.ts index e46ffd094f64..33531dbe813f 100644 --- a/packages/utils/src/misc.ts +++ b/packages/utils/src/misc.ts @@ -4,6 +4,7 @@ import { Event, Exception, Mechanism, StackFrame } from '@sentry/types'; import { getGlobalObject } from './global'; import { addNonEnumerableProperty } from './object'; import { snipLine } from './string'; +import { secToMs } from './time'; /** * Extended Window interface that allows for Crypto API usage in IE browsers @@ -41,9 +42,13 @@ export function uuid4(): string { return v; }; - return ( - pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + pad(arr[5]) + pad(arr[6]) + pad(arr[7]) - ); + let i = 0; + let str = pad(arr[0]); + + // eslint-disable-next-line no-plusplus + while (i++ < 7) str += pad(arr[i]); + + return str; } // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, c => { @@ -189,7 +194,7 @@ export function parseSemver(input: string): SemVer { }; } -const defaultRetryAfter = 60 * 1000; // 60 seconds +const defaultRetryAfter = secToMs(60); // 60 seconds /** * Extracts Retry-After value from the request header or returns default value @@ -203,7 +208,7 @@ export function parseRetryAfterHeader(now: number, header?: string | number | nu const headerDelay = parseInt(`${header}`, 10); if (!isNaN(headerDelay)) { - return headerDelay * 1000; + return secToMs(headerDelay); } const headerDate = Date.parse(`${header}`); diff --git a/packages/utils/src/time.ts b/packages/utils/src/time.ts index 932fffc902d9..17b2ca9eccc6 100644 --- a/packages/utils/src/time.ts +++ b/packages/utils/src/time.ts @@ -16,7 +16,7 @@ interface TimestampSource { * is more obvious to explain "why does my span have negative duration" than "why my spans have zero duration". */ const dateTimestampSource: TimestampSource = { - nowSeconds: () => Date.now() / 1000, + nowSeconds: () => msToSec(Date.now()), }; /** @@ -97,7 +97,7 @@ const timestampSource: TimestampSource = platformPerformance === undefined ? dateTimestampSource : { - nowSeconds: () => (platformPerformance.timeOrigin + platformPerformance.now()) / 1000, + nowSeconds: () => msToSec(platformPerformance.timeOrigin + platformPerformance.now()), }; /** @@ -183,3 +183,19 @@ export const browserPerformanceTimeOrigin = ((): number | undefined => { _browserPerformanceTimeOriginMode = 'dateNow'; return dateNow; })(); + +/** + * Converts from milliseconds to seconds + * @param time time in ms + */ +export function msToSec(time: number): number { + return time / 1000; +} + +/** + * Converts from seconds to milliseconds + * @param time time in seconds + */ +export function secToMs(time: number): number { + return time * 1000; +}