UNPKG

@vtex/api

Version:
112 lines (111 loc) 6.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.traceUserLandRemainingPipelineMiddleware = exports.nameSpanOperationMiddleware = exports.addTracingMiddleware = void 0; const opentracing_1 = require("opentracing"); const stream_1 = require("stream"); const constants_1 = require("../../constants"); const tracing_1 = require("../../tracing"); const Tags_1 = require("../../tracing/Tags"); const utils_1 = require("../../tracing/utils"); const utils_2 = require("../../utils"); const PATHS_BLACKLISTED_FOR_TRACING = ['/_status', '/healthcheck']; const addTracingMiddleware = (tracer) => { return async function addTracing(ctx, next) { var _a; const rootSpan = tracer.extract(opentracing_1.FORMAT_HTTP_HEADERS, ctx.request.headers); ctx.tracing = { tracer, currentSpan: undefined }; if (!shouldTrace(ctx, rootSpan)) { await next(); return; } const currentSpan = tracer.startSpan('unknown-operation', { childOf: rootSpan, tags: { [Tags_1.OpentracingTags.SPAN_KIND]: Tags_1.OpentracingTags.SPAN_KIND_RPC_SERVER }, }); const initialSamplingDecision = (0, tracing_1.getTraceInfo)(currentSpan).isSampled; ctx.tracing = { currentSpan, tracer }; let responseClosed = false; ctx.res.once('close', () => (responseClosed = true)); try { await next(); } catch (err) { tracing_1.ErrorReport.create({ originalError: err }).injectOnSpan(currentSpan, (_a = ctx.vtex) === null || _a === void 0 ? void 0 : _a.logger); throw err; } finally { const traceInfo = (0, tracing_1.getTraceInfo)(currentSpan); if (traceInfo === null || traceInfo === void 0 ? void 0 : traceInfo.isSampled) { if (!initialSamplingDecision) { currentSpan === null || currentSpan === void 0 ? void 0 : currentSpan.setTag(Tags_1.OpentracingTags.SPAN_KIND, Tags_1.OpentracingTags.SPAN_KIND_RPC_SERVER); } currentSpan === null || currentSpan === void 0 ? void 0 : currentSpan.addTags({ [Tags_1.OpentracingTags.HTTP_URL]: ctx.request.href, [Tags_1.OpentracingTags.HTTP_METHOD]: ctx.request.method, [Tags_1.OpentracingTags.HTTP_STATUS_CODE]: ctx.response.status, ["http.path" /* CustomHttpTags.HTTP_PATH */]: ctx.request.path, ["vtex.request_id" /* VTEXIncomingRequestTags.VTEX_REQUEST_ID */]: ctx.get(constants_1.REQUEST_ID_HEADER), ["vtex.incoming.workspace" /* VTEXIncomingRequestTags.VTEX_WORKSPACE */]: ctx.get(constants_1.WORKSPACE_HEADER), ["vtex.incoming.account" /* VTEXIncomingRequestTags.VTEX_ACCOUNT */]: ctx.get(constants_1.ACCOUNT_HEADER), }); currentSpan === null || currentSpan === void 0 ? void 0 : currentSpan.log((0, utils_1.cloneAndSanitizeHeaders)(ctx.request.headers, 'req.headers.')); currentSpan === null || currentSpan === void 0 ? void 0 : currentSpan.log((0, utils_1.cloneAndSanitizeHeaders)(ctx.response.headers, 'res.headers.')); ctx.set(constants_1.TRACE_ID_HEADER, traceInfo.traceId); } const onResFinished = () => { currentSpan === null || currentSpan === void 0 ? void 0 : currentSpan.finish(); }; if (responseClosed) { onResFinished(); } else { (0, stream_1.finished)(ctx.res, onResFinished); } } }; }; exports.addTracingMiddleware = addTracingMiddleware; const nameSpanOperationMiddleware = (operationType, operationName) => { return function nameSpanOperation(ctx, next) { var _a, _b; ctx.requestHandlerName = `${operationType}:${operationName}`; (_b = (_a = ctx.tracing) === null || _a === void 0 ? void 0 : _a.currentSpan) === null || _b === void 0 ? void 0 : _b.setOperationName(ctx.requestHandlerName); return next(); }; }; exports.nameSpanOperationMiddleware = nameSpanOperationMiddleware; const traceUserLandRemainingPipelineMiddleware = () => { return async function traceUserLandRemainingPipeline(ctx, next) { const tracingCtx = ctx.tracing; ctx.tracing = undefined; const span = tracingCtx === null || tracingCtx === void 0 ? void 0 : tracingCtx.currentSpan; const userLandTracer = ctx.vtex.tracer; userLandTracer.setFallbackSpan(span); userLandTracer.lockFallbackSpan(); const startTime = process.hrtime(); try { span === null || span === void 0 ? void 0 : span.log({ event: "user-middlewares-start" /* RuntimeLogEvents.USER_MIDDLEWARES_START */ }); await next(); } catch (err) { tracing_1.ErrorReport.create({ originalError: err }).injectOnSpan(span, ctx.vtex.logger); throw err; } finally { span === null || span === void 0 ? void 0 : span.log({ event: "user-middlewares-finish" /* RuntimeLogEvents.USER_MIDDLEWARES_FINISH */, ["user-middlewares-duration" /* RuntimeLogFields.USER_MIDDLEWARES_DURATION */]: (0, utils_2.hrToMillis)(process.hrtime(startTime)), }); ctx.tracing = tracingCtx; } }; }; exports.traceUserLandRemainingPipelineMiddleware = traceUserLandRemainingPipelineMiddleware; function shouldTrace(ctx, rootSpan) { var _a, _b, _c; /** Should trace if path isnt blacklisted and sampling decision came from the edge * ((rootSpan as any).isSampled. returns whether or not this span context was sampled * There is a cast to bypass opentracing typescript */ return !PATHS_BLACKLISTED_FOR_TRACING.includes(ctx.request.path) && ((_c = (_b = (_a = rootSpan).isSampled) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : false); }