diff --git a/app/client/packages/rts/src/controllers/Dsl/DslController.ts b/app/client/packages/rts/src/controllers/Dsl/DslController.ts index 7f0f062d475d..5a6ec060cc7b 100644 --- a/app/client/packages/rts/src/controllers/Dsl/DslController.ts +++ b/app/client/packages/rts/src/controllers/Dsl/DslController.ts @@ -2,6 +2,7 @@ import type { Response, Request } from "express"; import BaseController from "@controllers/BaseController"; import { latestDSLVersion, migrateDSLToLatest } from "@services/DslService"; import { StatusCodes } from "http-status-codes"; +import { startSpan, endSpan } from "../../utils/tracing"; export default class DSLController extends BaseController { constructor() { @@ -9,11 +10,15 @@ export default class DSLController extends BaseController { } async migrateDSL(req: Request, res: Response) { + const span = startSpan("dsl-migration"); + try { const latestDSL = await migrateDSLToLatest(req.body); super.sendResponse(res, latestDSL); } catch (err) { + endSpan(span, err); + return super.sendError( res, this.serverErrorMessage, @@ -21,12 +26,19 @@ export default class DSLController extends BaseController { StatusCodes.INTERNAL_SERVER_ERROR, ); } + endSpan(span); } getLatestDSLVersion(req: Request, res: Response) { + const span = startSpan("get-latest-dsl-version"); + const childSpan = startSpan("version-check", {}, span); + try { super.sendResponse(res, { version: latestDSLVersion }); } catch (err) { + endSpan(childSpan, err); + endSpan(span, err); + return super.sendError( res, this.serverErrorMessage, @@ -34,5 +46,7 @@ export default class DSLController extends BaseController { StatusCodes.INTERNAL_SERVER_ERROR, ); } + endSpan(childSpan); + endSpan(span); } } diff --git a/app/client/packages/rts/src/utils/tracing.ts b/app/client/packages/rts/src/utils/tracing.ts new file mode 100644 index 000000000000..c77ab0ceb39a --- /dev/null +++ b/app/client/packages/rts/src/utils/tracing.ts @@ -0,0 +1,46 @@ +import { trace, context, SpanStatusCode } from "@opentelemetry/api"; +import type { Span } from "@opentelemetry/api"; + +const tracer = trace.getTracer("rts-tracer"); + +/** + * Creates and starts a span. If parentSpan is provided, creates a child span. + * @param name Name of the operation to trace + * @param attributes Optional attributes for the span + * @param parentSpan Optional parent span to create child span + * @returns Span object that must be ended when operation completes + */ +export function startSpan( + name: string, + attributes?: Record, + parentSpan?: Span, +): Span { + const ctx = parentSpan + ? trace.setSpan(context.active(), parentSpan) + : undefined; + const span = tracer.startSpan(name, {}, ctx); + + if (attributes) { + Object.entries(attributes).forEach(([key, value]) => { + span.setAttribute(key, value); + }); + } + + return span; +} + +/** + * Ends a span and sets error status if error is provided + * @param span Span to end + * @param error Optional error to set on span + */ +export function endSpan(span: Span, error?: Error): void { + if (error) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error.message, + }); + } + + span.end(); +}