UNPKG

@sentry/core

Version:
1 lines 21.3 kB
{"version":3,"file":"idletransaction.js","sources":["../../../src/tracing/idletransaction.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { TransactionContext } from '@sentry/types';\nimport { logger, timestampWithMs } from '@sentry/utils';\n\nimport type { Hub } from '../hub';\nimport type { Span } from './span';\nimport { SpanRecorder } from './span';\nimport { Transaction } from './transaction';\n\nexport const TRACING_DEFAULTS = {\n idleTimeout: 1000,\n finalTimeout: 30000,\n heartbeatInterval: 5000,\n};\n\nconst FINISH_REASON_TAG = 'finishReason';\n\nconst IDLE_TRANSACTION_FINISH_REASONS = [\n 'heartbeatFailed',\n 'idleTimeout',\n 'documentHidden',\n 'finalTimeout',\n 'externalFinish',\n 'cancelled',\n];\n\n/**\n * @inheritDoc\n */\nexport class IdleTransactionSpanRecorder extends SpanRecorder {\n public constructor(\n private readonly _pushActivity: (id: string) => void,\n private readonly _popActivity: (id: string) => void,\n public transactionSpanId: string,\n maxlen?: number,\n ) {\n super(maxlen);\n }\n\n /**\n * @inheritDoc\n */\n public add(span: Span): void {\n // We should make sure we do not push and pop activities for\n // the transaction that this span recorder belongs to.\n if (span.spanId !== this.transactionSpanId) {\n // We patch span.finish() to pop an activity after setting an endTimestamp.\n span.finish = (endTimestamp?: number) => {\n span.endTimestamp = typeof endTimestamp === 'number' ? endTimestamp : timestampWithMs();\n this._popActivity(span.spanId);\n };\n\n // We should only push new activities if the span does not have an end timestamp.\n if (span.endTimestamp === undefined) {\n this._pushActivity(span.spanId);\n }\n }\n\n super.add(span);\n }\n}\n\nexport type BeforeFinishCallback = (transactionSpan: IdleTransaction, endTimestamp: number) => void;\n\n/**\n * An IdleTransaction is a transaction that automatically finishes. It does this by tracking child spans as activities.\n * You can have multiple IdleTransactions active, but if the `onScope` option is specified, the idle transaction will\n * put itself on the scope on creation.\n */\nexport class IdleTransaction extends Transaction {\n // Activities store a list of active spans\n public activities: Record<string, boolean> = {};\n\n // Track state of activities in previous heartbeat\n private _prevHeartbeatString: string | undefined;\n\n // Amount of times heartbeat has counted. Will cause transaction to finish after 3 beats.\n private _heartbeatCounter: number = 0;\n\n // We should not use heartbeat if we finished a transaction\n private _finished: boolean = false;\n\n // Idle timeout was canceled and we should finish the transaction with the last span end.\n private _idleTimeoutCanceledPermanently: boolean = false;\n\n private readonly _beforeFinishCallbacks: BeforeFinishCallback[] = [];\n\n /**\n * Timer that tracks Transaction idleTimeout\n */\n private _idleTimeoutID: ReturnType<typeof setTimeout> | undefined;\n\n private _finishReason: typeof IDLE_TRANSACTION_FINISH_REASONS[number] = IDLE_TRANSACTION_FINISH_REASONS[4];\n\n public constructor(\n transactionContext: TransactionContext,\n private readonly _idleHub: Hub,\n /**\n * The time to wait in ms until the idle transaction will be finished. This timer is started each time\n * there are no active spans on this transaction.\n */\n private readonly _idleTimeout: number = TRACING_DEFAULTS.idleTimeout,\n /**\n * The final value in ms that a transaction cannot exceed\n */\n private readonly _finalTimeout: number = TRACING_DEFAULTS.finalTimeout,\n private readonly _heartbeatInterval: number = TRACING_DEFAULTS.heartbeatInterval,\n // Whether or not the transaction should put itself on the scope when it starts and pop itself off when it ends\n private readonly _onScope: boolean = false,\n ) {\n super(transactionContext, _idleHub);\n\n if (_onScope) {\n // There should only be one active transaction on the scope\n clearActiveTransaction(_idleHub);\n\n // We set the transaction here on the scope so error events pick up the trace\n // context and attach it to the error.\n __DEBUG_BUILD__ && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`);\n _idleHub.configureScope(scope => scope.setSpan(this));\n }\n\n this._restartIdleTimeout();\n setTimeout(() => {\n if (!this._finished) {\n this.setStatus('deadline_exceeded');\n this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[3];\n this.finish();\n }\n }, this._finalTimeout);\n }\n\n /** {@inheritDoc} */\n public finish(endTimestamp: number = timestampWithMs()): string | undefined {\n this._finished = true;\n this.activities = {};\n\n if (this.op === 'ui.action.click') {\n this.setTag(FINISH_REASON_TAG, this._finishReason);\n }\n\n if (this.spanRecorder) {\n __DEBUG_BUILD__ &&\n logger.log('[Tracing] finishing IdleTransaction', new Date(endTimestamp * 1000).toISOString(), this.op);\n\n for (const callback of this._beforeFinishCallbacks) {\n callback(this, endTimestamp);\n }\n\n this.spanRecorder.spans = this.spanRecorder.spans.filter((span: Span) => {\n // If we are dealing with the transaction itself, we just return it\n if (span.spanId === this.spanId) {\n return true;\n }\n\n // We cancel all pending spans with status \"cancelled\" to indicate the idle transaction was finished early\n if (!span.endTimestamp) {\n span.endTimestamp = endTimestamp;\n span.setStatus('cancelled');\n __DEBUG_BUILD__ &&\n logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2));\n }\n\n const keepSpan = span.startTimestamp < endTimestamp;\n if (!keepSpan) {\n __DEBUG_BUILD__ &&\n logger.log(\n '[Tracing] discarding Span since it happened after Transaction was finished',\n JSON.stringify(span, undefined, 2),\n );\n }\n return keepSpan;\n });\n\n __DEBUG_BUILD__ && logger.log('[Tracing] flushing IdleTransaction');\n } else {\n __DEBUG_BUILD__ && logger.log('[Tracing] No active IdleTransaction');\n }\n\n // if `this._onScope` is `true`, the transaction put itself on the scope when it started\n if (this._onScope) {\n clearActiveTransaction(this._idleHub);\n }\n\n return super.finish(endTimestamp);\n }\n\n /**\n * Register a callback function that gets excecuted before the transaction finishes.\n * Useful for cleanup or if you want to add any additional spans based on current context.\n *\n * This is exposed because users have no other way of running something before an idle transaction\n * finishes.\n */\n public registerBeforeFinishCallback(callback: BeforeFinishCallback): void {\n this._beforeFinishCallbacks.push(callback);\n }\n\n /**\n * @inheritDoc\n */\n public initSpanRecorder(maxlen?: number): void {\n if (!this.spanRecorder) {\n const pushActivity = (id: string): void => {\n if (this._finished) {\n return;\n }\n this._pushActivity(id);\n };\n const popActivity = (id: string): void => {\n if (this._finished) {\n return;\n }\n this._popActivity(id);\n };\n\n this.spanRecorder = new IdleTransactionSpanRecorder(pushActivity, popActivity, this.spanId, maxlen);\n\n // Start heartbeat so that transactions do not run forever.\n __DEBUG_BUILD__ && logger.log('Starting heartbeat');\n this._pingHeartbeat();\n }\n this.spanRecorder.add(this);\n }\n\n /**\n * Cancels the existing idle timeout, if there is one.\n * @param restartOnChildSpanChange Default is `true`.\n * If set to false the transaction will end\n * with the last child span.\n */\n public cancelIdleTimeout(\n endTimestamp?: Parameters<IdleTransaction['finish']>[0],\n {\n restartOnChildSpanChange,\n }: {\n restartOnChildSpanChange?: boolean;\n } = {\n restartOnChildSpanChange: true,\n },\n ): void {\n this._idleTimeoutCanceledPermanently = restartOnChildSpanChange === false;\n if (this._idleTimeoutID) {\n clearTimeout(this._idleTimeoutID);\n this._idleTimeoutID = undefined;\n\n if (Object.keys(this.activities).length === 0 && this._idleTimeoutCanceledPermanently) {\n this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[5];\n this.finish(endTimestamp);\n }\n }\n }\n\n /**\n * Restarts idle timeout, if there is no running idle timeout it will start one.\n */\n private _restartIdleTimeout(endTimestamp?: Parameters<IdleTransaction['finish']>[0]): void {\n this.cancelIdleTimeout();\n this._idleTimeoutID = setTimeout(() => {\n if (!this._finished && Object.keys(this.activities).length === 0) {\n this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[1];\n this.finish(endTimestamp);\n }\n }, this._idleTimeout);\n }\n\n /**\n * Start tracking a specific activity.\n * @param spanId The span id that represents the activity\n */\n private _pushActivity(spanId: string): void {\n this.cancelIdleTimeout(undefined, { restartOnChildSpanChange: !this._idleTimeoutCanceledPermanently });\n __DEBUG_BUILD__ && logger.log(`[Tracing] pushActivity: ${spanId}`);\n this.activities[spanId] = true;\n __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length);\n }\n\n /**\n * Remove an activity from usage\n * @param spanId The span id that represents the activity\n */\n private _popActivity(spanId: string): void {\n if (this.activities[spanId]) {\n __DEBUG_BUILD__ && logger.log(`[Tracing] popActivity ${spanId}`);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete this.activities[spanId];\n __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length);\n }\n\n if (Object.keys(this.activities).length === 0) {\n const endTimestamp = timestampWithMs();\n if (this._idleTimeoutCanceledPermanently) {\n this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[5];\n this.finish(endTimestamp);\n } else {\n // We need to add the timeout here to have the real endtimestamp of the transaction\n // Remember timestampWithMs is in seconds, timeout is in ms\n this._restartIdleTimeout(endTimestamp + this._idleTimeout / 1000);\n }\n }\n }\n\n /**\n * Checks when entries of this.activities are not changing for 3 beats.\n * If this occurs we finish the transaction.\n */\n private _beat(): void {\n // We should not be running heartbeat if the idle transaction is finished.\n if (this._finished) {\n return;\n }\n\n const heartbeatString = Object.keys(this.activities).join('');\n\n if (heartbeatString === this._prevHeartbeatString) {\n this._heartbeatCounter++;\n } else {\n this._heartbeatCounter = 1;\n }\n\n this._prevHeartbeatString = heartbeatString;\n\n if (this._heartbeatCounter >= 3) {\n __DEBUG_BUILD__ && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats');\n this.setStatus('deadline_exceeded');\n this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[0];\n this.finish();\n } else {\n this._pingHeartbeat();\n }\n }\n\n /**\n * Pings the heartbeat\n */\n private _pingHeartbeat(): void {\n __DEBUG_BUILD__ && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`);\n setTimeout(() => {\n this._beat();\n }, this._heartbeatInterval);\n }\n}\n\n/**\n * Reset transaction on scope to `undefined`\n */\nfunction clearActiveTransaction(hub: Hub): void {\n const scope = hub.getScope();\n if (scope) {\n const transaction = scope.getTransaction();\n if (transaction) {\n scope.setSpan(undefined);\n }\n }\n}\n"],"names":[],"mappings":"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"}