Version using events for call joins / leaves and matrix events

This is probably conceptually nicer although isn't quite as nice in
the jaeger / stalk UI.

Also this may no loger work with the posthog exporter (unsure what it
will do with events on spans).
This commit is contained in:
David Baker 2023-03-17 19:26:23 +00:00
parent 2d91b43a7d
commit 63ede0b51a

View file

@ -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<string, unknown>, // XXX Types
flatObject,
"matrix.event.",
0
);
return flatObject;
}
function setSpanEventAttributesRecursive(
span: Span,
function flattenVoipEventRecursive(
obj: Record<string, unknown>,
flatObject: Record<string, unknown>,
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<string, unknown>,
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();
}
}
}