diff --git a/src/otel/OTelGroupCallMembership.ts b/src/otel/OTelGroupCallMembership.ts index ba06090f..a4e3bfb1 100644 --- a/src/otel/OTelGroupCallMembership.ts +++ b/src/otel/OTelGroupCallMembership.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import opentelemetry, { Context, Span } from "@opentelemetry/api"; +import opentelemetry, { Span, Attributes } from "@opentelemetry/api"; import { GroupCall, MatrixClient, @@ -26,20 +26,25 @@ import { VoipEvent } from "matrix-js-sdk/src/webrtc/call"; import { tracer } from "./otel"; /** - * Recursively sets the contents of a todevice event object as attributes on a span + * Flattens out an object into a single layer with components + * of the key separated by dots */ -function setNestedAttributesFromEvent(span: Span, event: VoipEvent) { - setSpanEventAttributesRecursive( - span, +function flattenVoipEvent(event: VoipEvent): Attributes { + const flatObject = {}; + + flattenVoipEventRecursive( event as unknown as Record, // XXX Types + flatObject, "matrix.event.", 0 ); + + return flatObject; } -function setSpanEventAttributesRecursive( - span: Span, +function flattenVoipEventRecursive( obj: Record, + flatObject: Record, prefix: string, depth: number ) { @@ -50,11 +55,11 @@ function setSpanEventAttributesRecursive( for (const [k, v] of Object.entries(obj)) { if (["string", "number"].includes(typeof v)) { - span.setAttribute(prefix + k, v as string | number); + flatObject[prefix + k] = v; } else if (typeof v === "object") { - setSpanEventAttributesRecursive( - span, + flattenVoipEventRecursive( v as Record, + flatObject, prefix + k + ".", depth + 1 ); @@ -66,7 +71,6 @@ function setSpanEventAttributesRecursive( * Represent the span of time which we intend to be joined to a group call */ export class OTelGroupCallMembership { - private context: Context; private callMembershipSpan: Span; private myUserId: string; private myMember: RoomMember; @@ -83,7 +87,6 @@ export class OTelGroupCallMembership { // Create the main span that tracks the time we intend to be in the call this.callMembershipSpan = tracer.startSpan("otel_groupCallMembershipSpan"); - this.callMembershipSpan.setAttribute( "matrix.confId", this.groupCall.groupCallId @@ -94,30 +97,16 @@ export class OTelGroupCallMembership { this.myMember.name ); - this.context = opentelemetry.trace.setSpan( + opentelemetry.trace.setSpan( opentelemetry.context.active(), this.callMembershipSpan ); - // Here we start a very short span. This is a hack to trigger the posthog exporter. - // Only ended spans are processed by the exporter. - // We want the exporter to know that a call has started - const joinCallSpan = tracer.startSpan( - "otel_joinCallSpan", - undefined, - this.context - ); - joinCallSpan.end(); + this.callMembershipSpan.addEvent("matrix.joinCall"); } public onLeaveCall() { - // A very short span to represent us leaving the call - const startCallSpan = tracer.startSpan( - "otel_leaveCallSpan", - undefined, - this.context - ); - startCallSpan.end(); + this.callMembershipSpan.addEvent("matrix.leaveCall"); // and end the main span to indicate we've left if (this.callMembershipSpan) this.callMembershipSpan.end(); @@ -128,17 +117,14 @@ export class OTelGroupCallMembership { !event || (!event.getType().startsWith("m.call") && !event.getType().startsWith("org.matrix.msc3401.call")) - ) + ) { return; + } - const span = tracer.startSpan( + this.callMembershipSpan.addEvent( `otel_onRoomStateEvent_${event.getType()}`, - undefined, - this.context + flattenVoipEvent(event.getContent()) ); - - setNestedAttributesFromEvent(span, event.getContent()); - span.end(); } public onSendEvent(event: VoipEvent) { @@ -146,23 +132,15 @@ export class OTelGroupCallMembership { if (!eventType.startsWith("m.call")) return; if (event.type === "toDevice") { - const span = tracer.startSpan( - `otel_sendToDeviceEvent_${event.eventType}`, - undefined, - this.context + this.callMembershipSpan.addEvent( + `matrix.sendToDeviceEvent_${event.eventType}`, + flattenVoipEvent(event) ); - - setNestedAttributesFromEvent(span, event); - span.end(); } else if (event.type === "sendEvent") { - const span = tracer.startSpan( - `otel_sendToRoomEvent_${event.eventType}`, - undefined, - this.context + this.callMembershipSpan.addEvent( + `matrix.sendToRoomEvent_${event.eventType}`, + flattenVoipEvent(event) ); - - setNestedAttributesFromEvent(span, event); - span.end(); } } }