Files
element-call/src/otel/ObjectFlattener.ts

101 lines
2.7 KiB
TypeScript
Raw Normal View History

/*
Copyright 2023, 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type Attributes } from "@opentelemetry/api";
2025-03-13 16:58:14 +01:00
import { type VoipEvent } from "matrix-js-sdk/lib/webrtc/call";
import { type GroupCallStatsReport } from "matrix-js-sdk/lib/webrtc/groupCall";
import {
type ByteSentStatsReport,
type ConnectionStatsReport,
type SummaryStatsReport,
2025-03-13 16:58:14 +01:00
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
export class ObjectFlattener {
public static flattenReportObject(
prefix: string,
2023-10-11 10:42:04 -04:00
report: ConnectionStatsReport | ByteSentStatsReport,
): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(report, flatObject, `${prefix}.`, 0);
return flatObject;
}
public static flattenByteSentStatsReportObject(
2023-10-11 10:42:04 -04:00
statsReport: GroupCallStatsReport<ByteSentStatsReport>,
): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(
statsReport.report,
flatObject,
"matrix.stats.bytesSent.",
2023-10-11 10:42:04 -04:00
0,
);
return flatObject;
}
public static flattenSummaryStatsReportObject(
2023-10-11 10:42:04 -04:00
statsReport: GroupCallStatsReport<SummaryStatsReport>,
): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(
statsReport.report,
flatObject,
"matrix.stats.summary.",
2023-10-11 10:42:04 -04:00
0,
);
return flatObject;
}
2023-04-27 14:00:27 +02:00
/* Flattens out an object into a single layer with components
* of the key separated by dots
*/
public static flattenVoipEvent(event: VoipEvent): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(
event as unknown as Record<string, unknown>, // XXX Types
flatObject,
"matrix.event.",
2023-10-11 10:42:04 -04:00
0,
2023-04-27 14:00:27 +02:00
);
return flatObject;
}
public static flattenObjectRecursive(
obj: object,
flatObject: Attributes,
prefix: string,
2023-10-11 10:42:04 -04:00
depth: number,
): void {
if (depth > 10)
throw new Error(
"Depth limit exceeded: aborting VoipEvent recursion. Prefix is " +
2023-10-11 10:42:04 -04:00
prefix,
);
let entries;
if (obj instanceof Map) {
entries = obj.entries();
} else {
entries = Object.entries(obj);
}
for (const [k, v] of entries) {
if (["string", "number", "boolean"].includes(typeof v) || v === null) {
let value;
value = v === null ? "null" : v;
value = typeof v === "number" && Number.isNaN(v) ? "NaN" : value;
flatObject[prefix + k] = value;
} else if (typeof v === "object") {
ObjectFlattener.flattenObjectRecursive(
v,
flatObject,
prefix + k + ".",
2023-10-11 10:42:04 -04:00
depth + 1,
);
}
}
}
}