UNPKG

@cerbos/opentelemetry

Version:

OpenTelemetry instrumentation for the @cerbos/grpc and @cerbos/http client libraries

117 lines 4.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Transport = void 0; const api_1 = require("@opentelemetry/api"); const incubating_1 = require("@opentelemetry/semantic-conventions/incubating"); const core_1 = require("@cerbos/core"); const serviceNames = { admin: "cerbos.svc.v1.CerbosAdminService", cerbos: "cerbos.svc.v1.CerbosService", health: "grpc.health.v1.Health", }; class Transport { instrumentation; transport; constructor(instrumentation, transport) { this.instrumentation = instrumentation; this.transport = { unary: transport.unary.bind(transport), serverStream: transport.serverStream.bind(transport), }; } async unary(service, method, request, headers, abortHandler) { const call = this.call(service, "unary", method, request, headers, abortHandler); try { const response = await call.result; call.succeeded(); return response; } catch (error) { call.failed(error); throw error; } } async *serverStream(service, method, request, headers, abortHandler) { const call = this.call(service, "serverStream", method, request, headers, abortHandler); let done = false; try { yield* call.result; done = true; call.succeeded(); } catch (error) { done = true; call.failed(error); throw error; } finally { if (!done) { call.failed(abortHandler.error()); } } } call(service, methodKind, method, request, headers, abortHandler) { const startTime = performance.now(); const serviceName = serviceNames[service]; const methodName = `${method.charAt(0).toUpperCase()}${method.slice(1)}`; const status = { code: api_1.SpanStatusCode.UNSET }; const attributes = { [incubating_1.ATTR_RPC_SYSTEM]: "grpc", [incubating_1.ATTR_RPC_SERVICE]: serviceName, [incubating_1.ATTR_RPC_METHOD]: methodName, }; const span = this.tracer.startSpan(`${serviceName}/${methodName}`, { kind: api_1.SpanKind.CLIENT, startTime, }); const activeContext = api_1.trace.setSpan(api_1.context.active(), span); api_1.propagation.inject(activeContext, headers, { set(carrier, key, value) { carrier.set(key, value); }, }); const finish = () => { const endTime = performance.now(); span.setStatus(status); span.setAttributes(attributes); span.end(endTime); this.instruments.duration.record(endTime - startTime, attributes); }; const call = { succeeded: () => { attributes[incubating_1.ATTR_RPC_GRPC_STATUS_CODE] = core_1.Status.OK; finish(); }, failed: (error) => { status.code = api_1.SpanStatusCode.ERROR; if (error instanceof Error) { status.message = error.message; attributes["cerbos.error"] = error.message; if (error instanceof core_1.NotOK) { attributes[incubating_1.ATTR_RPC_GRPC_STATUS_CODE] = error.code; } } finish(); }, }; const transport = this.transport[methodKind]; try { return { result: api_1.context.with(activeContext, transport, undefined, service, method, request, headers, abortHandler), ...call, }; } catch (error) { call.failed(error); throw error; } } get instruments() { return this.instrumentation._instruments; } get tracer() { return this.instrumentation._tracer; } } exports.Transport = Transport; //# sourceMappingURL=transport.js.map