Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 04b5b58

Browse files
authored
Expected UTDs: report a different Posthog code (#12389)
* `DecryptionFailureTracker`: stronger typing Use `DecryptionFailureCode` rather than string * `DecryptionFailureTracker`: remove use of `DecryptionError` The second argument to `MatrixEventEvent.Decrypted` callbacks is deprecatedf, and we can get the info we need direct from the event. This means that we no longer need to reference the internal `DecryptionError` class in the js-sdk. * `DecryptionFailureTracker`: use a different Posthog code for historical UTDs * Update for new UTD error codes
1 parent 6cec2bb commit 04b5b58

File tree

5 files changed

+84
-134
lines changed

5 files changed

+84
-134
lines changed

.eslintrc.js

-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ module.exports = {
108108
"!matrix-js-sdk/src/extensible_events_v1/PollEndEvent",
109109
"!matrix-js-sdk/src/extensible_events_v1/InvalidEventError",
110110
"!matrix-js-sdk/src/crypto",
111-
"!matrix-js-sdk/src/crypto/algorithms",
112111
"!matrix-js-sdk/src/crypto/aes",
113112
"!matrix-js-sdk/src/crypto/olmlib",
114113
"!matrix-js-sdk/src/crypto/crypto",

src/DecryptionFailureTracker.ts

+31-29
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import { DecryptionError } from "matrix-js-sdk/src/crypto/algorithms";
1817
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
1918
import { Error as ErrorEvent } from "@matrix-org/analytics-events/types/typescript/Error";
19+
import { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api";
2020

2121
import { PosthogAnalytics } from "./PosthogAnalytics";
2222

@@ -25,17 +25,15 @@ export class DecryptionFailure {
2525

2626
public constructor(
2727
public readonly failedEventId: string,
28-
public readonly errorCode: string,
28+
public readonly errorCode: DecryptionFailureCode,
2929
) {
3030
this.ts = Date.now();
3131
}
3232
}
3333

34-
type ErrorCode = "OlmKeysNotSentError" | "OlmIndexError" | "UnknownError" | "OlmUnspecifiedError";
35-
34+
type ErrorCode = ErrorEvent["name"];
3635
type TrackingFn = (count: number, trackedErrCode: ErrorCode, rawError: string) => void;
37-
38-
export type ErrCodeMapFn = (errcode: string) => ErrorCode;
36+
export type ErrCodeMapFn = (errcode: DecryptionFailureCode) => ErrorCode;
3937

4038
export class DecryptionFailureTracker {
4139
private static internalInstance = new DecryptionFailureTracker(
@@ -52,12 +50,14 @@ export class DecryptionFailureTracker {
5250
(errorCode) => {
5351
// Map JS-SDK error codes to tracker codes for aggregation
5452
switch (errorCode) {
55-
case "MEGOLM_UNKNOWN_INBOUND_SESSION_ID":
53+
case DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID:
5654
return "OlmKeysNotSentError";
57-
case "OLM_UNKNOWN_MESSAGE_INDEX":
55+
case DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX:
5856
return "OlmIndexError";
59-
case undefined:
60-
return "OlmUnspecifiedError";
57+
case DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP:
58+
case DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED:
59+
case DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP:
60+
return "HistoricalMessage";
6161
default:
6262
return "UnknownError";
6363
}
@@ -76,11 +76,11 @@ export class DecryptionFailureTracker {
7676
// accumulated in `failureCounts`.
7777
public visibleFailures: Map<string, DecryptionFailure> = new Map();
7878

79-
// A histogram of the number of failures that will be tracked at the next tracking
80-
// interval, split by failure error code.
81-
public failureCounts: Record<string, number> = {
82-
// [errorCode]: 42
83-
};
79+
/**
80+
* A histogram of the number of failures that will be tracked at the next tracking
81+
* interval, split by failure error code.
82+
*/
83+
private failureCounts: Map<DecryptionFailureCode, number> = new Map();
8484

8585
// Event IDs of failures that were tracked previously
8686
public trackedEvents: Set<string> = new Set();
@@ -108,10 +108,10 @@ export class DecryptionFailureTracker {
108108
*
109109
* @param {function} fn The tracking function, which will be called when failures
110110
* are tracked. The function should have a signature `(count, trackedErrorCode) => {...}`,
111-
* where `count` is the number of failures and `errorCode` matches the `.code` of
112-
* provided DecryptionError errors (by default, unless `errorCodeMapFn` is specified.
113-
* @param {function?} errorCodeMapFn The function used to map error codes to the
114-
* trackedErrorCode. If not provided, the `.code` of errors will be used.
111+
* where `count` is the number of failures and `errorCode` matches the output of `errorCodeMapFn`.
112+
*
113+
* @param {function} errorCodeMapFn The function used to map decryption failure reason codes to the
114+
* `trackedErrorCode`.
115115
*/
116116
private constructor(
117117
private readonly fn: TrackingFn,
@@ -138,13 +138,15 @@ export class DecryptionFailureTracker {
138138
// localStorage.setItem('mx-decryption-failure-event-ids', JSON.stringify([...this.trackedEvents]));
139139
// }
140140

141-
public eventDecrypted(e: MatrixEvent, err: DecryptionError): void {
142-
// for now we only track megolm decrytion failures
141+
public eventDecrypted(e: MatrixEvent): void {
142+
// for now we only track megolm decryption failures
143143
if (e.getWireContent().algorithm != "m.megolm.v1.aes-sha2") {
144144
return;
145145
}
146-
if (err) {
147-
this.addDecryptionFailure(new DecryptionFailure(e.getId()!, err.code));
146+
147+
const errCode = e.decryptionFailureReason;
148+
if (errCode !== null) {
149+
this.addDecryptionFailure(new DecryptionFailure(e.getId()!, errCode));
148150
} else {
149151
// Could be an event in the failures, remove it
150152
this.removeDecryptionFailuresForEvent(e);
@@ -205,7 +207,7 @@ export class DecryptionFailureTracker {
205207
this.failures = new Map();
206208
this.visibleEvents = new Set();
207209
this.visibleFailures = new Map();
208-
this.failureCounts = {};
210+
this.failureCounts = new Map();
209211
}
210212

211213
/**
@@ -236,7 +238,7 @@ export class DecryptionFailureTracker {
236238
private aggregateFailures(failures: Set<DecryptionFailure>): void {
237239
for (const failure of failures) {
238240
const errorCode = failure.errorCode;
239-
this.failureCounts[errorCode] = (this.failureCounts[errorCode] || 0) + 1;
241+
this.failureCounts.set(errorCode, (this.failureCounts.get(errorCode) ?? 0) + 1);
240242
}
241243
}
242244

@@ -245,12 +247,12 @@ export class DecryptionFailureTracker {
245247
* function with the number of failures that should be tracked.
246248
*/
247249
public trackFailures(): void {
248-
for (const errorCode of Object.keys(this.failureCounts)) {
249-
if (this.failureCounts[errorCode] > 0) {
250+
for (const [errorCode, count] of this.failureCounts.entries()) {
251+
if (count > 0) {
250252
const trackedErrorCode = this.errorCodeMapFn(errorCode);
251253

252-
this.fn(this.failureCounts[errorCode], trackedErrorCode, errorCode);
253-
this.failureCounts[errorCode] = 0;
254+
this.fn(count, trackedErrorCode, errorCode);
255+
this.failureCounts.set(errorCode, 0);
254256
}
255257
}
256258
}

src/components/structures/MatrixChat.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import { defer, IDeferred, QueryDict } from "matrix-js-sdk/src/utils";
3232
import { logger } from "matrix-js-sdk/src/logger";
3333
import { throttle } from "lodash";
3434
import { CryptoEvent } from "matrix-js-sdk/src/crypto";
35-
import { DecryptionError } from "matrix-js-sdk/src/crypto/algorithms";
3635
import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup";
3736
import { TooltipProvider } from "@vector-im/compound-web";
3837

@@ -1598,7 +1597,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
15981597

15991598
// When logging out, stop tracking failures and destroy state
16001599
cli.on(HttpApiEvent.SessionLoggedOut, () => dft.stop());
1601-
cli.on(MatrixEventEvent.Decrypted, (e, err) => dft.eventDecrypted(e, err as DecryptionError));
1600+
cli.on(MatrixEventEvent.Decrypted, (e) => dft.eventDecrypted(e));
16021601

16031602
cli.on(ClientEvent.Room, (room) => {
16041603
if (cli.isCryptoEnabled()) {

0 commit comments

Comments
 (0)