move webrtc etc. events from groupCall to matrix.call span (#1080)

* add new linked span for connection stats

* move stats span under call span and add user attribute

* Update matrix-js-sdk
This commit is contained in:
Enrico Schwendig 2023-06-06 08:28:53 +02:00 committed by GitHub
parent b1a5417b63
commit f0a6f5919e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 184 additions and 150 deletions

View file

@ -53,7 +53,7 @@
"i18next-browser-languagedetector": "^6.1.8", "i18next-browser-languagedetector": "^6.1.8",
"i18next-http-backend": "^1.4.4", "i18next-http-backend": "^1.4.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#a7b1dcaf9514b2e424a387e266c6f383a5909927", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#e70a1a1effe59e6754f9a10cc2df8eef81638c7d",
"matrix-widget-api": "^1.3.1", "matrix-widget-api": "^1.3.1",
"mermaid": "^8.13.8", "mermaid": "^8.13.8",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",

View file

@ -333,22 +333,70 @@ export class OTelGroupCallMembership {
public onConnectionStatsReport( public onConnectionStatsReport(
statsReport: GroupCallStatsReport<ConnectionStatsReport> statsReport: GroupCallStatsReport<ConnectionStatsReport>
) { ) {
if (!ElementCallOpenTelemetry.instance) return; this.buildCallStatsSpan(
OTelStatsReportType.ConnectionReport,
const type = OTelStatsReportType.ConnectionReport; statsReport.report
const data = );
ObjectFlattener.flattenConnectionStatsReportObject(statsReport);
this.buildStatsEventSpan({ type, data });
} }
public onByteSentStatsReport( public onByteSentStatsReport(
statsReport: GroupCallStatsReport<ByteSentStatsReport> statsReport: GroupCallStatsReport<ByteSentStatsReport>
) { ) {
if (!ElementCallOpenTelemetry.instance) return; this.buildCallStatsSpan(
OTelStatsReportType.ByteSentReport,
statsReport.report
);
}
const type = OTelStatsReportType.ByteSentReport; public buildCallStatsSpan(
const data = ObjectFlattener.flattenByteSentStatsReportObject(statsReport); type: OTelStatsReportType,
this.buildStatsEventSpan({ type, data }); report: ByteSentStatsReport | ConnectionStatsReport
): void {
if (!ElementCallOpenTelemetry.instance) return;
let call: OTelCall | undefined;
const callId = report?.callId;
if (callId) {
call = this.callsByCallId.get(callId);
}
if (!call) {
this.callMembershipSpan?.addEvent(type + "_unknown_callid", {
"call.callId": callId,
"call.opponentMemberId": report.opponentMemberId
? report.opponentMemberId
: "unknown",
});
logger.error(`Received ${type} with unknown call ID: ${callId}`);
return;
}
const data = ObjectFlattener.flattenReportObject(type, report);
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
call.span
);
const options = {
links: [
{
context: call.span.spanContext(),
},
],
};
const span = ElementCallOpenTelemetry.instance.tracer.startSpan(
type,
options,
ctx
);
span.setAttribute("matrix.callId", callId);
span.setAttribute(
"matrix.opponentMemberId",
report.opponentMemberId ? report.opponentMemberId : "unknown"
);
span.addEvent("matrix.call.connection_stats_event", data);
span.end();
} }
public onSummaryStatsReport( public onSummaryStatsReport(
@ -381,45 +429,6 @@ export class OTelGroupCallMembership {
span.end(); span.end();
} }
} }
private buildStatsEventSpan(event: OTelStatsReportEvent): void {
// @ TODO: fix this - Because on multiple calls we receive multiple stats report spans.
// This could be break if stats arrived in same time from different call objects.
if (this.statsReportSpan.span === undefined && this.callMembershipSpan) {
const ctx = setSpan(
opentelemetry.context.active(),
this.callMembershipSpan
);
this.statsReportSpan.span =
ElementCallOpenTelemetry.instance?.tracer.startSpan(
"matrix.groupCallMembership.statsReport",
undefined,
ctx
);
if (this.statsReportSpan.span === undefined) {
return;
}
this.statsReportSpan.span.setAttribute(
"matrix.confId",
this.groupCall.groupCallId
);
this.statsReportSpan.span.setAttribute("matrix.userId", this.myUserId);
this.statsReportSpan.span.setAttribute(
"matrix.displayName",
this.myMember ? this.myMember.name : "unknown-name"
);
this.statsReportSpan.span.addEvent(event.type, event.data);
this.statsReportSpan.stats.push(event);
} else if (
this.statsReportSpan.span !== undefined &&
this.callMembershipSpan
) {
this.statsReportSpan.span.addEvent(event.type, event.data);
this.statsReportSpan.span.end();
this.statsReportSpan = { span: undefined, stats: [] };
}
}
} }
interface OTelStatsReportEvent { interface OTelStatsReportEvent {
@ -428,7 +437,7 @@ interface OTelStatsReportEvent {
} }
enum OTelStatsReportType { enum OTelStatsReportType {
ConnectionReport = "matrix.stats.connection", ConnectionReport = "matrix.call.stats.connection",
ByteSentReport = "matrix.stats.byteSent", ByteSentReport = "matrix.call.stats.byteSent",
SummaryReport = "matrix.stats.summary", SummaryReport = "matrix.stats.summary",
} }

View file

@ -23,16 +23,12 @@ import {
} from "matrix-js-sdk/src/webrtc/stats/statsReport"; } from "matrix-js-sdk/src/webrtc/stats/statsReport";
export class ObjectFlattener { export class ObjectFlattener {
public static flattenConnectionStatsReportObject( public static flattenReportObject(
statsReport: GroupCallStatsReport<ConnectionStatsReport> prefix: string,
report: ConnectionStatsReport | ByteSentStatsReport
): Attributes { ): Attributes {
const flatObject = {}; const flatObject = {};
ObjectFlattener.flattenObjectRecursive( ObjectFlattener.flattenObjectRecursive(report, flatObject, `${prefix}.`, 0);
statsReport.report,
flatObject,
"matrix.stats.conn.",
0
);
return flatObject; return flatObject;
} }

View file

@ -1,6 +1,7 @@
import { GroupCallStatsReport } from "matrix-js-sdk/src/webrtc/groupCall"; import { GroupCallStatsReport } from "matrix-js-sdk/src/webrtc/groupCall";
import { import {
AudioConcealment, AudioConcealment,
ByteSentStatsReport,
ConnectionStatsReport, ConnectionStatsReport,
} from "matrix-js-sdk/src/webrtc/stats/statsReport"; } from "matrix-js-sdk/src/webrtc/stats/statsReport";
import { ObjectFlattener } from "../../src/otel/ObjectFlattener"; import { ObjectFlattener } from "../../src/otel/ObjectFlattener";
@ -28,6 +29,8 @@ describe("ObjectFlattener", () => {
const statsReport: GroupCallStatsReport<ConnectionStatsReport> = { const statsReport: GroupCallStatsReport<ConnectionStatsReport> = {
report: { report: {
callId: "callId",
opponentMemberId: "opponentMemberId",
bandwidth: { upload: 426, download: 0 }, bandwidth: { upload: 426, download: 0 },
bitrate: { bitrate: {
upload: 426, upload: 426,
@ -116,21 +119,25 @@ describe("ObjectFlattener", () => {
ObjectFlattener.flattenObjectRecursive( ObjectFlattener.flattenObjectRecursive(
statsReport.report.resolution, statsReport.report.resolution,
flatObject, flatObject,
"matrix.stats.conn.resolution.", "matrix.call.stats.connection.resolution.",
0 0
); );
expect(flatObject).toEqual({ expect(flatObject).toEqual({
"matrix.stats.conn.resolution.local.LOCAL_AUDIO_TRACK_ID.height": -1, "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.height":
"matrix.stats.conn.resolution.local.LOCAL_AUDIO_TRACK_ID.width": -1, -1,
"matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.width":
-1,
"matrix.stats.conn.resolution.local.LOCAL_VIDEO_TRACK_ID.height": 460, "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.height": 460,
"matrix.stats.conn.resolution.local.LOCAL_VIDEO_TRACK_ID.width": 780, "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.width": 780,
"matrix.stats.conn.resolution.remote.REMOTE_AUDIO_TRACK_ID.height": -1, "matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.height":
"matrix.stats.conn.resolution.remote.REMOTE_AUDIO_TRACK_ID.width": -1, -1,
"matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.width":
-1,
"matrix.stats.conn.resolution.remote.REMOTE_VIDEO_TRACK_ID.height": 960, "matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.height": 960,
"matrix.stats.conn.resolution.remote.REMOTE_VIDEO_TRACK_ID.width": 1080, "matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.width": 1080,
}); });
}); });
it("should flatter an Array object", () => { it("should flatter an Array object", () => {
@ -138,106 +145,128 @@ describe("ObjectFlattener", () => {
ObjectFlattener.flattenObjectRecursive( ObjectFlattener.flattenObjectRecursive(
statsReport.report.transport, statsReport.report.transport,
flatObject, flatObject,
"matrix.stats.conn.transport.", "matrix.call.stats.connection.transport.",
0 0
); );
expect(flatObject).toEqual({ expect(flatObject).toEqual({
"matrix.stats.conn.transport.0.ip": "ff11::5fa:abcd:999c:c5c5:50000", "matrix.call.stats.connection.transport.0.ip":
"matrix.stats.conn.transport.0.type": "udp", "ff11::5fa:abcd:999c:c5c5:50000",
"matrix.stats.conn.transport.0.localIp": "matrix.call.stats.connection.transport.0.type": "udp",
"matrix.call.stats.connection.transport.0.localIp":
"2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000", "2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000",
"matrix.stats.conn.transport.0.isFocus": true, "matrix.call.stats.connection.transport.0.isFocus": true,
"matrix.stats.conn.transport.0.localCandidateType": "host", "matrix.call.stats.connection.transport.0.localCandidateType": "host",
"matrix.stats.conn.transport.0.remoteCandidateType": "host", "matrix.call.stats.connection.transport.0.remoteCandidateType": "host",
"matrix.stats.conn.transport.0.networkType": "ethernet", "matrix.call.stats.connection.transport.0.networkType": "ethernet",
"matrix.stats.conn.transport.0.rtt": "NaN", "matrix.call.stats.connection.transport.0.rtt": "NaN",
"matrix.stats.conn.transport.1.ip": "10.10.10.2:22222", "matrix.call.stats.connection.transport.1.ip": "10.10.10.2:22222",
"matrix.stats.conn.transport.1.type": "tcp", "matrix.call.stats.connection.transport.1.type": "tcp",
"matrix.stats.conn.transport.1.localIp": "10.10.10.100:33333", "matrix.call.stats.connection.transport.1.localIp":
"matrix.stats.conn.transport.1.isFocus": true, "10.10.10.100:33333",
"matrix.stats.conn.transport.1.localCandidateType": "srfx", "matrix.call.stats.connection.transport.1.isFocus": true,
"matrix.stats.conn.transport.1.remoteCandidateType": "srfx", "matrix.call.stats.connection.transport.1.localCandidateType": "srfx",
"matrix.stats.conn.transport.1.networkType": "ethernet", "matrix.call.stats.connection.transport.1.remoteCandidateType": "srfx",
"matrix.stats.conn.transport.1.rtt": "null", "matrix.call.stats.connection.transport.1.networkType": "ethernet",
"matrix.call.stats.connection.transport.1.rtt": "null",
}); });
}); });
}); });
describe("on flattenConnectionStatsReportObject", () => { describe("on flattenReportObject Connection Stats", () => {
it("should flatten a Report to otel Attributes Object", () => { it("should flatten a Report to otel Attributes Object", () => {
expect( expect(
ObjectFlattener.flattenConnectionStatsReportObject(statsReport) ObjectFlattener.flattenReportObject(
"matrix.call.stats.connection",
statsReport.report
)
).toEqual({ ).toEqual({
"matrix.stats.conn.bandwidth.download": 0, "matrix.call.stats.connection.callId": "callId",
"matrix.stats.conn.bandwidth.upload": 426, "matrix.call.stats.connection.opponentMemberId": "opponentMemberId",
"matrix.stats.conn.bitrate.audio.download": 0, "matrix.call.stats.connection.bandwidth.download": 0,
"matrix.stats.conn.bitrate.audio.upload": 124, "matrix.call.stats.connection.bandwidth.upload": 426,
"matrix.stats.conn.bitrate.download": 0, "matrix.call.stats.connection.bitrate.audio.download": 0,
"matrix.stats.conn.bitrate.upload": 426, "matrix.call.stats.connection.bitrate.audio.upload": 124,
"matrix.stats.conn.bitrate.video.download": 0, "matrix.call.stats.connection.bitrate.download": 0,
"matrix.stats.conn.bitrate.video.upload": 302, "matrix.call.stats.connection.bitrate.upload": 426,
"matrix.stats.conn.codec.local.LOCAL_AUDIO_TRACK_ID": "opus", "matrix.call.stats.connection.bitrate.video.download": 0,
"matrix.stats.conn.codec.local.LOCAL_VIDEO_TRACK_ID": "v8", "matrix.call.stats.connection.bitrate.video.upload": 302,
"matrix.stats.conn.codec.remote.REMOTE_AUDIO_TRACK_ID": "opus", "matrix.call.stats.connection.codec.local.LOCAL_AUDIO_TRACK_ID": "opus",
"matrix.stats.conn.codec.remote.REMOTE_VIDEO_TRACK_ID": "v9", "matrix.call.stats.connection.codec.local.LOCAL_VIDEO_TRACK_ID": "v8",
"matrix.stats.conn.framerate.local.LOCAL_AUDIO_TRACK_ID": 0, "matrix.call.stats.connection.codec.remote.REMOTE_AUDIO_TRACK_ID":
"matrix.stats.conn.framerate.local.LOCAL_VIDEO_TRACK_ID": 30, "opus",
"matrix.stats.conn.framerate.remote.REMOTE_AUDIO_TRACK_ID": 0, "matrix.call.stats.connection.codec.remote.REMOTE_VIDEO_TRACK_ID": "v9",
"matrix.stats.conn.framerate.remote.REMOTE_VIDEO_TRACK_ID": 60, "matrix.call.stats.connection.framerate.local.LOCAL_AUDIO_TRACK_ID": 0,
"matrix.stats.conn.jitter.REMOTE_AUDIO_TRACK_ID": 2, "matrix.call.stats.connection.framerate.local.LOCAL_VIDEO_TRACK_ID": 30,
"matrix.stats.conn.jitter.REMOTE_VIDEO_TRACK_ID": 50, "matrix.call.stats.connection.framerate.remote.REMOTE_AUDIO_TRACK_ID": 0,
"matrix.stats.conn.packetLoss.download": 0, "matrix.call.stats.connection.framerate.remote.REMOTE_VIDEO_TRACK_ID": 60,
"matrix.stats.conn.packetLoss.total": 0, "matrix.call.stats.connection.jitter.REMOTE_AUDIO_TRACK_ID": 2,
"matrix.stats.conn.packetLoss.upload": 0, "matrix.call.stats.connection.jitter.REMOTE_VIDEO_TRACK_ID": 50,
"matrix.stats.conn.resolution.local.LOCAL_AUDIO_TRACK_ID.height": -1, "matrix.call.stats.connection.packetLoss.download": 0,
"matrix.stats.conn.resolution.local.LOCAL_AUDIO_TRACK_ID.width": -1, "matrix.call.stats.connection.packetLoss.total": 0,
"matrix.stats.conn.resolution.local.LOCAL_VIDEO_TRACK_ID.height": 460, "matrix.call.stats.connection.packetLoss.upload": 0,
"matrix.stats.conn.resolution.local.LOCAL_VIDEO_TRACK_ID.width": 780, "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.height":
"matrix.stats.conn.resolution.remote.REMOTE_AUDIO_TRACK_ID.height": -1, -1,
"matrix.stats.conn.resolution.remote.REMOTE_AUDIO_TRACK_ID.width": -1, "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.width":
"matrix.stats.conn.resolution.remote.REMOTE_VIDEO_TRACK_ID.height": 960, -1,
"matrix.stats.conn.resolution.remote.REMOTE_VIDEO_TRACK_ID.width": 1080, "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.height": 460,
"matrix.stats.conn.transport.0.ip": "ff11::5fa:abcd:999c:c5c5:50000", "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.width": 780,
"matrix.stats.conn.transport.0.type": "udp", "matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.height":
"matrix.stats.conn.transport.0.localIp": -1,
"matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.width":
-1,
"matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.height": 960,
"matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.width": 1080,
"matrix.call.stats.connection.transport.0.ip":
"ff11::5fa:abcd:999c:c5c5:50000",
"matrix.call.stats.connection.transport.0.type": "udp",
"matrix.call.stats.connection.transport.0.localIp":
"2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000", "2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000",
"matrix.stats.conn.transport.0.isFocus": true, "matrix.call.stats.connection.transport.0.isFocus": true,
"matrix.stats.conn.transport.0.localCandidateType": "host", "matrix.call.stats.connection.transport.0.localCandidateType": "host",
"matrix.stats.conn.transport.0.remoteCandidateType": "host", "matrix.call.stats.connection.transport.0.remoteCandidateType": "host",
"matrix.stats.conn.transport.0.networkType": "ethernet", "matrix.call.stats.connection.transport.0.networkType": "ethernet",
"matrix.stats.conn.transport.0.rtt": "NaN", "matrix.call.stats.connection.transport.0.rtt": "NaN",
"matrix.stats.conn.transport.1.ip": "10.10.10.2:22222", "matrix.call.stats.connection.transport.1.ip": "10.10.10.2:22222",
"matrix.stats.conn.transport.1.type": "tcp", "matrix.call.stats.connection.transport.1.type": "tcp",
"matrix.stats.conn.transport.1.localIp": "10.10.10.100:33333", "matrix.call.stats.connection.transport.1.localIp":
"matrix.stats.conn.transport.1.isFocus": true, "10.10.10.100:33333",
"matrix.stats.conn.transport.1.localCandidateType": "srfx", "matrix.call.stats.connection.transport.1.isFocus": true,
"matrix.stats.conn.transport.1.remoteCandidateType": "srfx", "matrix.call.stats.connection.transport.1.localCandidateType": "srfx",
"matrix.stats.conn.transport.1.networkType": "ethernet", "matrix.call.stats.connection.transport.1.remoteCandidateType": "srfx",
"matrix.stats.conn.transport.1.rtt": "null", "matrix.call.stats.connection.transport.1.networkType": "ethernet",
"matrix.stats.conn.audioConcealment.REMOTE_AUDIO_TRACK_ID.concealedAudio": 0, "matrix.call.stats.connection.transport.1.rtt": "null",
"matrix.stats.conn.audioConcealment.REMOTE_AUDIO_TRACK_ID.totalAudioDuration": 0, "matrix.call.stats.connection.audioConcealment.REMOTE_AUDIO_TRACK_ID.concealedAudio": 0,
"matrix.stats.conn.audioConcealment.REMOTE_VIDEO_TRACK_ID.concealedAudio": 0, "matrix.call.stats.connection.audioConcealment.REMOTE_AUDIO_TRACK_ID.totalAudioDuration": 0,
"matrix.stats.conn.audioConcealment.REMOTE_VIDEO_TRACK_ID.totalAudioDuration": 0, "matrix.call.stats.connection.audioConcealment.REMOTE_VIDEO_TRACK_ID.concealedAudio": 0,
"matrix.stats.conn.totalAudioConcealment.concealedAudio": 0, "matrix.call.stats.connection.audioConcealment.REMOTE_VIDEO_TRACK_ID.totalAudioDuration": 0,
"matrix.stats.conn.totalAudioConcealment.totalAudioDuration": 0, "matrix.call.stats.connection.totalAudioConcealment.concealedAudio": 0,
"matrix.call.stats.connection.totalAudioConcealment.totalAudioDuration": 0,
}); });
}); });
}); });
describe("on flattenByteSendStatsReportObject", () => { describe("on flattenByteSendStatsReportObject", () => {
const byteSent = { const byteSentStatsReport = new Map<
report: new Map([ string,
["4aa92608-04c6-428e-8312-93e17602a959", 132093], number
["a08e4237-ee30-4015-a932-b676aec894b1", 913448], >() as ByteSentStatsReport;
]), byteSentStatsReport.callId = "callId";
}; byteSentStatsReport.opponentMemberId = "opponentMemberId";
byteSentStatsReport.set("4aa92608-04c6-428e-8312-93e17602a959", 132093);
byteSentStatsReport.set("a08e4237-ee30-4015-a932-b676aec894b1", 913448);
it("should flatten a Report to otel Attributes Object", () => { it("should flatten a Report to otel Attributes Object", () => {
expect( expect(
ObjectFlattener.flattenByteSentStatsReportObject(byteSent) ObjectFlattener.flattenReportObject(
"matrix.call.stats.bytesSend",
byteSentStatsReport
)
).toEqual({ ).toEqual({
"matrix.stats.bytesSent.4aa92608-04c6-428e-8312-93e17602a959": 132093, "matrix.call.stats.bytesSend.4aa92608-04c6-428e-8312-93e17602a959": 132093,
"matrix.stats.bytesSent.a08e4237-ee30-4015-a932-b676aec894b1": 913448, "matrix.call.stats.bytesSend.a08e4237-ee30-4015-a932-b676aec894b1": 913448,
}); });
expect(byteSentStatsReport.callId).toEqual("callId");
expect(byteSentStatsReport.opponentMemberId).toEqual("opponentMemberId");
}); });
}); });
}); });

View file

@ -10557,9 +10557,9 @@ matrix-events-sdk@0.0.1:
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd"
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#a7b1dcaf9514b2e424a387e266c6f383a5909927": "matrix-js-sdk@github:matrix-org/matrix-js-sdk#e70a1a1effe59e6754f9a10cc2df8eef81638c7d":
version "25.1.1" version "25.1.1"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/a7b1dcaf9514b2e424a387e266c6f383a5909927" resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/e70a1a1effe59e6754f9a10cc2df8eef81638c7d"
dependencies: dependencies:
"@babel/runtime" "^7.12.5" "@babel/runtime" "^7.12.5"
"@matrix-org/matrix-sdk-crypto-js" "^0.1.0-alpha.9" "@matrix-org/matrix-sdk-crypto-js" "^0.1.0-alpha.9"