package.build.esm.tracing.idleSpan.js.map Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core Show documentation
Show all versions of core Show documentation
Base implementation for all Sentry JavaScript SDKs
{"version":3,"file":"idleSpan.js","sources":["../../../src/tracing/idleSpan.ts"],"sourcesContent":["import type { Span, SpanAttributes, StartSpanOptions } from '@sentry/types';\nimport { logger, timestampInSeconds } from '@sentry/utils';\nimport { getClient, getCurrentScope } from '../currentScopes';\n\nimport { DEBUG_BUILD } from '../debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '../semanticAttributes';\nimport { hasTracingEnabled } from '../utils/hasTracingEnabled';\nimport { _setSpanForScope } from '../utils/spanOnScope';\nimport {\n getActiveSpan,\n getSpanDescendants,\n removeChildSpanFromSpan,\n spanTimeInputToSeconds,\n spanToJSON,\n} from '../utils/spanUtils';\nimport { SentryNonRecordingSpan } from './sentryNonRecordingSpan';\nimport { SPAN_STATUS_ERROR } from './spanstatus';\nimport { startInactiveSpan } from './trace';\n\nexport const TRACING_DEFAULTS = {\n idleTimeout: 1_000,\n finalTimeout: 30_000,\n childSpanTimeout: 15_000,\n};\n\nconst FINISH_REASON_HEARTBEAT_FAILED = 'heartbeatFailed';\nconst FINISH_REASON_IDLE_TIMEOUT = 'idleTimeout';\nconst FINISH_REASON_FINAL_TIMEOUT = 'finalTimeout';\nconst FINISH_REASON_EXTERNAL_FINISH = 'externalFinish';\nconst FINISH_REASON_CANCELLED = 'cancelled';\n\n// unused\nconst FINISH_REASON_DOCUMENT_HIDDEN = 'documentHidden';\n\n// unusued in this file, but used in BrowserTracing\nconst FINISH_REASON_INTERRUPTED = 'interactionInterrupted';\n\ntype IdleSpanFinishReason =\n | typeof FINISH_REASON_CANCELLED\n | typeof FINISH_REASON_DOCUMENT_HIDDEN\n | typeof FINISH_REASON_EXTERNAL_FINISH\n | typeof FINISH_REASON_FINAL_TIMEOUT\n | typeof FINISH_REASON_HEARTBEAT_FAILED\n | typeof FINISH_REASON_IDLE_TIMEOUT\n | typeof FINISH_REASON_INTERRUPTED;\n\ninterface IdleSpanOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n */\n idleTimeout: number;\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n */\n finalTimeout: number;\n /**\n * The max. time a child span may run.\n * If the time since the last span was started exceeds this time, the idle span will finish.\n */\n childSpanTimeout?: number;\n /**\n * When set to `true`, will disable the idle timeout and child timeout\n * until the `idleSpanEnableAutoFinish` hook is emitted for the idle span.\n * The final timeout mechanism will not be affected by this option,\n * meaning the idle span will definitely be finished when the final timeout is\n * reached, no matter what this option is configured to.\n *\n * Defaults to `false`.\n */\n disableAutoFinish?: boolean;\n /** Allows to configure a hook that is called when the idle span is ended, before it is processed. */\n beforeSpanEnd?: (span: Span) => void;\n}\n\n/**\n * An idle span is a span that automatically finishes. It does this by tracking child spans as activities.\n * An idle span is always the active span.\n */\nexport function startIdleSpan(startSpanOptions: StartSpanOptions, options: Partial = {}): Span {\n // Activities store a list of active spans\n const activities = new Map();\n\n // We should not use heartbeat if we finished a span\n let _finished = false;\n\n // Timer that tracks idleTimeout\n let _idleTimeoutID: ReturnType | undefined;\n\n // Timer that tracks maxSpanTime for child spans\n let _childSpanTimeoutID: ReturnType | undefined;\n\n // The reason why the span was finished\n let _finishReason: IdleSpanFinishReason = FINISH_REASON_EXTERNAL_FINISH;\n\n let _autoFinishAllowed: boolean = !options.disableAutoFinish;\n\n const _cleanupHooks: (() => void)[] = [];\n\n const {\n idleTimeout = TRACING_DEFAULTS.idleTimeout,\n finalTimeout = TRACING_DEFAULTS.finalTimeout,\n childSpanTimeout = TRACING_DEFAULTS.childSpanTimeout,\n beforeSpanEnd,\n } = options;\n\n const client = getClient();\n\n if (!client || !hasTracingEnabled()) {\n return new SentryNonRecordingSpan();\n }\n\n const scope = getCurrentScope();\n const previousActiveSpan = getActiveSpan();\n const span = _startIdleSpan(startSpanOptions);\n\n // We patch span.end to ensure we can run some things before the span is ended\n // eslint-disable-next-line @typescript-eslint/unbound-method\n span.end = new Proxy(span.end, {\n apply(target, thisArg, args: Parameters) {\n if (beforeSpanEnd) {\n beforeSpanEnd(span);\n }\n\n // Just ensuring that this keeps working, even if we ever have more arguments here\n const [definedEndTimestamp, ...rest] = args;\n const timestamp = definedEndTimestamp || timestampInSeconds();\n const spanEndTimestamp = spanTimeInputToSeconds(timestamp);\n\n // Ensure we end with the last span timestamp, if possible\n const spans = getSpanDescendants(span).filter(child => child !== span);\n\n // If we have no spans, we just end, nothing else to do here\n if (!spans.length) {\n onIdleSpanEnded(spanEndTimestamp);\n return Reflect.apply(target, thisArg, [spanEndTimestamp, ...rest]);\n }\n\n const childEndTimestamps = spans\n .map(span => spanToJSON(span).timestamp)\n .filter(timestamp => !!timestamp) as number[];\n const latestSpanEndTimestamp = childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined;\n\n // In reality this should always exist here, but type-wise it may be undefined...\n const spanStartTimestamp = spanToJSON(span).start_timestamp;\n\n // The final endTimestamp should:\n // * Never be before the span start timestamp\n // * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp\n // * Otherwise be the passed end timestamp\n // Final timestamp can never be after finalTimeout\n const endTimestamp = Math.min(\n spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity,\n Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)),\n );\n\n onIdleSpanEnded(endTimestamp);\n return Reflect.apply(target, thisArg, [endTimestamp, ...rest]);\n },\n });\n\n /**\n * Cancels the existing idle timeout, if there is one.\n */\n function _cancelIdleTimeout(): void {\n if (_idleTimeoutID) {\n clearTimeout(_idleTimeoutID);\n _idleTimeoutID = undefined;\n }\n }\n\n /**\n * Cancels the existing child span timeout, if there is one.\n */\n function _cancelChildSpanTimeout(): void {\n if (_childSpanTimeoutID) {\n clearTimeout(_childSpanTimeoutID);\n _childSpanTimeoutID = undefined;\n }\n }\n\n /**\n * Restarts idle timeout, if there is no running idle timeout it will start one.\n */\n function _restartIdleTimeout(endTimestamp?: number): void {\n _cancelIdleTimeout();\n _idleTimeoutID = setTimeout(() => {\n if (!_finished && activities.size === 0 && _autoFinishAllowed) {\n _finishReason = FINISH_REASON_IDLE_TIMEOUT;\n span.end(endTimestamp);\n }\n }, idleTimeout);\n }\n\n /**\n * Restarts child span timeout, if there is none running it will start one.\n */\n function _restartChildSpanTimeout(endTimestamp?: number): void {\n _cancelChildSpanTimeout();\n _idleTimeoutID = setTimeout(() => {\n if (!_finished && _autoFinishAllowed) {\n _finishReason = FINISH_REASON_HEARTBEAT_FAILED;\n span.end(endTimestamp);\n }\n }, childSpanTimeout);\n }\n\n /**\n * Start tracking a specific activity.\n * @param spanId The span id that represents the activity\n */\n function _pushActivity(spanId: string): void {\n _cancelIdleTimeout();\n activities.set(spanId, true);\n\n const endTimestamp = timestampInSeconds();\n // We need to add the timeout here to have the real endtimestamp of the idle span\n // Remember timestampInSeconds is in seconds, timeout is in ms\n _restartChildSpanTimeout(endTimestamp + childSpanTimeout / 1000);\n }\n\n /**\n * Remove an activity from usage\n * @param spanId The span id that represents the activity\n */\n function _popActivity(spanId: string): void {\n if (activities.has(spanId)) {\n activities.delete(spanId);\n }\n\n if (activities.size === 0) {\n const endTimestamp = timestampInSeconds();\n // We need to add the timeout here to have the real endtimestamp of the idle span\n // Remember timestampInSeconds is in seconds, timeout is in ms\n _restartIdleTimeout(endTimestamp + idleTimeout / 1000);\n _cancelChildSpanTimeout();\n }\n }\n\n function onIdleSpanEnded(endTimestamp: number): void {\n _finished = true;\n activities.clear();\n\n _cleanupHooks.forEach(cleanup => cleanup());\n\n _setSpanForScope(scope, previousActiveSpan);\n\n const spanJSON = spanToJSON(span);\n\n const { start_timestamp: startTimestamp } = spanJSON;\n // This should never happen, but to make TS happy...\n if (!startTimestamp) {\n return;\n }\n\n const attributes: SpanAttributes = spanJSON.data || {};\n if (!attributes[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, _finishReason);\n }\n\n logger.log(`[Tracing] Idle span \"${spanJSON.op}\" finished`);\n\n const childSpans = getSpanDescendants(span).filter(child => child !== span);\n\n let discardedSpans = 0;\n childSpans.forEach(childSpan => {\n // We cancel all pending spans with status \"cancelled\" to indicate the idle span was finished early\n if (childSpan.isRecording()) {\n childSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n childSpan.end(endTimestamp);\n DEBUG_BUILD &&\n logger.log('[Tracing] Cancelling span since span ended early', JSON.stringify(childSpan, undefined, 2));\n }\n\n const childSpanJSON = spanToJSON(childSpan);\n const { timestamp: childEndTimestamp = 0, start_timestamp: childStartTimestamp = 0 } = childSpanJSON;\n\n const spanStartedBeforeIdleSpanEnd = childStartTimestamp <= endTimestamp;\n\n // Add a delta with idle timeout so that we prevent false positives\n const timeoutWithMarginOfError = (finalTimeout + idleTimeout) / 1000;\n const spanEndedBeforeFinalTimeout = childEndTimestamp - childStartTimestamp <= timeoutWithMarginOfError;\n\n if (DEBUG_BUILD) {\n const stringifiedSpan = JSON.stringify(childSpan, undefined, 2);\n if (!spanStartedBeforeIdleSpanEnd) {\n logger.log('[Tracing] Discarding span since it happened after idle span was finished', stringifiedSpan);\n } else if (!spanEndedBeforeFinalTimeout) {\n logger.log('[Tracing] Discarding span since it finished after idle span final timeout', stringifiedSpan);\n }\n }\n\n if (!spanEndedBeforeFinalTimeout || !spanStartedBeforeIdleSpanEnd) {\n removeChildSpanFromSpan(span, childSpan);\n discardedSpans++;\n }\n });\n\n if (discardedSpans > 0) {\n span.setAttribute('sentry.idle_span_discarded_spans', discardedSpans);\n }\n }\n\n _cleanupHooks.push(\n client.on('spanStart', startedSpan => {\n // If we already finished the idle span,\n // or if this is the idle span itself being started,\n // or if the started span has already been closed,\n // we don't care about it for activity\n if (_finished || startedSpan === span || !!spanToJSON(startedSpan).timestamp) {\n return;\n }\n\n const allSpans = getSpanDescendants(span);\n\n // If the span that was just started is a child of the idle span, we should track it\n if (allSpans.includes(startedSpan)) {\n _pushActivity(startedSpan.spanContext().spanId);\n }\n }),\n );\n\n _cleanupHooks.push(\n client.on('spanEnd', endedSpan => {\n if (_finished) {\n return;\n }\n\n _popActivity(endedSpan.spanContext().spanId);\n }),\n );\n\n _cleanupHooks.push(\n client.on('idleSpanEnableAutoFinish', spanToAllowAutoFinish => {\n if (spanToAllowAutoFinish === span) {\n _autoFinishAllowed = true;\n _restartIdleTimeout();\n\n if (activities.size) {\n _restartChildSpanTimeout();\n }\n }\n }),\n );\n\n // We only start the initial idle timeout if we are not delaying the auto finish\n if (!options.disableAutoFinish) {\n _restartIdleTimeout();\n }\n\n setTimeout(() => {\n if (!_finished) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });\n _finishReason = FINISH_REASON_FINAL_TIMEOUT;\n span.end();\n }\n }, finalTimeout);\n\n return span;\n}\n\nfunction _startIdleSpan(options: StartSpanOptions): Span {\n const span = startInactiveSpan(options);\n\n _setSpanForScope(getCurrentScope(), span);\n\n DEBUG_BUILD && logger.log('[Tracing] Started span is an idle span');\n\n return span;\n}\n"],"names":[],"mappings":"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"}