You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-06 12:02:40 +03:00
Add remote user and call id in webrtc call stats (#3413)
* Refactor names in webrtc stats * Refactor summary stats reporter to gatherer * Add call and opponent member id to call stats reports * Update opponent member when we know them * Add missing return type * remove async in test * mark new stats property as optional to avoid braking changes
This commit is contained in:
@@ -158,7 +158,7 @@ describe("CallStatsReportGatherer", () => {
|
|||||||
|
|
||||||
collector = new CallStatsReportGatherer(CALL_ID, USER_ID, rtcSpy, emitter);
|
collector = new CallStatsReportGatherer(CALL_ID, USER_ID, rtcSpy, emitter);
|
||||||
});
|
});
|
||||||
it("in case of stable, parse remote and local description", async () => {
|
it("in case of stable, parse remote and local description", () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const mediaSsrcHandler = {
|
const mediaSsrcHandler = {
|
||||||
parse: jest.fn(),
|
parse: jest.fn(),
|
||||||
|
@@ -2848,7 +2848,9 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
pc.addEventListener("negotiationneeded", this.onNegotiationNeeded);
|
pc.addEventListener("negotiationneeded", this.onNegotiationNeeded);
|
||||||
pc.addEventListener("datachannel", this.onDataChannel);
|
pc.addEventListener("datachannel", this.onDataChannel);
|
||||||
|
|
||||||
this.stats?.addStatsReportGatherer(this.callId, "unknown", pc);
|
const opponentMember: RoomMember | undefined = this.getOpponentMember();
|
||||||
|
const opponentMemberId = opponentMember ? opponentMember.userId : "unknown";
|
||||||
|
this.stats?.addStatsReportGatherer(this.callId, opponentMemberId, pc);
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2882,6 +2884,9 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
|
|||||||
}
|
}
|
||||||
this.opponentCaps = msg.capabilities || ({} as CallCapabilities);
|
this.opponentCaps = msg.capabilities || ({} as CallCapabilities);
|
||||||
this.opponentMember = this.client.getRoom(this.roomId)!.getMember(ev.getSender()!) ?? undefined;
|
this.opponentMember = this.client.getRoom(this.roomId)!.getMember(ev.getSender()!) ?? undefined;
|
||||||
|
if (this.opponentMember) {
|
||||||
|
this.stats?.updateOpponentMember(this.callId, this.opponentMember.userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async addBufferedIceCandidates(): Promise<void> {
|
private async addBufferedIceCandidates(): Promise<void> {
|
||||||
|
@@ -37,7 +37,7 @@ export class CallStatsReportGatherer {
|
|||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
public readonly callId: string,
|
public readonly callId: string,
|
||||||
public readonly remoteUserId: string,
|
private opponentMemberId: string,
|
||||||
private readonly pc: RTCPeerConnection,
|
private readonly pc: RTCPeerConnection,
|
||||||
private readonly emitter: StatsReportEmitter,
|
private readonly emitter: StatsReportEmitter,
|
||||||
private readonly isFocus = true,
|
private readonly isFocus = true,
|
||||||
@@ -93,7 +93,9 @@ export class CallStatsReportGatherer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private processStatsReport(groupCallId: string, localUserId: string): void {
|
private processStatsReport(groupCallId: string, localUserId: string): void {
|
||||||
const byteSentStatsReport: ByteSentStatsReport = new Map<TrackID, ByteSend>();
|
const byteSentStatsReport: ByteSentStatsReport = new Map<TrackID, ByteSend>() as ByteSentStatsReport;
|
||||||
|
byteSentStatsReport.callId = this.callId;
|
||||||
|
byteSentStatsReport.opponentMemberId = this.opponentMemberId;
|
||||||
|
|
||||||
this.currentStatsReport?.forEach((now) => {
|
this.currentStatsReport?.forEach((now) => {
|
||||||
const before = this.previousStatsReport ? this.previousStatsReport.get(now.id) : null;
|
const before = this.previousStatsReport ? this.previousStatsReport.get(now.id) : null;
|
||||||
@@ -176,6 +178,8 @@ export class CallStatsReportGatherer {
|
|||||||
|
|
||||||
private processAndEmitConnectionStatsReport(): void {
|
private processAndEmitConnectionStatsReport(): void {
|
||||||
const report = ConnectionStatsReportBuilder.build(this.trackStats.getTrack2stats());
|
const report = ConnectionStatsReportBuilder.build(this.trackStats.getTrack2stats());
|
||||||
|
report.callId = this.callId;
|
||||||
|
report.opponentMemberId = this.opponentMemberId;
|
||||||
|
|
||||||
this.connectionStats.bandwidth = report.bandwidth;
|
this.connectionStats.bandwidth = report.bandwidth;
|
||||||
this.connectionStats.bitrate = report.bitrate;
|
this.connectionStats.bitrate = report.bitrate;
|
||||||
@@ -201,4 +205,8 @@ export class CallStatsReportGatherer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setOpponentMemberId(id: string): void {
|
||||||
|
this.opponentMemberId = id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,11 +45,15 @@ export class GroupCallStats {
|
|||||||
return this.gatherers.has(callId);
|
return this.gatherers.has(callId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addStatsReportGatherer(callId: string, userId: string, peerConnection: RTCPeerConnection): boolean {
|
public addStatsReportGatherer(
|
||||||
|
callId: string,
|
||||||
|
opponentMemberId: string,
|
||||||
|
peerConnection: RTCPeerConnection,
|
||||||
|
): boolean {
|
||||||
if (this.hasStatsReportGatherer(callId)) {
|
if (this.hasStatsReportGatherer(callId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.gatherers.set(callId, new CallStatsReportGatherer(callId, userId, peerConnection, this.reports));
|
this.gatherers.set(callId, new CallStatsReportGatherer(callId, opponentMemberId, peerConnection, this.reports));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +65,10 @@ export class GroupCallStats {
|
|||||||
return this.hasStatsReportGatherer(callId) ? this.gatherers.get(callId) : undefined;
|
return this.hasStatsReportGatherer(callId) ? this.gatherers.get(callId) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateOpponentMember(callId: string, opponentMember: string): void {
|
||||||
|
this.getStatsReportGatherer(callId)?.setOpponentMemberId(opponentMember);
|
||||||
|
}
|
||||||
|
|
||||||
private processStats(): void {
|
private processStats(): void {
|
||||||
const summary: Promise<CallStatsReportSummary>[] = [];
|
const summary: Promise<CallStatsReportSummary>[] = [];
|
||||||
this.gatherers.forEach((c) => {
|
this.gatherers.forEach((c) => {
|
||||||
|
@@ -28,10 +28,14 @@ export type TrackID = string;
|
|||||||
export type ByteSend = number;
|
export type ByteSend = number;
|
||||||
|
|
||||||
export interface ByteSentStatsReport extends Map<TrackID, ByteSend> {
|
export interface ByteSentStatsReport extends Map<TrackID, ByteSend> {
|
||||||
|
callId?: string;
|
||||||
|
opponentMemberId?: string;
|
||||||
// is a map: `local trackID` => byte send
|
// is a map: `local trackID` => byte send
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConnectionStatsReport {
|
export interface ConnectionStatsReport {
|
||||||
|
callId?: string;
|
||||||
|
opponentMemberId?: string;
|
||||||
bandwidth: ConnectionStatsBandwidth;
|
bandwidth: ConnectionStatsBandwidth;
|
||||||
bitrate: ConnectionStatsBitrate;
|
bitrate: ConnectionStatsBitrate;
|
||||||
packetLoss: PacketLoss;
|
packetLoss: PacketLoss;
|
||||||
|
Reference in New Issue
Block a user