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:
		
					parent
					
						
							
								2d91b43a7d
							
						
					
				
			
			
				commit
				
					
						63ede0b51a
					
				
			
		
					 1 changed files with 28 additions and 50 deletions
				
			
		| 
						 | 
				
			
			@ -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();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue