diff --git a/src/CountlyAnalytics.ts b/src/CountlyAnalytics.ts index 600a9be1bf..36d4b5ae8c 100644 --- a/src/CountlyAnalytics.ts +++ b/src/CountlyAnalytics.ts @@ -343,6 +343,18 @@ const getRoomStats = (roomId: string) => { } } +// async wrapper for regex-powered String.prototype.replace +const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise) => { + const promises: Promise[] = []; + // dry-run to calculate the replace values + str.replace(regex, (...args: string[]) => { + promises.push(fn(...args)); + return ""; + }); + const values = await Promise.all(promises); + return str.replace(regex, () => values.shift()); +}; + export default class CountlyAnalytics { private baseUrl: URL = null; private appKey: string = null; @@ -495,7 +507,7 @@ export default class CountlyAnalytics { return this.lastMsTs; } - public recordError(err: Error | string, fatal = false) { + public async recordError(err: Error | string, fatal = false) { if (this.disabled || this.anonymous) return; let error = ""; @@ -523,6 +535,11 @@ export default class CountlyAnalytics { error = err + ""; } + // sanitize the error from identifiers + error = await strReplaceAsync(error, /([!@+#]).+?:[\w:.]+/g, async (substring: string, glyph: string) => { + return glyph + await hashHex(substring.substring(1)); + }); + const metrics = this.getMetrics(); const ob: ICrash = { _resolution: metrics?._resolution, @@ -666,11 +683,11 @@ export default class CountlyAnalytics { return window.innerWidth > window.innerHeight ? Orientation.Landscape : Orientation.Portrait; }; - private reportOrientation() { + private reportOrientation = () => { this.track("[CLY]_orientation", { mode: this.getOrientation(), }); - } + }; private startTime() { if (!this.trackTime) { @@ -754,7 +771,7 @@ export default class CountlyAnalytics { } } - private endSession() { + private endSession = () => { if (this.sessionStarted) { window.removeEventListener("resize", this.reportOrientation) @@ -765,7 +782,7 @@ export default class CountlyAnalytics { }); } this.sessionStarted = false; - } + }; private onVisibilityChange = () => { if (document.hidden) {