Include unended spans in rageshakes

By turning the RageshakeSpanExporter into a SpanProcessor, it can now be notified of spans as soon as they're started.
This commit is contained in:
Robin Townsend 2023-04-12 17:07:18 -04:00
parent d211d27817
commit a17ffcc327
3 changed files with 26 additions and 22 deletions

View file

@ -1,10 +1,10 @@
import { Attributes } from "@opentelemetry/api"; import { Attributes } from "@opentelemetry/api";
import { hrTimeToMilliseconds } from "@opentelemetry/core";
import { import {
ExportResult, SpanProcessor,
ExportResultCode, ReadableSpan,
hrTimeToMilliseconds, Span,
} from "@opentelemetry/core"; } from "@opentelemetry/sdk-trace-base";
import { SpanExporter, ReadableSpan } from "@opentelemetry/sdk-trace-base";
const dumpAttributes = (attr: Attributes) => const dumpAttributes = (attr: Attributes) =>
Object.entries(attr).map(([key, value]) => ({ Object.entries(attr).map(([key, value]) => ({
@ -17,21 +17,22 @@ const dumpAttributes = (attr: Attributes) =>
* Exports spans on demand to the Jaeger JSON format, which can be attached to * Exports spans on demand to the Jaeger JSON format, which can be attached to
* rageshakes and loaded into analysis tools like Jaeger and Stalk. * rageshakes and loaded into analysis tools like Jaeger and Stalk.
*/ */
export class RageshakeSpanExporter implements SpanExporter { export class RageshakeSpanProcessor implements SpanProcessor {
private readonly spans: ReadableSpan[] = []; private readonly spans: ReadableSpan[] = [];
export( async forceFlush(): Promise<void> {}
spans: ReadableSpan[],
resultCallback: (result: ExportResult) => void onStart(span: Span): void {
): void { this.spans.push(span);
this.spans.push(...spans);
resultCallback({ code: ExportResultCode.SUCCESS });
} }
onEnd(): void {}
/** /**
* Dumps the spans collected so far as Jaeger-compatible JSON. * Dumps the spans collected so far as Jaeger-compatible JSON.
*/ */
public dump(): string { public dump(): string {
const now = Date.now();
const traces = new Map<string, ReadableSpan[]>(); const traces = new Map<string, ReadableSpan[]>();
// Organize spans by their trace IDs // Organize spans by their trace IDs
@ -69,6 +70,12 @@ export class RageshakeSpanExporter implements SpanExporter {
processes, processes,
spans: spans.map((span) => { spans: spans.map((span) => {
const ctx = span.spanContext(); const ctx = span.spanContext();
const startTime = hrTimeToMilliseconds(span.startTime);
// If the span has not yet ended, pretend that it ends now
const duration =
span.duration[0] === -1
? now - startTime
: hrTimeToMilliseconds(span.duration);
return { return {
traceID: traceId, traceID: traceId,
@ -76,8 +83,8 @@ export class RageshakeSpanExporter implements SpanExporter {
operationName: span.name, operationName: span.name,
processID: processId, processID: processId,
warnings: null, warnings: null,
startTime: hrTimeToMilliseconds(span.startTime), startTime,
duration: hrTimeToMilliseconds(span.duration), duration,
references: references:
span.parentSpanId === undefined span.parentSpanId === undefined
? [] ? []

View file

@ -28,7 +28,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { PosthogSpanExporter } from "../analytics/OtelPosthogExporter"; import { PosthogSpanExporter } from "../analytics/OtelPosthogExporter";
import { Anonymity } from "../analytics/PosthogAnalytics"; import { Anonymity } from "../analytics/PosthogAnalytics";
import { Config } from "../config/Config"; import { Config } from "../config/Config";
import { RageshakeSpanExporter } from "../analytics/RageshakeSpanExporter"; import { RageshakeSpanProcessor } from "../analytics/RageshakeSpanProcessor";
const SERVICE_NAME = "element-call"; const SERVICE_NAME = "element-call";
@ -39,7 +39,7 @@ export class ElementCallOpenTelemetry {
private _tracer: Tracer; private _tracer: Tracer;
private _anonymity: Anonymity; private _anonymity: Anonymity;
private otlpExporter: OTLPTraceExporter; private otlpExporter: OTLPTraceExporter;
public readonly rageshakeExporter?: RageshakeSpanExporter; public readonly rageshakeProcessor?: RageshakeSpanProcessor;
static globalInit(): void { static globalInit(): void {
const config = Config.get(); const config = Config.get();
@ -89,11 +89,8 @@ export class ElementCallOpenTelemetry {
} }
if (rageshakeUrl) { if (rageshakeUrl) {
logger.info("Enabling rageshake collector"); this.rageshakeProcessor = new RageshakeSpanProcessor();
this.rageshakeExporter = new RageshakeSpanExporter(); this._provider.addSpanProcessor(this.rageshakeProcessor);
this._provider.addSpanProcessor(
new SimpleSpanProcessor(this.rageshakeExporter)
);
} }
const consoleExporter = new ConsoleSpanExporter(); const consoleExporter = new ConsoleSpanExporter();

View file

@ -248,7 +248,7 @@ export function useSubmitRageshake(): {
body.append( body.append(
"file", "file",
gzip(ElementCallOpenTelemetry.instance.rageshakeExporter!.dump()), gzip(ElementCallOpenTelemetry.instance.rageshakeProcessor!.dump()),
"traces.json" "traces.json"
); );