diff --git a/packages/logs/src/domain/assembly.spec.ts b/packages/logs/src/domain/assembly.spec.ts index 970dd3ebc9..df4772f493 100644 --- a/packages/logs/src/domain/assembly.spec.ts +++ b/packages/logs/src/domain/assembly.spec.ts @@ -41,11 +41,12 @@ const COMMON_CONTEXT_WITH_USER: CommonContext = { describe('startLogsAssembly', () => { const sessionManager: LogsSessionManager = { - findTrackedSession: () => (sessionIsTracked ? { id: SESSION_ID } : undefined), + findTrackedSession: () => (sessionIsTracked ? { id: SESSION_ID, isActiveAt: () => sessionIsActive } : undefined), expireObservable: new Observable(), } let beforeSend: (event: LogsEvent) => void | boolean + let sessionIsActive: boolean let sessionIsTracked: boolean let lifeCycle: LifeCycle let serverLogs: Array = [] @@ -53,6 +54,7 @@ describe('startLogsAssembly', () => { beforeEach(() => { sessionIsTracked = true + sessionIsActive = true lifeCycle = new LifeCycle() lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (serverRumEvent) => serverLogs.push(serverRumEvent)) const configuration = { @@ -96,31 +98,53 @@ describe('startLogsAssembly', () => { expect(serverLogs.length).toEqual(0) }) - it('should not send if session is not tracked', () => { - sessionIsTracked = false - lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { - rawLogsEvent: DEFAULT_MESSAGE, + describe('event generation condition', () => { + it('should not send if session is not tracked', () => { + sessionIsTracked = false + lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { + rawLogsEvent: DEFAULT_MESSAGE, + }) + expect(serverLogs.length).toEqual(0) }) - expect(serverLogs.length).toEqual(0) - }) - it('should enable/disable the sending when the tracking type change', () => { - lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { - rawLogsEvent: DEFAULT_MESSAGE, + it('should send log with session id if session is active', () => { + sessionIsTracked = true + sessionIsActive = true + lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { + rawLogsEvent: DEFAULT_MESSAGE, + }) + expect(serverLogs.length).toEqual(1) + expect(serverLogs[0].session_id).toEqual(SESSION_ID) }) - expect(serverLogs.length).toEqual(1) - sessionIsTracked = false - lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { - rawLogsEvent: DEFAULT_MESSAGE, + it('should send log without session id if session has expired', () => { + sessionIsTracked = true + sessionIsActive = false + lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { + rawLogsEvent: DEFAULT_MESSAGE, + }) + expect(serverLogs.length).toEqual(1) + expect(serverLogs[0].session_id).toBeUndefined() }) - expect(serverLogs.length).toEqual(1) - sessionIsTracked = true - lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { - rawLogsEvent: DEFAULT_MESSAGE, + it('should enable/disable the sending when the tracking type change', () => { + lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { + rawLogsEvent: DEFAULT_MESSAGE, + }) + expect(serverLogs.length).toEqual(1) + + sessionIsTracked = false + lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { + rawLogsEvent: DEFAULT_MESSAGE, + }) + expect(serverLogs.length).toEqual(1) + + sessionIsTracked = true + lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { + rawLogsEvent: DEFAULT_MESSAGE, + }) + expect(serverLogs.length).toEqual(2) }) - expect(serverLogs.length).toEqual(2) }) describe('contexts inclusion', () => { @@ -283,7 +307,7 @@ describe('startLogsAssembly', () => { describe('user management', () => { const sessionManager: LogsSessionManager = { - findTrackedSession: () => (sessionIsTracked ? { id: SESSION_ID } : undefined), + findTrackedSession: () => (sessionIsTracked ? { id: SESSION_ID, isActiveAt: () => true } : undefined), expireObservable: new Observable(), } @@ -351,7 +375,7 @@ describe('user management', () => { describe('logs limitation', () => { let clock: Clock const sessionManager: LogsSessionManager = { - findTrackedSession: () => ({ id: SESSION_ID }), + findTrackedSession: () => ({ id: SESSION_ID, isActiveAt: () => true }), expireObservable: new Observable(), } diff --git a/packages/logs/src/domain/assembly.ts b/packages/logs/src/domain/assembly.ts index b038938677..2ebaf86d97 100644 --- a/packages/logs/src/domain/assembly.ts +++ b/packages/logs/src/domain/assembly.ts @@ -25,7 +25,7 @@ export function startLogsAssembly( LifeCycleEventType.RAW_LOG_COLLECTED, ({ rawLogsEvent, messageContext = undefined, savedCommonContext = undefined }) => { const startTime = getRelativeTime(rawLogsEvent.date) - const session = sessionManager.findTrackedSession(startTime) + const session = sessionManager.findTrackedSession(startTime, { returnExpired: true }) if (!session) { return @@ -35,7 +35,7 @@ export function startLogsAssembly( const log = combine( { service: configuration.service, - session_id: session.id, + session_id: session.isActiveAt(startTime) ? session.id : undefined, // Insert user first to allow overrides from global context usr: !isEmptyObject(commonContext.user) ? commonContext.user : undefined, view: commonContext.view, diff --git a/packages/logs/src/domain/contexts/internalContext.spec.ts b/packages/logs/src/domain/contexts/internalContext.spec.ts index 8e20ecdd72..2da152dae1 100644 --- a/packages/logs/src/domain/contexts/internalContext.spec.ts +++ b/packages/logs/src/domain/contexts/internalContext.spec.ts @@ -15,6 +15,7 @@ describe('internal context', () => { const sessionManagerMock = { findTrackedSession: () => ({ id: sessionIdMock, + isActiveAt: () => true, }), expireObservable: new Observable(), } diff --git a/packages/logs/src/domain/logsSessionManager.spec.ts b/packages/logs/src/domain/logsSessionManager.spec.ts index 929c653e9b..e1d9774ec6 100644 --- a/packages/logs/src/domain/logsSessionManager.spec.ts +++ b/packages/logs/src/domain/logsSessionManager.spec.ts @@ -7,6 +7,7 @@ import { stopSessionManager, ONE_SECOND, DOM_EVENT, + relativeNow, } from '@datadog/browser-core' import type { Clock } from '@datadog/browser-core/test' import { createNewEvent, mockClock } from '@datadog/browser-core/test' @@ -132,13 +133,18 @@ describe('logs session manager', () => { expect(logsSessionManager.findTrackedSession()!.id).toEqual('bar') }) }) + + describe('isActiveAt', () => { + it('should return true when the session is active and false when the session has expired', () => { setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION) const logsSessionManager = startLogsSessionManager(configuration as LogsConfiguration) clock.tick(10 * ONE_SECOND) setCookie(SESSION_STORE_KEY, '', DURATION) clock.tick(STORAGE_POLL_DELAY) - expect(logsSessionManager.findTrackedSession()).toBeUndefined() - expect(logsSessionManager.findTrackedSession(0 as RelativeTime)!.id).toBe('abcdef') + + const session = logsSessionManager.findTrackedSession(relativeNow(), { returnExpired: true })! + expect(session.isActiveAt(0 as RelativeTime)).toEqual(true) + expect(session.isActiveAt((11 * ONE_SECOND) as RelativeTime)).toEqual(false) }) }) }) diff --git a/packages/logs/src/domain/logsSessionManager.ts b/packages/logs/src/domain/logsSessionManager.ts index 6a867ae28c..946cfb34ed 100644 --- a/packages/logs/src/domain/logsSessionManager.ts +++ b/packages/logs/src/domain/logsSessionManager.ts @@ -1,5 +1,5 @@ import type { RelativeTime } from '@datadog/browser-core' -import { Observable, performDraw, startSessionManager } from '@datadog/browser-core' +import { Observable, performDraw, relativeNow, startSessionManager } from '@datadog/browser-core' import type { LogsConfiguration } from './configuration' export const LOGS_SESSION_KEY = 'logs' @@ -11,6 +11,7 @@ export interface LogsSessionManager { export type LogsSession = { id?: string // session can be tracked without id + isActiveAt: (startTime?: RelativeTime) => boolean } export const enum LoggerTrackingType { @@ -24,15 +25,16 @@ export function startLogsSessionManager(configuration: LogsConfiguration): LogsS ) return { - findTrackedSession: (startTime?: RelativeTime, { returnExpired } = { returnExpired: false }) => { + findTrackedSession: (startTime: RelativeTime, { returnExpired } = { returnExpired: true }) => { const session = returnExpired ? sessionManager.findActiveOrExpiredSession(startTime) : sessionManager.findActiveSession(startTime) if (session && session.trackingType === LoggerTrackingType.TRACKED) { return { - id: session.id, - } + id: session.id, + isActiveAt: (startTime = relativeNow()) => (session.endTime || Infinity) > startTime, + } } }, expireObservable: sessionManager.expireObservable, @@ -41,7 +43,7 @@ export function startLogsSessionManager(configuration: LogsConfiguration): LogsS export function startLogsSessionManagerStub(configuration: LogsConfiguration): LogsSessionManager { const isTracked = computeTrackingType(configuration) === LoggerTrackingType.TRACKED - const session = isTracked ? {} : undefined + const session = isTracked ? { isActiveAt: () => true } : undefined return { findTrackedSession: () => session, expireObservable: new Observable(),