diff --git a/.github/actions/install-playwright/action.yml b/.github/actions/install-playwright/action.yml index 30b33b91..07a40ccf 100644 --- a/.github/actions/install-playwright/action.yml +++ b/.github/actions/install-playwright/action.yml @@ -3,6 +3,11 @@ description: 'Install Playwright browser binaries and OS dependencies' runs: using: 'composite' steps: + - name: Get Node.js version + id: node-version + shell: bash + run: echo "node=$(node -v)" >> $GITHUB_ENV + - name: Get installed Playwright version id: playwright-version shell: bash @@ -20,7 +25,7 @@ runs: id: playwright-cache with: path: ${{ env.PLAYWRIGHT_CACHE_PATH }} - key: '${{ runner.os }}-playwright-cache-${{ env.PLAYWRIGHT_VERSION }}-splunk-otel-js-web-artifacts' + key: '${{ runner.os }}-node-${{ steps.node-version.outputs.node }}-playwright-cache-${{ env.PLAYWRIGHT_VERSION }}-splunk-otel-js-web-artifacts' - name: Install Playwright browser binaries if: steps.playwright-cache.outputs.cache-hit != 'true' diff --git a/CHANGELOG.md b/CHANGELOG.md index bf319c2d..e78839da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,28 @@ If the version of Open Telemetry is unspecified for a version, then it is the same as in the previous release. +## 0.20.0-beta.4 + +* `@splunk/otel-web` + * feat: add `http.status_code` to all resources spans + * Resource spans now contain status code. The status code is set always when browser reports it. + Browser does not report status code for [cross-origin resources](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus#value) that do not have [`crossorigin` attribute set](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin). + in such cases, status code is omitted. ([#936](https://github.com/signalfx/splunk-otel-js-web/pull/936)) + * fix: do not extend session from discarded session replay spans + * Session is not extended when span is discarded by session replay. Please see detailed info in [PR description](https://github.com/signalfx/splunk-otel-js-web/pull/939). + * There is a possibly breaking change as the `Splunk.getSessionId()` can return `undefined` when previous session + expired and there are no new spans. The API already was typed as returning `string | undefined` hence not + considered as a breaking change. See PR for explanation. ([#939](https://github.com/signalfx/splunk-otel-js-web/pull/939)) + +## 0.20.0-beta.3 + +* `@splunk/otel-web` + * fix: rename `http.response.status_code` to `http.status_code` in documentFetch span ([#934](https://github.com/signalfx/splunk-otel-js-web/pull/934)) + ## 0.20.0-beta.2 * `@splunk/otel-web` - * fix: add 'http.response.status_code' to documentFetch span ([#928](https://github.com/signalfx/splunk-otel-js-web/pull/928)) + * fix: add `http.response.status_code` to documentFetch span ([#928](https://github.com/signalfx/splunk-otel-js-web/pull/928)) * `root - internal changes` * chore(internal): deps bump ([#890](https://github.com/signalfx/splunk-otel-js-web/pull/890), [#915](https://github.com/signalfx/splunk-otel-js-web/pull/915), [#921](https://github.com/signalfx/splunk-otel-js-web/pull/921), [#911](https://github.com/signalfx/splunk-otel-js-web/pull/911)) * chore(internal): update license headers to reflect new year ([#920](https://github.com/signalfx/splunk-otel-js-web/pull/920)) diff --git a/package-lock.json b/package-lock.json index af37f11c..4401fc9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splunk/otel-web-dev-root", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@splunk/otel-web-dev-root", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "workspaces": [ "packages/web", "packages/session-recorder", @@ -4615,13 +4615,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", - "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.0.tgz", + "integrity": "sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.48.2" + "playwright": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -15497,13 +15497,13 @@ } }, "node_modules/playwright": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", - "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.0.tgz", + "integrity": "sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.48.2" + "playwright-core": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -15516,9 +15516,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", - "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.0.tgz", + "integrity": "sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -18930,7 +18930,7 @@ }, "packages/integration-tests": { "name": "@splunk/otel-js-web-integration-tests", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "license": "Apache-2.0", "dependencies": { "@fastify/view": "^10.0.1", @@ -18942,7 +18942,7 @@ }, "devDependencies": { "@fastify/static": "^8.0.2", - "@playwright/test": "^1.48.2", + "@playwright/test": "^1.50.0", "@types/ejs": "^3.1.5", "@types/express": "^5.0.0", "@types/node": "^22.9.0", @@ -18952,7 +18952,7 @@ }, "packages/session-recorder": { "name": "@splunk/otel-web-session-recorder", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "~7.24.7", @@ -18995,7 +18995,7 @@ }, "packages/web": { "name": "@splunk/otel-web", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.24.7", diff --git a/package.json b/package.json index b0dd2524..1e1bd014 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@splunk/otel-web-dev-root", "private": true, - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "--workspaces": "Hardcoded so npm runs workspaces commands in order", "workspaces": [ "packages/web", diff --git a/packages/integration-tests/package-lock.json b/packages/integration-tests/package-lock.json index 9259711d..75f4a711 100644 --- a/packages/integration-tests/package-lock.json +++ b/packages/integration-tests/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splunk/otel-js-web-integration-tests", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@splunk/otel-js-web-integration-tests", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "license": "Apache-2.0", "dependencies": { "tsx": "^4.19.2" diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index 6d978e88..47a55a34 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -1,7 +1,7 @@ { "name": "@splunk/otel-js-web-integration-tests", "private": true, - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "repository": "github:signalfx/splunk-otel-js-browser", "scripts": { "server": "run-p server:*", @@ -15,7 +15,7 @@ "license": "Apache-2.0", "devDependencies": { "@fastify/static": "^8.0.2", - "@playwright/test": "^1.48.2", + "@playwright/test": "^1.50.0", "@types/ejs": "^3.1.5", "@types/express": "^5.0.0", "@types/node": "^22.9.0", diff --git a/packages/integration-tests/src/tests/docload/docload.spec.ts b/packages/integration-tests/src/tests/docload/docload.spec.ts index f8f5f0ad..9e044ca2 100644 --- a/packages/integration-tests/src/tests/docload/docload.spec.ts +++ b/packages/integration-tests/src/tests/docload/docload.spec.ts @@ -80,10 +80,18 @@ test.describe('docload', () => { expect(scriptFetchSpans[0].traceId).toBe(docLoadSpans[0].traceId) expect(scriptFetchSpans[0].parentId).toBe(docLoadSpans[0].id) expect(scriptFetchSpans[0].tags['component']).toBe('document-load') + if (browserName !== 'webkit') { + // Webkit does not support https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus + expect(parseInt(scriptFetchSpans[0].tags['http.status_code'] as string)).toBe(200) + } expect(brokenImageFetchSpans.length).toBeGreaterThanOrEqual(1) expect(brokenImageFetchSpans[0].traceId).toBe(docLoadSpans[0].traceId) expect(brokenImageFetchSpans[0].parentId).toBe(docLoadSpans[0].id) + if (browserName !== 'webkit') { + // Webkit does not support https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus + expect(parseInt(brokenImageFetchSpans[0].tags['http.status_code'] as string)).toBe(404) + } expect(docFetchSpans[0].tags['component']).toBe('document-load') expect(docLoadSpans[0].tags['location.href']).toBe('http://localhost:3000/docload/docload.ejs') @@ -98,7 +106,7 @@ test.describe('docload', () => { expect(docFetchSpans[0].tags['link.spanId']).toBeDefined() if (browserName !== 'webkit') { // Webkit does not support https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus - expect(parseInt(docFetchSpans[0].tags['http.response.status_code'] as string)).toBe(200) + expect(parseInt(docFetchSpans[0].tags['http.status_code'] as string)).toBe(200) } expect(parseInt(scriptFetchSpans[0].tags['http.response_content_length'] as string)).toBeGreaterThan(0) diff --git a/packages/integration-tests/src/version.ts b/packages/integration-tests/src/version.ts index 25f4b97c..90c2e1c1 100644 --- a/packages/integration-tests/src/version.ts +++ b/packages/integration-tests/src/version.ts @@ -17,4 +17,4 @@ */ // this is an autogenerated file, see scripts/version-update.js -export const VERSION = '0.20.0-beta.2' +export const VERSION = '0.20.0-beta.4' diff --git a/packages/session-recorder/package.json b/packages/session-recorder/package.json index fb0a7a69..e6267683 100644 --- a/packages/session-recorder/package.json +++ b/packages/session-recorder/package.json @@ -1,6 +1,6 @@ { "name": "@splunk/otel-web-session-recorder", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "description": "Splunk distribution of rrweb for recording session", "repository": "github:signalfx/splunk-otel-js-browser", "scripts": { diff --git a/packages/session-recorder/src/index.ts b/packages/session-recorder/src/index.ts index 941774d2..e6696b81 100644 --- a/packages/session-recorder/src/index.ts +++ b/packages/session-recorder/src/index.ts @@ -194,9 +194,7 @@ const SplunkRumRecorder = { return } - if (SplunkRum._internalOnExternalSpanCreated) { - SplunkRum._internalOnExternalSpanCreated() - } + let isExtended = false // Safeguards from our ingest getting DDOSed: // 1. A session can send up to 4 hours of data @@ -206,6 +204,13 @@ const SplunkRumRecorder = { return } + // We need to call it here before another getSessionID call. This will create a new session + // if the previous one was expired + if (SplunkRum._internalOnExternalSpanCreated) { + SplunkRum._internalOnExternalSpanCreated() + isExtended = true + } + lastKnownSession = SplunkRum.getSessionId() sessionStartTime = Date.now() // reset counters @@ -218,6 +223,12 @@ const SplunkRumRecorder = { return } + if (!isExtended) { + if (SplunkRum._internalOnExternalSpanCreated) { + SplunkRum._internalOnExternalSpanCreated() + } + } + const time = event.timestamp const eventI = eventCounter eventCounter += 1 diff --git a/packages/session-recorder/src/version.ts b/packages/session-recorder/src/version.ts index 25f4b97c..90c2e1c1 100644 --- a/packages/session-recorder/src/version.ts +++ b/packages/session-recorder/src/version.ts @@ -17,4 +17,4 @@ */ // this is an autogenerated file, see scripts/version-update.js -export const VERSION = '0.20.0-beta.2' +export const VERSION = '0.20.0-beta.4' diff --git a/packages/web/package.json b/packages/web/package.json index b502466a..6c3e099a 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,6 +1,6 @@ { "name": "@splunk/otel-web", - "version": "0.20.0-beta.2", + "version": "0.20.0-beta.4", "description": "Splunk distribution of Open Telemetry for browser environment.", "repository": "github:signalfx/splunk-otel-js-browser", "scripts": { diff --git a/packages/web/src/SessionBasedSampler.ts b/packages/web/src/SessionBasedSampler.ts index 3be024c7..0e0db502 100644 --- a/packages/web/src/SessionBasedSampler.ts +++ b/packages/web/src/SessionBasedSampler.ts @@ -52,11 +52,14 @@ export class SessionBasedSampler implements Sampler { protected _upperBound: number - constructor({ - ratio = 1, - sampled = new AlwaysOnSampler(), - notSampled = new AlwaysOffSampler(), - }: SessionBasedSamplerConfig = {}) { + constructor( + { + ratio = 1, + sampled = new AlwaysOnSampler(), + notSampled = new AlwaysOffSampler(), + }: SessionBasedSamplerConfig = {}, + private readonly useLocalStorageForSessionMetadata = false, + ) { this._ratio = this._normalize(ratio) this._upperBound = Math.floor(this._ratio * 0xffffffff) @@ -75,7 +78,7 @@ export class SessionBasedSampler implements Sampler { // Implementation based on @opentelemetry/core TraceIdRatioBasedSampler // but replacing deciding based on traceId with sessionId // (not extended from due to private methods) - const currentSession = getRumSessionId() + const currentSession = getRumSessionId({ useLocalStorage: this.useLocalStorageForSessionMetadata }) if (this._currentSession !== currentSession) { this._currentSessionSampled = this._accumulate(currentSession) < this._upperBound this._currentSession = currentSession diff --git a/packages/web/src/SplunkDocumentLoadInstrumentation.ts b/packages/web/src/SplunkDocumentLoadInstrumentation.ts index ab6efaa8..c22e0cc2 100644 --- a/packages/web/src/SplunkDocumentLoadInstrumentation.ts +++ b/packages/web/src/SplunkDocumentLoadInstrumentation.ts @@ -17,13 +17,18 @@ */ import { InstrumentationConfig } from '@opentelemetry/instrumentation' -import { AttributeNames, DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load' +import { + AttributeNames, + DocumentLoadInstrumentation, + DocumentLoadInstrumentationConfig, + ResourceFetchCustomAttributeFunction, +} from '@opentelemetry/instrumentation-document-load' import * as api from '@opentelemetry/api' import { captureTraceParentFromPerformanceEntries } from './servertiming' -import { PerformanceEntries } from '@opentelemetry/sdk-trace-web' +import { addSpanNetworkEvents, PerformanceEntries, PerformanceTimingNames as PTN } from '@opentelemetry/sdk-trace-web' import { Span } from '@opentelemetry/sdk-trace-base' import { isUrlIgnored } from '@opentelemetry/core' -import { SemanticAttributes } from '@opentelemetry/semantic-conventions' +import { SemanticAttributes, SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions' export interface SplunkDocLoadInstrumentationConfig extends InstrumentationConfig { ignoreUrls?: (string | RegExp)[] @@ -46,8 +51,20 @@ type PerformanceEntriesWithServerTiming = PerformanceEntries & { } type ExposedSuper = { + _addCustomAttributesOnResourceSpan( + span: Span, + resource: PerformanceResourceTiming, + applyCustomAttributesOnSpan: ResourceFetchCustomAttributeFunction | undefined, + ) _endSpan(span: api.Span | undefined, performanceName: string, entries: PerformanceEntries): void _initResourceSpan(resource: PerformanceResourceTiming, parentSpan: api.Span): void + _startSpan( + spanName: string, + performanceName: string, + entries: PerformanceEntries, + parentSpan?: api.Span, + ): Span | undefined + getConfig(): DocumentLoadInstrumentationConfig } export class SplunkDocumentLoadInstrumentation extends DocumentLoadInstrumentation { @@ -76,8 +93,12 @@ export class SplunkDocumentLoadInstrumentation extends DocumentLoadInstrumentati ;(entries as PerformanceEntriesWithServerTiming).serverTiming = navEntries[0].serverTiming } - if (navEntries[0]?.responseStatus) { - span.setAttribute('http.response.status_code', navEntries[0].responseStatus) + if ( + navEntries[0] && + typeof navEntries[0].responseStatus === 'number' && + navEntries[0].responseStatus > 0 + ) { + span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, navEntries[0].responseStatus) } } @@ -92,7 +113,6 @@ export class SplunkDocumentLoadInstrumentation extends DocumentLoadInstrumentati return _superEndSpan(span, performanceName, entries) } - const _superInitResourceSpan: ExposedSuper['_initResourceSpan'] = exposedSuper._initResourceSpan.bind(this) exposedSuper._initResourceSpan = (resource, parentSpan) => { if ( excludedInitiatorTypes.indexOf(resource.initiatorType) !== -1 || @@ -101,7 +121,23 @@ export class SplunkDocumentLoadInstrumentation extends DocumentLoadInstrumentati return } - _superInitResourceSpan(resource, parentSpan) + const span = exposedSuper._startSpan(AttributeNames.RESOURCE_FETCH, PTN.FETCH_START, resource, parentSpan) + if (span) { + span.setAttribute(SEMATTRS_HTTP_URL, resource.name) + if (!exposedSuper.getConfig().ignoreNetworkEvents) { + addSpanNetworkEvents(span, resource) + if (typeof resource.responseStatus === 'number' && resource.responseStatus > 0) { + span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, resource.responseStatus) + } + } + + exposedSuper._addCustomAttributesOnResourceSpan( + span, + resource, + exposedSuper.getConfig().applyCustomAttributesOnSpan?.resourceFetch, + ) + exposedSuper._endSpan(span, PTN.RESPONSE_END, resource) + } } } } diff --git a/packages/web/src/SplunkSpanAttributesProcessor.ts b/packages/web/src/SplunkSpanAttributesProcessor.ts index 5498a213..09b389de 100644 --- a/packages/web/src/SplunkSpanAttributesProcessor.ts +++ b/packages/web/src/SplunkSpanAttributesProcessor.ts @@ -23,7 +23,10 @@ import { getRumSessionId } from './session' export class SplunkSpanAttributesProcessor implements SpanProcessor { private readonly _globalAttributes: Attributes - constructor(globalAttributes: Attributes) { + constructor( + globalAttributes: Attributes, + private useLocalStorageForSessionMetadata: boolean, + ) { this._globalAttributes = globalAttributes ?? {} } @@ -42,7 +45,10 @@ export class SplunkSpanAttributesProcessor implements SpanProcessor { onStart(span: Span): void { span.setAttribute('location.href', location.href) span.setAttributes(this._globalAttributes) - span.setAttribute('splunk.rumSessionId', getRumSessionId()) + span.setAttribute( + 'splunk.rumSessionId', + getRumSessionId({ useLocalStorage: this.useLocalStorageForSessionMetadata }), + ) span.setAttribute('browser.instance.visibility_state', document.visibilityState) } diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts index c37e0754..ab75406c 100644 --- a/packages/web/src/index.ts +++ b/packages/web/src/index.ts @@ -392,13 +392,16 @@ export const SplunkRum: SplunkOtelWebType = { return null }).filter((a): a is Exclude => Boolean(a)) - this.attributesProcessor = new SplunkSpanAttributesProcessor({ - ...(deploymentEnvironment - ? { 'environment': deploymentEnvironment, 'deployment.environment': deploymentEnvironment } - : {}), - ...(version ? { 'app.version': version } : {}), - ...(processedOptions.globalAttributes || {}), - }) + this.attributesProcessor = new SplunkSpanAttributesProcessor( + { + ...(deploymentEnvironment + ? { 'environment': deploymentEnvironment, 'deployment.environment': deploymentEnvironment } + : {}), + ...(version ? { 'app.version': version } : {}), + ...(processedOptions.globalAttributes || {}), + }, + this._processedOptions.persistence === 'localStorage', + ) provider.addSpanProcessor(this.attributesProcessor) if (processedOptions.beaconEndpoint) { @@ -517,7 +520,11 @@ export const SplunkRum: SplunkOtelWebType = { }, getSessionId() { - return getRumSessionId() + if (!inited) { + return undefined + } + + return getRumSessionId({ useLocalStorage: this._processedOptions.persistence === 'localStorage' }) }, _experimental_getSessionId() { return this.getSessionId() diff --git a/packages/web/src/session/session.ts b/packages/web/src/session/session.ts index e19be374..20726066 100644 --- a/packages/web/src/session/session.ts +++ b/packages/web/src/session/session.ts @@ -45,7 +45,6 @@ import { context } from '@opentelemetry/api' with setting cookies, checking for inactivity, etc. */ -let rumSessionId: SessionId | undefined let recentActivity = false let cookieDomain: string let eventTarget: InternalEventTarget | undefined @@ -93,8 +92,7 @@ export function updateSessionStatus({ } } - rumSessionId = sessionState.id - eventTarget?.emit('session-changed', { sessionId: rumSessionId }) + eventTarget?.emit('session-changed', { sessionId: sessionState.id }) if (recentActivity || forceActivity) { sessionState.expiresAt = Date.now() + SESSION_INACTIVITY_TIMEOUT_MS @@ -157,9 +155,7 @@ export function initSessionTracking( if (hasNativeSessionId()) { // short-circuit and bail out - don't create cookie, watch for inactivity, or anything return { - deinit: () => { - rumSessionId = undefined - }, + deinit: () => {}, } } @@ -167,7 +163,6 @@ export function initSessionTracking( cookieDomain = domain } - rumSessionId = instanceId recentActivity = true // document loaded implies activity eventTarget = newEventTarget @@ -179,16 +174,15 @@ export function initSessionTracking( return { deinit: () => { ACTIVITY_EVENTS.forEach((type) => document.removeEventListener(type, markActivity)) - rumSessionId = undefined eventTarget = undefined }, } } -export function getRumSessionId(): SessionId | undefined { +export function getRumSessionId({ useLocalStorage }: { useLocalStorage: boolean }): SessionId | undefined { if (hasNativeSessionId()) { return window['SplunkRumNative'].getNativeSessionId() } - return rumSessionId + return getCurrentSessionState({ useLocalStorage, forceStoreRead: true })?.id } diff --git a/packages/web/src/version.ts b/packages/web/src/version.ts index 25f4b97c..90c2e1c1 100644 --- a/packages/web/src/version.ts +++ b/packages/web/src/version.ts @@ -17,4 +17,4 @@ */ // this is an autogenerated file, see scripts/version-update.js -export const VERSION = '0.20.0-beta.2' +export const VERSION = '0.20.0-beta.4' diff --git a/packages/web/test/SplunkSpanAttributesProcessor.test.ts b/packages/web/test/SplunkSpanAttributesProcessor.test.ts index 09e75df1..930785a7 100644 --- a/packages/web/test/SplunkSpanAttributesProcessor.test.ts +++ b/packages/web/test/SplunkSpanAttributesProcessor.test.ts @@ -22,9 +22,12 @@ import { SplunkSpanAttributesProcessor } from '../src/SplunkSpanAttributesProces describe('SplunkSpanAttributesProcessor', () => { describe('setting global attribute', () => { it('should set attributes via constructor', () => { - const processor = new SplunkSpanAttributesProcessor({ - key1: 'value1', - }) + const processor = new SplunkSpanAttributesProcessor( + { + key1: 'value1', + }, + false, + ) expect(processor.getGlobalAttributes()).to.deep.eq({ key1: 'value1', @@ -32,10 +35,13 @@ describe('SplunkSpanAttributesProcessor', () => { }) it('should patch attributes via .setGlobalAttributes()', () => { - const processor = new SplunkSpanAttributesProcessor({ - key1: 'value1', - key2: 'value2', - }) + const processor = new SplunkSpanAttributesProcessor( + { + key1: 'value1', + key2: 'value2', + }, + false, + ) processor.setGlobalAttributes({ key2: 'value2-updaged', diff --git a/packages/web/test/session.test.ts b/packages/web/test/session.test.ts index bf47678c..e5651062 100644 --- a/packages/web/test/session.test.ts +++ b/packages/web/test/session.test.ts @@ -38,11 +38,11 @@ describe('Session tracking', () => { // the init tests have possibly already started the setInterval for updateSessionStatus. Try to accomodate this. const provider = new SplunkWebTracerProvider() const trackingHandle = initSessionTracking(provider, '1234', new InternalEventTarget()) - const firstSessionId = getRumSessionId() + const firstSessionId = getRumSessionId({ useLocalStorage: false }) assert.strictEqual(firstSessionId.length, 32) // no marked activity, should keep same state updateSessionStatus({ forceStore: false, useLocalStorage: false }) - assert.strictEqual(firstSessionId, getRumSessionId()) + assert.strictEqual(firstSessionId, getRumSessionId({ useLocalStorage: false })) // set cookie to expire in 2 seconds, mark activity, and then updateSessionStatus. // Wait 4 seconds and cookie should still be there (having been renewed) const cookieValue = encodeURIComponent( @@ -58,7 +58,7 @@ describe('Session tracking', () => { setTimeout(() => { // because of activity, same session should be there assert.ok(document.cookie.includes(SESSION_STORAGE_KEY)) - assert.strictEqual(firstSessionId, getRumSessionId()) + assert.strictEqual(firstSessionId, getRumSessionId({ useLocalStorage: false })) // Finally, set a fake cookie with startTime 5 hours ago, update status, and find a new cookie with a new session ID // after max age code does its thing @@ -74,7 +74,7 @@ describe('Session tracking', () => { updateSessionStatus({ forceStore: true, useLocalStorage: false }) assert.ok(document.cookie.includes(SESSION_STORAGE_KEY)) - const newSessionId = getRumSessionId() + const newSessionId = getRumSessionId({ useLocalStorage: false }) assert.strictEqual(newSessionId.length, 32) assert.ok(firstSessionId !== newSessionId) @@ -90,7 +90,7 @@ describe('Session tracking', () => { function subject(allSpansAreActivity = false) { const provider = new SplunkWebTracerProvider() - const firstSessionId = getRumSessionId() + const firstSessionId = getRumSessionId({ useLocalStorage: false }) initSessionTracking(provider, firstSessionId, new InternalEventTarget(), undefined, allSpansAreActivity) provider.getTracer('tracer').startSpan('any-span').end() @@ -138,9 +138,9 @@ describe('Session tracking - localStorage', () => { useLocalStorage, ) - const firstSessionId = getRumSessionId() + const firstSessionId = getRumSessionId({ useLocalStorage }) updateSessionStatus({ forceStore: true, useLocalStorage }) - assert.strictEqual(firstSessionId, getRumSessionId()) + assert.strictEqual(firstSessionId, getRumSessionId({ useLocalStorage })) trackingHandle.deinit() })