Skip to content

Commit d9a0a0b

Browse files
committed
Add config option to turn on in-room event sending timing metrics
This is intended to be hooked up to an external system. Due to the extra events and metadata concerns, this is only available if turned on from the config. See `sendTimePerformanceMetrics.ts` for event schemas.
1 parent 97e107e commit d9a0a0b

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

src/ContentMessages.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import {
3939
import { IUpload } from "./models/IUpload";
4040
import { IAbortablePromise, IImageInfo } from "matrix-js-sdk/src/@types/partials";
4141
import { BlurhashEncoder } from "./BlurhashEncoder";
42+
import SettingsStore from "./settings/SettingsStore";
43+
import { decorateStartSendingTime, sendRoundTripMetric } from "./sendTimePerformanceMetrics";
4244

4345
const MAX_WIDTH = 800;
4446
const MAX_HEIGHT = 600;
@@ -539,6 +541,10 @@ export default class ContentMessages {
539541
msgtype: "", // set later
540542
};
541543

544+
if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
545+
decorateStartSendingTime(content);
546+
}
547+
542548
// if we have a mime type for the file, add it to the message metadata
543549
if (file.type) {
544550
content.info.mimetype = file.type;
@@ -614,6 +620,11 @@ export default class ContentMessages {
614620
}).then(function() {
615621
if (upload.canceled) throw new UploadCanceledError();
616622
const prom = matrixClient.sendMessage(roomId, content);
623+
if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
624+
prom.then(resp => {
625+
sendRoundTripMetric(matrixClient, roomId, resp.event_id);
626+
});
627+
}
617628
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, false, content);
618629
return prom;
619630
}, function(err) {

src/components/views/rooms/SendMessageComposer.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import { Room } from 'matrix-js-sdk/src/models/room';
5454
import ErrorDialog from "../dialogs/ErrorDialog";
5555
import QuestionDialog from "../dialogs/QuestionDialog";
5656
import { ActionPayload } from "../../../dispatcher/payloads";
57+
import { decorateStartSendingTime, sendRoundTripMetric } from "../../../sendTimePerformanceMetrics";
5758

5859
function addReplyToMessageContent(
5960
content: IContent,
@@ -418,6 +419,10 @@ export default class SendMessageComposer extends React.Component<IProps> {
418419
// don't bother sending an empty message
419420
if (!content.body.trim()) return;
420421

422+
if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
423+
decorateStartSendingTime(content);
424+
}
425+
421426
const prom = this.context.sendMessage(roomId, content);
422427
if (replyToEvent) {
423428
// Clear reply_to_event as we put the message into the queue
@@ -433,6 +438,11 @@ export default class SendMessageComposer extends React.Component<IProps> {
433438
dis.dispatch({ action: `effects.${effect.command}` });
434439
}
435440
});
441+
if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
442+
prom.then(resp => {
443+
sendRoundTripMetric(this.context, roomId, resp.event_id);
444+
});
445+
}
436446
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, !!replyToEvent, content);
437447
}
438448

src/sendTimePerformanceMetrics.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2021 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { MatrixClient } from "matrix-js-sdk";
18+
19+
/**
20+
* Decorates the given event content object with the "send start time". The
21+
* object will be modified in-place.
22+
* @param {object} content The event content.
23+
*/
24+
export function decorateStartSendingTime(content: object) {
25+
content['io.element.performance_metrics'] = {
26+
sendStartTs: Date.now(),
27+
};
28+
}
29+
30+
/**
31+
* Called when an event decorated with `decorateStartSendingTime()` has been sent
32+
* by the server (the client now knows the event ID).
33+
* @param {MatrixClient} client The client to send as.
34+
* @param {string} inRoomId The room ID where the original event was sent.
35+
* @param {string} forEventId The event ID for the decorated event.
36+
*/
37+
export function sendRoundTripMetric(client: MatrixClient, inRoomId: string, forEventId: string) {
38+
// noinspection JSIgnoredPromiseFromCall
39+
client.sendEvent(inRoomId, 'io.element.performance_metric', {
40+
// XXX: We stick all of this into `m.relates_to` so it doesn't end up encrypted.
41+
"m.relates_to": {
42+
rel_type: "io.element.metric",
43+
event_id: forEventId,
44+
responseTs: Date.now(),
45+
kind: 'send_time',
46+
} as any, // override types because we're actually allowed to add extra metadata to relates_to
47+
});
48+
}

src/settings/Settings.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ export const SETTINGS: {[setting: string]: ISetting} = {
759759
default: true,
760760
controller: new ReducedMotionController(),
761761
},
762+
"Performance.addSendMessageTimingMetadata": {
763+
supportedLevels: [SettingLevel.CONFIG],
764+
default: false,
765+
},
762766
"Widgets.pinned": { // deprecated
763767
supportedLevels: LEVELS_ROOM_OR_ACCOUNT,
764768
default: {},

0 commit comments

Comments
 (0)