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

fix(new-metrics): add TypeError #3527

Open
wants to merge 3 commits into
base: beta
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
isNetworkError,
isUnauthorizedError,
isSdpOfferCreationError,
isTypeError,
} from './call-diagnostic-metrics.util';
import {CLIENT_NAME} from '../config';
import {
Expand Down Expand Up @@ -56,6 +57,7 @@ import {
AUTHENTICATION_FAILED_CODE,
WEBEX_SUB_SERVICE_TYPES,
SDP_OFFER_CREATION_ERROR_MAP,
TYPE_ERROR_CLIENT_CODE,
} from './config';

const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
Expand Down Expand Up @@ -526,6 +528,17 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
generateClientEventErrorPayload(rawError: any) {
const rawErrorMessage = rawError.message;
const httpStatusCode = rawError.statusCode;

if (isTypeError(rawError)) {
return this.getErrorPayloadForClientErrorCode({
serviceErrorCode: undefined,
clientErrorCode: TYPE_ERROR_CLIENT_CODE,
serviceErrorName: rawError.name,
rawErrorMessage,
httpStatusCode,
});
}

if (rawError.name) {
if (isBrowserMediaErrorName(rawError.name)) {
return this.getErrorPayloadForClientErrorCode({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,15 @@ export const isSdpOfferCreationError = (rawError: any) => {
return false;
};

/**
* Any service can return a TypeError, which tells little about the service it came from
* Documentation can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError/TypeError
*
* @param errorCode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not really an error code

* @returns
*/
export const isTypeError = (error: any) => error instanceof TypeError;

/**
* MDN Media Devices getUserMedia() method returns a name if it errs
* Documentation can be found here: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const MISSING_ROAP_ANSWER_CLIENT_CODE = 2007;
export const DTLS_HANDSHAKE_FAILED_CLIENT_CODE = 2008;
export const ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE = 2010;
export const ICE_FAILED_WITHOUT_TURN_TLS_CLIENT_CODE = 2009;
export const TYPE_ERROR_CLIENT_CODE = 2011;
export const WBX_APP_API_URL = 'wbxappapi'; // MeetingInfo WebexAppApi response object normally contains a body.url that includes the string 'wbxappapi'

export const WEBEX_SUB_SERVICE_TYPES: Record<string, ClientSubServiceType> = {
Expand All @@ -33,7 +34,6 @@ const BROWSER_MEDIA_ERROR_NAMES = {
NOT_FOUND_ERROR: 'NotFoundError',
OVERCONSTRAINED_ERROR: 'OverconstrainedError',
SECURITY_ERROR: 'SecurityError',
TYPE_ERROR: 'TypeError',
};

export const BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP = {
Expand All @@ -44,7 +44,6 @@ export const BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP = {
[BROWSER_MEDIA_ERROR_NAMES.NOT_FOUND_ERROR]: 2729, // User did not grant permission
[BROWSER_MEDIA_ERROR_NAMES.OVERCONSTRAINED_ERROR]: 2729, // Thrown if the specified constraints resulted in no candidate devices which met the criteria requested.
[BROWSER_MEDIA_ERROR_NAMES.SECURITY_ERROR]: 2729, // Thrown if user media support is disabled on the Document on which getUserMedia() was called. The mechanism by which user media support is enabled and disabled is left up to the individual user agent.
[BROWSER_MEDIA_ERROR_NAMES.TYPE_ERROR]: 2729, // Thrown if the list of constraints specified is empty, or has all constraints set to false. This can also happen if you try to call getUserMedia() in an insecure context, since navigator.mediaDevices is undefined in an insecure context.
};

export const SDP_OFFER_CREATION_ERROR_MAP = {
Expand Down Expand Up @@ -127,6 +126,7 @@ export const ERROR_DESCRIPTIONS = {
ICE_FAILED_WITH_TURN_TLS: 'ICEFailedWithTURN_TLS',
SDP_OFFER_CREATION_ERROR: 'SdpOfferCreationError',
SDP_OFFER_CREATION_ERROR_MISSING_CODEC: 'SdpOfferCreationErrorMissingCodec',
TYPE_ERROR: 'TypeError',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you add it under SDP section? Is TypeError not a generic thing?

};

export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
Expand Down Expand Up @@ -395,6 +395,11 @@ export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEv
category: 'network',
fatal: true,
},
[TYPE_ERROR_CLIENT_CODE]: {
errorDescription: ERROR_DESCRIPTIONS.TYPE_ERROR,
category: 'other',
fatal: true,
},
2050: {
errorDescription: ERROR_DESCRIPTIONS.SDP_OFFER_CREATION_ERROR,
category: 'media',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,39 @@ describe('internal-plugin-metrics', () => {
rawErrorMessage: 'bad times',
};

const checkTypeError = (payload: any, isExpectedToBeCalled: boolean) => {
const res = cd.generateClientEventErrorPayload(payload);
const expectedResult = {
category: 'other',
errorDescription: 'TypeError',
fatal: true,
name: 'other',
shownToUser: false,
serviceErrorCode: undefined,
errorCode: 2011,
errorData: {errorName: payload.name},
rawErrorMessage: payload.message,
};

if (isExpectedToBeCalled) {
assert.deepEqual(res, expectedResult);
} else {
console.log(res);
assert.notDeepEqual(res, expectedResult);
}
};


it('should generate type error payload if rawError isTypeError', () => {
const typeError = new TypeError;
checkTypeError(typeError, true);
});

it('should not generate type error payload if rawError is not TypeError', () => {
const typeError = new Error;
checkTypeError(typeError, false);
});

const checkNameError = (payload: any, isExpectedToBeCalled: boolean) => {
const res = cd.generateClientEventErrorPayload(payload);
const expectedResult = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
isUnauthorizedError,
generateClientErrorCodeForIceFailure,
isSdpOfferCreationError,
isTypeError,
} = CallDiagnosticUtils;

describe('internal-plugin-metrics', () => {
Expand Down Expand Up @@ -205,6 +206,21 @@ describe('internal-plugin-metrics', () => {
});
});

describe('isTypeError', () => {
[
[new TypeError, true],
[new TypeError('oh no'), true],
[new Error, false],
[new Error('oh no'), false],
[{name: 'TypeError'}, false],
].forEach(([error, expected]) => {
it(`for rawError ${error} returns the correct result`, () => {
//@ts-ignore
assert.deepEqual(isTypeError(error), expected);
});
});
});

describe('isBrowserMediaErrorName', () => {
[
['PermissionDeniedError', true],
Expand All @@ -221,8 +237,6 @@ describe('internal-plugin-metrics', () => {
['OverconstrainedErrors', false],
['SecurityError', true],
['SecurityErrors', false],
['TypeError', true],
['TypeErrors', false],
['', false],
['SomethingElse', false],
[{name: 'SomethingElse'}, false],
Expand Down