Skip to content

Commit

Permalink
Send logs when a session is expired
Browse files Browse the repository at this point in the history
- Send logs when a session is expired
- Only set session id when the session is active
  • Loading branch information
amortemousque committed Feb 1, 2024
1 parent c9e0459 commit 6e13af9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 30 deletions.
66 changes: 45 additions & 21 deletions packages/logs/src/domain/assembly.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,20 @@ 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<LogsEvent & Context> = []
let mainLogger: Logger

beforeEach(() => {
sessionIsTracked = true
sessionIsActive = true
lifeCycle = new LifeCycle()
lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (serverRumEvent) => serverLogs.push(serverRumEvent))
const configuration = {
Expand Down Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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<void>(),
}

Expand Down Expand Up @@ -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(),
}

Expand Down
4 changes: 2 additions & 2 deletions packages/logs/src/domain/assembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions packages/logs/src/domain/contexts/internalContext.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('internal context', () => {
const sessionManagerMock = {
findTrackedSession: () => ({
id: sessionIdMock,
isActiveAt: () => true,
}),
expireObservable: new Observable<void>(),
}
Expand Down
10 changes: 8 additions & 2 deletions packages/logs/src/domain/logsSessionManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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)
})
})
})
Expand Down
12 changes: 7 additions & 5 deletions packages/logs/src/domain/logsSessionManager.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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 {
Expand All @@ -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,
Expand All @@ -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(),
Expand Down

0 comments on commit 6e13af9

Please sign in to comment.