Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

startSession should no longer clone the client #2003

Merged
merged 2 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/plugin-express/src/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ module.exports = {
name: 'express',
load: client => {
const requestHandler = (req, res, next) => {
// Get a client to be scoped to this request. If sessions are enabled, use the
// resumeSession() call to get a session client, otherwise, clone the existing client.
const requestClient = client._config.autoTrackSessions ? client.resumeSession() : clone(client)
// clone the client to be scoped to this request. If sessions are enabled, start one
imjoehaines marked this conversation as resolved.
Show resolved Hide resolved
const requestClient = clone(client)
if (requestClient._config.autoTrackSessions) {
requestClient.startSession()
}

// attach it to the request
req.bugsnag = requestClient
Expand Down
16 changes: 10 additions & 6 deletions packages/plugin-koa/src/koa.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ module.exports = {
name: 'koa',
load: client => {
const requestHandler = async (ctx, next) => {
// Get a client to be scoped to this request. If sessions are enabled, use the
// resumeSession() call to get a session client, otherwise, clone the existing client.
const requestClient = client._config.autoTrackSessions ? client.resumeSession() : clone(client)
// clone the client to be scoped to this request. If sessions are enabled, start one
const requestClient = clone(client)
if (requestClient._config.autoTrackSessions) {
requestClient.startSession()
}

ctx.bugsnag = requestClient

Expand All @@ -35,9 +37,11 @@ module.exports = {
}

requestHandler.v1 = function * (next) {
// Get a client to be scoped to this request. If sessions are enabled, use the
// resumeSession() call to get a session client, otherwise, clone the existing client.
const requestClient = client._config.autoTrackSessions ? client.resumeSession() : clone(client)
// clone the client to be scoped to this request. If sessions are enabled, start one
const requestClient = clone(client)
if (requestClient._config.autoTrackSessions) {
requestClient.startSession()
}

this.bugsnag = requestClient

Expand Down
13 changes: 7 additions & 6 deletions packages/plugin-koa/test/koa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('plugin: koa', () => {
})

describe('requestHandler', () => {
it('should start a session and attach a client to the context', async () => {
it('should clone the client, start a session and attach the cloned client to the context', async () => {
const client = new Client({ apiKey: 'api_key', plugins: [plugin] })

const startSession = jest.fn().mockReturnValue(client)
Expand All @@ -58,10 +58,11 @@ describe('plugin: koa', () => {

expect(client._logger.warn).not.toHaveBeenCalled()
expect(client._logger.error).not.toHaveBeenCalled()
expect(startSession).not.toHaveBeenCalled()
expect(startSession).toHaveBeenCalledTimes(1)
expect(pauseSession).not.toHaveBeenCalled()
expect(resumeSession).toHaveBeenCalledTimes(1)
expect(context.bugsnag).toBe(client)
expect(resumeSession).not.toHaveBeenCalled()
expect(context.bugsnag).toStrictEqual(expect.any(Client))
expect(context.bugsnag).not.toBe(client)
expect(client._clientContext.run).toHaveBeenCalledWith(expect.any(Client), next)
})

Expand Down Expand Up @@ -114,7 +115,7 @@ describe('plugin: koa', () => {
expect(client._clientContext.run).toHaveBeenCalledWith(expect.any(Client), next)

const event: Event = await new Promise(resolve => {
client.notify(new Error('abc'), noop, (_, event) => resolve(event as Event))
(context.bugsnag as Client).notify(new Error('abc'), noop, (_, event) => resolve(event as Event))
})

expect(client._logger.warn).not.toHaveBeenCalled()
Expand Down Expand Up @@ -183,7 +184,7 @@ describe('plugin: koa', () => {
expect(client._clientContext.run).toHaveBeenCalledWith(expect.any(Client), next)

const event: Event = await new Promise(resolve => {
client.notify(new Error('abc'), noop, (_, event) => resolve(event as Event))
(context.bugsnag as Client).notify(new Error('abc'), noop, (_, event) => resolve(event as Event))
})

expect(client._logger.warn).not.toHaveBeenCalled()
Expand Down
8 changes: 5 additions & 3 deletions packages/plugin-restify/src/restify.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ module.exports = {
name: 'restify',
load: client => {
const requestHandler = (req, res, next) => {
// Get a client to be scoped to this request. If sessions are enabled, use the
// resumeSession() call to get a session client, otherwise, clone the existing client.
const requestClient = client._config.autoTrackSessions ? client.resumeSession() : clone(client)
// clone the client to be scoped to this request. If sessions are enabled, start one
const requestClient = clone(client)
if (requestClient._config.autoTrackSessions) {
requestClient.startSession()
}

// attach it to the request
req.bugsnag = requestClient
Expand Down
11 changes: 4 additions & 7 deletions packages/plugin-server-session/session.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const intRange = require('@bugsnag/core/lib/validators/int-range')
const clone = require('@bugsnag/core/lib/clone-client')
const SessionTracker = require('./tracker')
const Backoff = require('backo')
const runSyncCallbacks = require('@bugsnag/core/lib/sync-callback-runner')
Expand All @@ -11,11 +10,10 @@ module.exports = {
sessionTracker.start()
client._sessionDelegate = {
startSession: (client, session) => {
const sessionClient = clone(client)
sessionClient._session = session
sessionClient._pausedSession = null
sessionTracker.track(sessionClient._session)
return sessionClient
client._session = session
client._pausedSession = null
sessionTracker.track(client._session)
return client
},
pauseSession: (client) => {
client._pausedSession = client._session
Expand All @@ -31,7 +29,6 @@ module.exports = {
if (client._pausedSession) {
client._session = client._pausedSession
client._pausedSession = null

return client
}

Expand Down
48 changes: 12 additions & 36 deletions packages/plugin-server-session/test/session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,30 +96,6 @@ describe('plugin: server sessions', () => {
c.startSession()
})

it('should clone properties that shouldn’t be mutated on the original client', () => {
class TrackerMock extends EventEmitter {
start () {}
stop () {}
track () {}
}
Tracker.mockImplementation(() => new TrackerMock() as any)

const c = new Client({ apiKey: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }, undefined, [plugin])

c.leaveBreadcrumb('tick')
c._metadata = { datetime: { tz: 'GMT+1' } }

const sessionClient = c.startSession()

sessionClient.leaveBreadcrumb('tock')
sessionClient.addMetadata('other', { widgetsAdded: 'cat,dog,mouse' })

expect(c._breadcrumbs.length).toBe(1)
expect(Object.keys(c._metadata).length).toBe(1)
expect(sessionClient._breadcrumbs.length).toBe(2)
expect(Object.keys(sessionClient._metadata).length).toBe(2)
})

it('should support pausing/resuming sessions', () => {
class TrackerMock extends EventEmitter {
start () {}
Expand All @@ -131,27 +107,27 @@ describe('plugin: server sessions', () => {
const c = new Client({ apiKey: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }, undefined, [plugin])

// start a session and get its id
const sessionClient = c.startSession()
const sid0 = (sessionClient._session as Session).id
c.startSession()
const sid0 = (c._session as Session).id

// ensure pausing the session clears the client._session property
sessionClient.pauseSession()
const s1 = sessionClient._session
const psid1 = (sessionClient._pausedSession as Session).id
c.pauseSession()
const s1 = c._session
const psid1 = (c._pausedSession as Session).id
expect(s1).toBe(null)
expect(psid1).toBe(sid0)

// ensure resuming the session gets back the original session (not a new one)
sessionClient.resumeSession()
const sid2 = (sessionClient._session as Session).id
c.resumeSession()
const sid2 = (c._session as Session).id
expect(sid2).toBe(sid0)

// ensure resumeSession() starts a new one when no paused session exists
sessionClient._session = null
sessionClient._pausedSession = null
const resumedClient = sessionClient.resumeSession()
expect(resumedClient._session).toBeTruthy()
const sid3 = (resumedClient._session as Session).id
c._session = null
c._pausedSession = null
c.resumeSession()
expect(c._session).toBeTruthy()
const sid3 = (c._session as unknown as Session).id
expect(sid3).not.toBe(sid0)
})
})
Loading