This is send over zipkin. And it uses a posthog exporter to export events to posthog using a _otel prefix
129 lines
5.2 KiB
TypeScript
129 lines
5.2 KiB
TypeScript
/* document-load.ts|js file - the code is the same for both the languages */
|
|
import {
|
|
ConsoleSpanExporter,
|
|
SimpleSpanProcessor,
|
|
} from "@opentelemetry/sdk-trace-base";
|
|
import { ZipkinExporter } from "@opentelemetry/exporter-zipkin";
|
|
// import { JaegerExporter } from "@opentelemetry/exporter-jaeger";
|
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
|
|
import { ZoneContextManager } from "@opentelemetry/context-zone";
|
|
import { registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
import opentelemetry from "@opentelemetry/api";
|
|
import { Resource } from "@opentelemetry/resources";
|
|
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
|
|
|
|
import { PosthogSpanExporter } from "../analytics/OtelPosthogExporter";
|
|
|
|
const SERVICE_NAME = "element-call";
|
|
// It is really important to set the correct content type here. Otherwise the Jaeger will crash and not accept the zipkin event
|
|
// Additionally jaeger needs to be started with zipkin on port 9411
|
|
const optionsZipkin = {
|
|
// url: `http://localhost:9411/api/v2/spans`,
|
|
// serviceName: SERVICE_NAME,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
};
|
|
// We DO NOT use the OTLPTraceExporter. This somehow does not hit the right endpoint and also causes issues with CORS
|
|
const collectorOptions = {
|
|
// url: `http://localhost:14268/api/v2/spans`, // url is optional and can be omitted - default is http://localhost:4318/v1/traces
|
|
headers: { "Access-Control-Allow-Origin": "*" }, // an optional object containing custom headers to be sent with each request
|
|
concurrencyLimit: 10, // an optional limit on pending requests
|
|
};
|
|
const otlpExporter = new OTLPTraceExporter(collectorOptions);
|
|
const consoleExporter = new ConsoleSpanExporter();
|
|
// The zipkin exporter is the actual exporter we need for web based otel applications
|
|
const zipkin = new ZipkinExporter(optionsZipkin);
|
|
const posthogExporter = new PosthogSpanExporter();
|
|
|
|
// This is how we can make Jaeger show a reaonsable service in the dropdown on the left.
|
|
const providerConfig = {
|
|
resource: new Resource({
|
|
[SemanticResourceAttributes.SERVICE_NAME]: SERVICE_NAME,
|
|
}),
|
|
};
|
|
const provider = new WebTracerProvider(providerConfig);
|
|
|
|
provider.addSpanProcessor(new SimpleSpanProcessor(otlpExporter));
|
|
// We can add as many processors and exporters as we want to. The zipkin one is the important one for Jaeger
|
|
provider.addSpanProcessor(new SimpleSpanProcessor(posthogExporter));
|
|
provider.addSpanProcessor(new SimpleSpanProcessor(consoleExporter));
|
|
provider.addSpanProcessor(new SimpleSpanProcessor(zipkin));
|
|
|
|
// This is unecassary i think...
|
|
provider.register({
|
|
// Changing default contextManager to use ZoneContextManager - supports asynchronous operations - optional
|
|
contextManager: new ZoneContextManager(),
|
|
});
|
|
|
|
// Registering instrumentations (These are automated span collectors for the Http request during page loading, switching)
|
|
registerInstrumentations({
|
|
instrumentations: [
|
|
// new DocumentLoadInstrumentation(),
|
|
// new UserInteractionInstrumentation(),
|
|
],
|
|
});
|
|
|
|
// This is not the serviceName shown in jaeger
|
|
export const tracer = opentelemetry.trace.getTracer(
|
|
"my-element-call-otl-tracer"
|
|
);
|
|
|
|
class CallTracer {
|
|
// We create one tracer class for each main context.
|
|
// Even if differnt tracer classes overlap in time space, we might want to visulaize them seperately.
|
|
// The Call Tracer should only contain spans/events that are relevant to understand the procedure of the individual candidates.
|
|
// Another Tracer Class (for example a ConnectionTracer) can contain a very granular list of all steps to connect to a call.
|
|
|
|
private callSpan;
|
|
private callContext;
|
|
private muteSpan?;
|
|
public startCall(callId: string) {
|
|
// The main context will be set when initiating the main/parent span.
|
|
|
|
// Create an initial context with the callId param
|
|
const callIdContext = opentelemetry.context
|
|
.active()
|
|
.setValue(Symbol("callId"), callId);
|
|
|
|
// Create the main span that tracks the whole call
|
|
this.callSpan = tracer.startSpan("otel_callSpan", undefined, callIdContext);
|
|
|
|
// Create a new call based on the callIdContext. This context also has a span assigned to it.
|
|
// Other spans can use this context to extract the parent span.
|
|
// (When passing this context to startSpan the started span will use the span set in the context (in this case the callSpan) as the parent)
|
|
this.callContext = opentelemetry.trace.setSpan(
|
|
opentelemetry.context.active(),
|
|
this.callSpan
|
|
);
|
|
|
|
// 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 startCallSpan = tracer.startSpan(
|
|
"otel_startCallSpan",
|
|
undefined,
|
|
this.callContext
|
|
);
|
|
startCallSpan.end();
|
|
}
|
|
public muteMic(muteState: boolean) {
|
|
if (muteState) {
|
|
this.muteSpan = tracer.startSpan(
|
|
"otel_muteSpan",
|
|
undefined,
|
|
this.callContext
|
|
);
|
|
} else if (this.muteSpan) {
|
|
this.muteSpan.end();
|
|
this.muteSpan = null;
|
|
}
|
|
}
|
|
public endCall() {
|
|
this.callSpan?.end();
|
|
}
|
|
}
|
|
|
|
export const callTracer = new CallTracer();
|