diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index 700cdf17e32..eeb259f906f 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -40,6 +40,7 @@ import { isEndOfLifeVersion, } from '../utils/end-of-life-server'; import type { ImportConnectionOptions } from '@mongodb-js/connection-storage/provider'; +import { getErrorCodeCauseChain } from '../utils/telemetry'; export type ConnectionsEventMap = { connected: ( @@ -1278,6 +1279,7 @@ const connectionAttemptError = ( async () => { const trackParams = { error_code: err.code, + error_code_cause_chain: getErrorCodeCauseChain(err), error_name: err.codeName ?? err.name, }; if (connectionInfo) { diff --git a/packages/compass-connections/src/utils/telemetry.spec.tsx b/packages/compass-connections/src/utils/telemetry.spec.tsx index 87b010e9f4e..a06cd0ac565 100644 --- a/packages/compass-connections/src/utils/telemetry.spec.tsx +++ b/packages/compass-connections/src/utils/telemetry.spec.tsx @@ -3,6 +3,7 @@ import { trackConnectionDisconnectedEvent, trackConnectionCreatedEvent, trackConnectionRemovedEvent, + getErrorCodeCauseChain, } from './telemetry'; import { expect } from 'chai'; import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer'; @@ -64,4 +65,47 @@ describe('Connections telemetry', function () { expect(event).to.equal('Connection Removed'); expect(properties).to.deep.equal(expected); }); + + describe('#getErrorCodeCauseChain', function () { + it('should return undefined when no error', function () { + const result = getErrorCodeCauseChain(undefined); + expect(result).to.be.undefined; + }); + + it('should return undefined when there are no error codes', function () { + const result = getErrorCodeCauseChain({}); + expect(result).to.be.undefined; + }); + + it('should return an array with the error code', function () { + const error: any = new Error('Test error'); + error.code = 123; + + const result = getErrorCodeCauseChain(error); + expect(result).to.deep.equal([123]); + }); + + it('should return an array of error codes from the cause chain', function () { + const error: Error & { code?: number } = new Error('Test error'); + error.code = 123; + + // No code / codeName on error two. + const errorTwo = new Error('Test error two'); + + const errorThree: Error & { codeName?: string } = new Error( + 'Test error three' + ); + errorThree.codeName = 'PINEAPPLE'; + + const errorFour: Error & { code?: number } = new Error('Test error four'); + errorFour.code = 1111; + + error.cause = errorTwo; + errorTwo.cause = errorThree; + errorThree.cause = errorFour; + + const result = getErrorCodeCauseChain(error); + expect(result).to.deep.equal([123, 'PINEAPPLE', 1111]); + }); + }); }); diff --git a/packages/compass-connections/src/utils/telemetry.tsx b/packages/compass-connections/src/utils/telemetry.tsx index 8c2b632f8af..8bfebf519d0 100644 --- a/packages/compass-connections/src/utils/telemetry.tsx +++ b/packages/compass-connections/src/utils/telemetry.tsx @@ -27,3 +27,25 @@ export function trackConnectionRemovedEvent( ): void { track('Connection Removed', {}, connectionInfo); } + +export function getErrorCodeCauseChain( + err: unknown +): (string | number)[] | undefined { + const errorCodesInCauseChain: (string | number)[] = []; + let current = err; + + while (current && typeof current === 'object') { + if ('code' in current && current.code) { + errorCodesInCauseChain.push(current.code as string | number); + } else if ('codeName' in current && current.codeName) { + errorCodesInCauseChain.push(current.codeName as string | number); + } + current = (current as { cause?: unknown }).cause; + } + + if (errorCodesInCauseChain.length === 0) { + return undefined; + } + + return errorCodesInCauseChain; +} diff --git a/packages/compass-telemetry/src/telemetry-events.ts b/packages/compass-telemetry/src/telemetry-events.ts index 3ced818db18..66e4f2b0305 100644 --- a/packages/compass-telemetry/src/telemetry-events.ts +++ b/packages/compass-telemetry/src/telemetry-events.ts @@ -832,6 +832,12 @@ type ConnectionFailedEvent = ConnectionScopedEvent<{ * The error name. */ error_name: string; + + /** + * The error codes (or code names) from the error's cause chain. + * The driver and the OIDC library we use are two places that use cause chains. + */ + error_code_cause_chain: (string | number)[] | undefined; } & ExtraConnectionData; }>;