UNPKG

@embrace-io/web-sdk

Version:
1 lines 23.6 kB
{"version":3,"file":"DocumentLoadInstrumentation.cjs","names":["EmbraceInstrumentationBase","TRACE_PARENT_HEADER","getPerformanceNavigationEntries","propagation","ROOT_CONTEXT","PerformanceTimingNames","trace","context","ATTR_URL_FULL","KEY_EMB_TYPE","ATTR_USER_AGENT_ORIGINAL","ATTR_HTTP_RESPONSE_STATUS_CODE","ATTR_HTTP_RESPONSE_BODY_SIZE","ATTR_HTTP_RESPONSE_SIZE"],"sources":["../../../../src/instrumentations/document-load/DocumentLoadInstrumentation/DocumentLoadInstrumentation.ts"],"sourcesContent":["/*\n * Adapted from OpenTelemetry document-load instrumentation\n * https://github.com/open-telemetry/opentelemetry-js-contrib/tree/cc7eff47e2e7bad7678241b766753d5bd6dbc85f/packages/instrumentation-document-load\n *\n * Additional PerformanceResourceTiming attributes collected:\n * - entry_type, initiator_type\n * - decoded_body_size, http.response.body.size, http.response.size\n * - delivery_type (Chromium only)\n * - render_blocking_status (Chromium only)\n * - http.response.status_code (no Safari support)\n *\n * Custom diagnostic attributes added to identify resource loading issues:\n * - http.response.cors_opaque - CORS-restricted resource (opaque response)\n * - http.response.cache_revalidated - 304 Not Modified response\n * - http.request.incomplete - Request started but didn't complete (network error, aborted)\n * - http.request.prevented - Request never started (blocked by CSP, browser, extension)\n */\n\nimport type { Span } from '@opentelemetry/api';\nimport { context, propagation, ROOT_CONTEXT, trace } from '@opentelemetry/api';\nimport { TRACE_PARENT_HEADER } from '@opentelemetry/core';\nimport { safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';\nimport type { PerformanceEntries } from '@opentelemetry/sdk-trace-web';\nimport {\n addSpanNetworkEvent,\n addSpanNetworkEvents,\n hasKey,\n PerformanceTimingNames,\n} from '@opentelemetry/sdk-trace-web';\nimport { ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';\nimport {\n ATTR_HTTP_RESPONSE_BODY_SIZE,\n ATTR_HTTP_RESPONSE_SIZE,\n ATTR_URL_FULL,\n ATTR_USER_AGENT_ORIGINAL,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { EMB_TYPES, KEY_EMB_TYPE } from '../../../constants/index.ts';\nimport { EmbraceInstrumentationBase } from '../../EmbraceInstrumentationBase/index.ts';\nimport { AttributeNames } from './enums/AttributeNames.ts';\nimport type {\n DocumentLoadCustomAttributeFunction,\n DocumentLoadInstrumentationConfig,\n ResourceFetchCustomAttributeFunction,\n} from './types.ts';\nimport {\n addSpanPerformancePaintEvents,\n getPerformanceNavigationEntries,\n} from './utils.ts';\n\n/**\n * Adds new browser features not yet in TypeScript's DOM lib (as of Oct 2025):\n * - deliveryType: Chromium only (experimental) https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType\n * - renderBlockingStatus: Chromium only https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/renderBlockingStatus\n */\ntype EmbracePerformanceResourceTiming = PerformanceResourceTiming & {\n deliveryType?: 'cache' | '';\n renderBlockingStatus?: 'blocking' | 'non-blocking';\n};\n\n// PerformanceResourceTiming attribute names\nconst ATTR_HTTP_RESPONSE_DELIVERY_TYPE = 'http.response.delivery_type';\nconst ATTR_HTTP_RESPONSE_DECODED_BODY_SIZE = 'http.response.decoded_body_size';\nconst ATTR_HTTP_REQUEST_INITIATOR_TYPE = 'http.request.initiator_type';\nconst ATTR_HTTP_REQUEST_RENDER_BLOCKING_STATUS =\n 'http.request.render_blocking_status';\n\n// Diagnostic attribute names\nconst ATTR_HTTP_RESPONSE_CORS_OPAQUE = 'http.response.cors_opaque'; // CORS-restricted resource (opaque response)\nconst ATTR_HTTP_RESPONSE_CACHE_REVALIDATED = 'http.response.cache_revalidated'; // 304 Not Modified response\nconst ATTR_HTTP_REQUEST_INCOMPLETE = 'http.request.incomplete'; // Request started but didn't complete\nconst ATTR_HTTP_REQUEST_PREVENTED = 'http.request.prevented'; // Request never started (blocked)\n\nexport class DocumentLoadInstrumentation extends EmbraceInstrumentationBase<DocumentLoadInstrumentationConfig> {\n private readonly _onDocumentLoaded: () => void;\n private _performanceCollected = false;\n\n public constructor({\n diag,\n perf,\n enabled,\n applyCustomAttributesOnSpan,\n ignorePerformancePaintEvents = false,\n ignoreNetworkEvents = false,\n }: DocumentLoadInstrumentationConfig = {}) {\n super({\n instrumentationName: 'DocumentLoadInstrumentation',\n instrumentationVersion: '1.0.0',\n diag,\n perf,\n config: {\n enabled,\n applyCustomAttributesOnSpan,\n ignorePerformancePaintEvents,\n ignoreNetworkEvents,\n },\n });\n\n this._onDocumentLoaded = () => {\n // Timeout needed because performance metrics for loadEnd aren't available until after the load event\n window.setTimeout(() => {\n this._collectPerformance();\n }, 0);\n };\n\n if (this._config.enabled) {\n this.enable();\n }\n }\n\n protected override init() {\n this._diag.debug('Initializing document load instrumentation');\n return undefined;\n }\n\n /**\n * Adds spans for all resources\n * @param rootSpan\n */\n private _addResourcesSpans(rootSpan: Span): void {\n const resources: EmbracePerformanceResourceTiming[] =\n performance.getEntriesByType('resource');\n resources.forEach((resource) => {\n this._initResourceSpan(resource, rootSpan);\n });\n }\n\n /**\n * Collects information about performance and creates appropriate spans\n */\n private _collectPerformance(): void {\n if (this._performanceCollected) {\n return;\n }\n this._performanceCollected = true;\n\n const metaElement = Array.from(document.getElementsByTagName('meta')).find(\n (e) => e.getAttribute('name') === TRACE_PARENT_HEADER,\n );\n const entries = getPerformanceNavigationEntries();\n const traceparent = metaElement?.content || '';\n context.with(propagation.extract(ROOT_CONTEXT, { traceparent }), () => {\n const rootSpan = this._startSpan(\n AttributeNames.DOCUMENT_LOAD,\n PerformanceTimingNames.FETCH_START,\n entries,\n );\n if (!rootSpan) {\n return;\n }\n context.with(trace.setSpan(context.active(), rootSpan), () => {\n const fetchSpan = this._startSpan(\n AttributeNames.DOCUMENT_FETCH,\n PerformanceTimingNames.FETCH_START,\n entries,\n );\n if (fetchSpan) {\n fetchSpan.setAttribute(ATTR_URL_FULL, location.href);\n context.with(trace.setSpan(context.active(), fetchSpan), () => {\n addSpanNetworkEvents(\n fetchSpan,\n entries,\n this.getConfig().ignoreNetworkEvents,\n );\n this._addCustomAttributesOnSpan(\n fetchSpan,\n this.getConfig().applyCustomAttributesOnSpan?.documentFetch,\n );\n this._endSpan(\n fetchSpan,\n PerformanceTimingNames.RESPONSE_END,\n entries,\n );\n });\n }\n });\n\n rootSpan.setAttribute(KEY_EMB_TYPE, EMB_TYPES.DocumentLoad);\n rootSpan.setAttribute(ATTR_URL_FULL, location.href);\n rootSpan.setAttribute(ATTR_USER_AGENT_ORIGINAL, navigator.userAgent);\n\n this._addResourcesSpans(rootSpan);\n\n if (!this.getConfig().ignoreNetworkEvents) {\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.FETCH_START,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.UNLOAD_EVENT_START,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.UNLOAD_EVENT_END,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.DOM_INTERACTIVE,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.DOM_CONTENT_LOADED_EVENT_START,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.DOM_CONTENT_LOADED_EVENT_END,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.DOM_COMPLETE,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.LOAD_EVENT_START,\n entries,\n );\n addSpanNetworkEvent(\n rootSpan,\n PerformanceTimingNames.LOAD_EVENT_END,\n entries,\n );\n }\n\n if (!this.getConfig().ignorePerformancePaintEvents) {\n addSpanPerformancePaintEvents(rootSpan, this.perf);\n }\n\n this._addCustomAttributesOnSpan(\n rootSpan,\n this.getConfig().applyCustomAttributesOnSpan?.documentLoad,\n );\n this._endSpan(rootSpan, PerformanceTimingNames.LOAD_EVENT_END, entries);\n });\n }\n\n /**\n * Helper function for ending a span\n * @param span\n * @param performanceName name of performance entry for end time\n * @param entries\n */\n private _endSpan(\n span: Span | undefined,\n performanceName: string,\n entries: PerformanceEntries,\n ) {\n // Span can be undefined when entries are missing the required performance timing - no span will be created\n if (span) {\n if (\n hasKey(entries, performanceName) &&\n typeof entries[performanceName] === 'number'\n ) {\n span.end(this.perf.epochMillisFromOrigin(entries[performanceName]));\n } else {\n span.end();\n }\n }\n }\n\n /**\n * Creates and ends a span with network information about a resource added as timed events\n * @param resource\n * @param parentSpan\n */\n private _initResourceSpan(\n resource: EmbracePerformanceResourceTiming,\n parentSpan: Span,\n ) {\n const span = this._startSpan(\n AttributeNames.RESOURCE_FETCH,\n PerformanceTimingNames.FETCH_START,\n resource,\n parentSpan,\n );\n if (!span) {\n return;\n }\n\n span.setAttribute(KEY_EMB_TYPE, EMB_TYPES.ResourceFetch);\n span.setAttribute(ATTR_URL_FULL, resource.name);\n addSpanNetworkEvents(span, resource, this.getConfig().ignoreNetworkEvents);\n\n if (resource.deliveryType) {\n span.setAttribute(\n ATTR_HTTP_RESPONSE_DELIVERY_TYPE,\n resource.deliveryType,\n );\n }\n\n if (resource.initiatorType) {\n span.setAttribute(\n ATTR_HTTP_REQUEST_INITIATOR_TYPE,\n resource.initiatorType,\n );\n }\n\n if (resource.renderBlockingStatus) {\n span.setAttribute(\n ATTR_HTTP_REQUEST_RENDER_BLOCKING_STATUS,\n resource.renderBlockingStatus,\n );\n }\n\n if (resource.responseStatus) {\n span.setAttribute(\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n resource.responseStatus,\n );\n }\n\n // Validate size fields exist and aren't negative\n if (\n typeof resource.encodedBodySize === 'number' &&\n resource.encodedBodySize >= 0\n ) {\n span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, resource.encodedBodySize);\n }\n\n if (\n typeof resource.transferSize === 'number' &&\n resource.transferSize >= 0\n ) {\n span.setAttribute(ATTR_HTTP_RESPONSE_SIZE, resource.transferSize);\n }\n\n if (\n typeof resource.decodedBodySize === 'number' &&\n resource.decodedBodySize >= 0\n ) {\n span.setAttribute(\n ATTR_HTTP_RESPONSE_DECODED_BODY_SIZE,\n resource.decodedBodySize,\n );\n }\n\n this._addResourceDiagnosticAttributes(span, resource);\n\n this._addCustomAttributesOnResourceSpan(\n span,\n resource,\n this.getConfig().applyCustomAttributesOnSpan?.resourceFetch,\n );\n this._endSpan(span, PerformanceTimingNames.RESPONSE_END, resource);\n }\n\n /**\n * Helper function for starting a span\n * @param spanName name of span\n * @param performanceName name of performance entry for time start\n * @param entries\n * @param parentSpan\n */\n private _startSpan(\n spanName: string,\n performanceName: string,\n entries: PerformanceEntries,\n parentSpan?: Span,\n ): Span | undefined {\n if (\n hasKey(entries, performanceName) &&\n typeof entries[performanceName] === 'number'\n ) {\n const span = this.tracer.startSpan(\n spanName,\n {\n startTime: this.perf.epochMillisFromOrigin(entries[performanceName]),\n },\n parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined,\n );\n return span;\n }\n return undefined;\n }\n\n /**\n * Executes callback {_onDocumentLoaded} when the page is loaded\n */\n private _waitForPageLoad() {\n if (window.document.readyState === 'complete') {\n this._onDocumentLoaded();\n } else {\n window.addEventListener('load', this._onDocumentLoaded);\n }\n }\n\n /**\n * Adds custom attributes to span if configured\n * Used for both documentFetch and documentLoad spans\n */\n private _addCustomAttributesOnSpan(\n span: Span,\n applyCustomAttributesOnSpan:\n | DocumentLoadCustomAttributeFunction\n | undefined,\n ) {\n if (applyCustomAttributesOnSpan) {\n safeExecuteInTheMiddle(\n () => {\n applyCustomAttributesOnSpan(span);\n },\n (error) => {\n if (!error) {\n return;\n }\n\n this._diag.error('addCustomAttributesOnSpan', error);\n },\n true,\n );\n }\n }\n\n /**\n * Adds custom attributes to resource span if configured\n */\n private _addCustomAttributesOnResourceSpan(\n span: Span,\n resource: EmbracePerformanceResourceTiming,\n applyCustomAttributesOnSpan:\n | ResourceFetchCustomAttributeFunction\n | undefined,\n ) {\n if (applyCustomAttributesOnSpan) {\n safeExecuteInTheMiddle(\n () => {\n applyCustomAttributesOnSpan(span, resource);\n },\n (error) => {\n if (!error) {\n return;\n }\n\n this._diag.error('addCustomAttributesOnResourceSpan', error);\n },\n true,\n );\n }\n }\n\n private _hasNoSizeData(resource: EmbracePerformanceResourceTiming): boolean {\n const transferSize =\n typeof resource.transferSize === 'number' ? resource.transferSize : 0;\n const decodedBodySize =\n typeof resource.decodedBodySize === 'number'\n ? resource.decodedBodySize\n : 0;\n const encodedBodySize =\n typeof resource.encodedBodySize === 'number'\n ? resource.encodedBodySize\n : 0;\n\n return transferSize === 0 && decodedBodySize === 0 && encodedBodySize === 0;\n }\n\n private _hasTimingData(resource: EmbracePerformanceResourceTiming): boolean {\n const fetchStart =\n typeof resource.fetchStart === 'number' ? resource.fetchStart : 0;\n const responseEnd =\n typeof resource.responseEnd === 'number' ? resource.responseEnd : 0;\n\n return fetchStart > 0 && responseEnd > 0;\n }\n\n private _isCorsRestricted(\n resource: EmbracePerformanceResourceTiming,\n ): boolean {\n return this._hasNoSizeData(resource) && this._hasTimingData(resource);\n }\n\n private _isFetchIncomplete(\n resource: EmbracePerformanceResourceTiming,\n ): boolean {\n const fetchStart =\n typeof resource.fetchStart === 'number' ? resource.fetchStart : 0;\n const responseEnd =\n typeof resource.responseEnd === 'number' ? resource.responseEnd : 0;\n\n return this._hasNoSizeData(resource) && fetchStart > 0 && responseEnd === 0;\n }\n\n private _isFetchPrevented(\n resource: EmbracePerformanceResourceTiming,\n ): boolean {\n const fetchStart =\n typeof resource.fetchStart === 'number' ? resource.fetchStart : 0;\n\n return this._hasNoSizeData(resource) && fetchStart === 0;\n }\n\n /**\n * Detect cache validation (304 Not Modified responses)\n *\n * 304 responses show transferSize of ~300 bytes (headers only, no body).\n * Use deliveryType to distinguish from cache hits: 'cache' = no network, otherwise = 304.\n *\n * Spec: https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-transfersize\n */\n private _isCacheValidated(\n resource: EmbracePerformanceResourceTiming,\n ): boolean {\n const transferSize =\n typeof resource.transferSize === 'number' ? resource.transferSize : 0;\n const deliveryType =\n typeof resource.deliveryType === 'string' ? resource.deliveryType : '';\n\n return transferSize === 300 && deliveryType !== 'cache';\n }\n\n /**\n * Add diagnostic attributes to identify resource loading issues\n *\n * Diagnostic attributes help identify why resources may have incomplete timing data:\n * - CORS restrictions (opaque responses without Timing-Allow-Origin header)\n * - Cache revalidation (304 Not Modified responses)\n * - Request incomplete (started but didn't complete - network error, aborted)\n * - Request prevented (never started - blocked by CSP, browser, extension)\n */\n private _addResourceDiagnosticAttributes(\n span: Span,\n resource: EmbracePerformanceResourceTiming,\n ): void {\n if (this._isCorsRestricted(resource)) {\n span.setAttribute(ATTR_HTTP_RESPONSE_CORS_OPAQUE, true);\n } else if (this._isFetchIncomplete(resource)) {\n span.setAttribute(ATTR_HTTP_REQUEST_INCOMPLETE, true);\n } else if (this._isFetchPrevented(resource)) {\n span.setAttribute(ATTR_HTTP_REQUEST_PREVENTED, true);\n }\n\n if (this._isCacheValidated(resource)) {\n span.setAttribute(ATTR_HTTP_RESPONSE_CACHE_REVALIDATED, true);\n }\n }\n\n public override onEnable(): void {\n window.removeEventListener('load', this._onDocumentLoaded);\n this._waitForPageLoad();\n }\n\n public override onDisable(): void {\n window.removeEventListener('load', this._onDocumentLoaded);\n }\n}\n"],"mappings":"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"}