@cerbos/opentelemetry
Version:
OpenTelemetry instrumentation for the @cerbos/grpc and @cerbos/http client libraries
117 lines • 4.12 kB
JavaScript
;
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