diff --git a/src/CountlyAnalytics.ts b/src/CountlyAnalytics.ts index 476508ce8c..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,