Add CORS to jaeger query endpoint and make spans nested

Adds an nginx in front of the query endpoint so we can use stalk
without faffing with browser extension to bypass CORS.

Also make the spans correctly have the call membership span as parent,
which they didn't because we hadn't set the span at the point we made
the context.
This commit is contained in:
David Baker 2023-03-17 17:01:59 +00:00
parent 521b0a857a
commit f8f5d2011d
3 changed files with 35 additions and 15 deletions

View file

@ -6,4 +6,13 @@ traces into the jaeger. Jaeger has a built-in OpenTelemetry collector, but it ca
configured to send CORS headers so can't be used from a browser. This sets the config on
the collector to send CORS headers.
This also adds an nginx to add CORS headers to the jaeger query endpoint, such that it can
be used from webapps like stalk (https://deniz.co/stalk/). The CORS enabled endpoint is
exposed on port 16687. To use stalk, you should simply be able to navigate to it and add
http://127.0.0.1:16687/api as a data source.
(Yes, we could enable the OTLP collector in jaeger all-in-one and passed this through
the nginx to enable CORS too, rather than running a separate collector. There's no reason
it's done this way other than that I'd already set up the separate collector.)
Running `docker compose up` in this directory should be all you need.

View file

@ -21,3 +21,9 @@ services:
- "55670:55679" # zpages extension
depends_on:
- jaeger-all-in-one
nginx:
image: nginxinc/nginx-unprivileged:latest
volumes:
- ./nginx_otel.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "16687:8080"

View file

@ -15,7 +15,12 @@ limitations under the License.
*/
import opentelemetry, { Context, Span } from "@opentelemetry/api";
import { GroupCall, MatrixClient, MatrixEvent } from "matrix-js-sdk";
import {
GroupCall,
MatrixClient,
MatrixEvent,
RoomMember,
} from "matrix-js-sdk";
import { VoipEvent } from "matrix-js-sdk/src/webrtc/call";
import { tracer } from "./otel";
@ -63,27 +68,27 @@ function setSpanEventAttributesRecursive(
export class OTelGroupCallMembership {
private context: Context;
private callMembershipSpan: Span;
private myUserId: string;
private myMember: RoomMember;
constructor(groupCall: GroupCall, client: MatrixClient) {
constructor(private groupCall: GroupCall, client: MatrixClient) {
this.myUserId = client.getUserId();
this.myMember = groupCall.room.getMember(client.getUserId());
}
public onJoinCall() {
// 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)
const myMember = groupCall.room.getMember(client.getUserId());
// Create the main span that tracks the time we intend to be in the call
this.callMembershipSpan = tracer.startSpan("otel_groupCallMembershipSpan");
this.context = opentelemetry.trace
.setSpan(opentelemetry.context.active(), this.callMembershipSpan)
.setValue(Symbol("confId"), groupCall.groupCallId)
.setValue(Symbol("matrix.userId"), client.getUserId())
.setValue(Symbol("matrix.displayName"), myMember.name);
}
public onJoinCall() {
// Create the main span that tracks the time we intend to be in the call
this.callMembershipSpan = tracer.startSpan(
"otel_groupCallMembershipSpan",
undefined,
this.context
);
.setValue(Symbol("confId"), this.groupCall.groupCallId)
.setValue(Symbol("matrix.userId"), this.myUserId)
.setValue(Symbol("matrix.displayName"), this.myMember.name);
// Here we start a very short span. This is a hack to trigger the posthog exporter.
// Only ended spans are processed by the exporter.