@kultify/kmicro-js 0.0.15 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +26 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +27 -21
- package/dist/index.js.map +1 -1
- package/package.json +26 -17
package/dist/index.cjs
CHANGED
|
@@ -28,14 +28,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
33
|
CallError: () => CallError,
|
|
34
34
|
Kmicro: () => Kmicro,
|
|
35
35
|
RequestContext: () => RequestContext,
|
|
36
36
|
init: () => init
|
|
37
37
|
});
|
|
38
|
-
module.exports = __toCommonJS(
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
40
|
// src/KMicro.ts
|
|
41
41
|
var import_node_assert = __toESM(require("assert"), 1);
|
|
@@ -49,13 +49,13 @@ var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
|
49
49
|
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
50
50
|
var import_incubating = require("@opentelemetry/semantic-conventions/incubating");
|
|
51
51
|
var import_pino = __toESM(require("pino"), 1);
|
|
52
|
-
async function init(nats, serviceName, version, description) {
|
|
52
|
+
async function init(nats, serviceName, version, description, enableOtel = true) {
|
|
53
53
|
const kmicro = new Kmicro({
|
|
54
54
|
name: serviceName,
|
|
55
55
|
version,
|
|
56
56
|
description
|
|
57
57
|
});
|
|
58
|
-
await kmicro.init(nats);
|
|
58
|
+
await kmicro.init(nats, enableOtel);
|
|
59
59
|
return kmicro;
|
|
60
60
|
}
|
|
61
61
|
var Kmicro = class {
|
|
@@ -71,7 +71,11 @@ var Kmicro = class {
|
|
|
71
71
|
getLogger(module2) {
|
|
72
72
|
return this.pinoLogger.child({ module: module2 });
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
getNc() {
|
|
75
|
+
(0, import_node_assert.default)(this.nc);
|
|
76
|
+
return this.nc;
|
|
77
|
+
}
|
|
78
|
+
async init(natsURI, enableOtel = true) {
|
|
75
79
|
const natsUrl = new URL(natsURI);
|
|
76
80
|
this.nc = await (0, import_transport_node.connect)({
|
|
77
81
|
name: this.meta.name,
|
|
@@ -86,20 +90,22 @@ var Kmicro = class {
|
|
|
86
90
|
description: this.meta.description
|
|
87
91
|
});
|
|
88
92
|
this.group = this.service.addGroup(this.meta.name);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
if (enableOtel) {
|
|
94
|
+
this.otel = new import_sdk_node.NodeSDK({
|
|
95
|
+
serviceName: this.meta.name,
|
|
96
|
+
traceExporter: new import_exporter_trace_otlp_proto.OTLPTraceExporter(),
|
|
97
|
+
resource: (0, import_resources.resourceFromAttributes)({
|
|
98
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: this.meta.name,
|
|
99
|
+
[import_incubating.ATTR_MESSAGING_SYSTEM]: "nats"
|
|
100
|
+
}),
|
|
101
|
+
instrumentations: [
|
|
102
|
+
new import_instrumentation_pino.PinoInstrumentation({
|
|
103
|
+
disableLogSending: true
|
|
104
|
+
})
|
|
105
|
+
]
|
|
106
|
+
});
|
|
107
|
+
this.otel.start();
|
|
108
|
+
}
|
|
103
109
|
}
|
|
104
110
|
async stop() {
|
|
105
111
|
await this.service?.stop().catch((error) => {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/KMicro.ts"],"sourcesContent":["export * from \"./KMicro.js\";\n","import assert from \"node:assert\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { type NatsConnection, connect, headers } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\tcontext,\n\tpropagation,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\nimport { PinoInstrumentation } from \"@opentelemetry/instrumentation-pino\";\nimport { Resource } from \"@opentelemetry/resources\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\";\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\n\t});\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.Logger;\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({ module });\n\t}\n\n\tpublic async init(natsURI: string) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t\tthis.otel = new NodeSDK({\n\t\t\tserviceName: this.meta.name,\n\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\tresource: new Resource({\n\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t[ATTR_MESSAGING_SYSTEM]: \"nats\",\n\t\t\t}),\n\t\t\tinstrumentations: [\n\t\t\t\tnew PinoInstrumentation({\n\t\t\t\t\tdisableLogSending: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t});\n\n\t\tthis.otel.start();\n\t}\n\n\tpublic async stop() {\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.otel?.shutdown().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.pinoLogger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["pino","module","assert","trace","context"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/KMicro.ts"],"sourcesContent":["export * from \"./KMicro.js\";\n","import assert from \"node:assert\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { connect, headers, type NatsConnection } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\nimport { PinoInstrumentation } from \"@opentelemetry/instrumentation-pino\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\";\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n\tenableOtel = true,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\n\t});\n\tawait kmicro.init(nats, enableOtel);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.Logger;\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({ module });\n\t}\n\n\tpublic getNc(): NatsConnection {\n\t\tassert(this.nc);\n\t\treturn this.nc;\n\t}\n\n\tpublic async init(natsURI: string, enableOtel = true) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t\tif (enableOtel) {\n\t\t\tthis.otel = new NodeSDK({\n\t\t\t\tserviceName: this.meta.name,\n\t\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\t\tresource: resourceFromAttributes({\n\t\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t\t[ATTR_MESSAGING_SYSTEM]: \"nats\",\n\t\t\t\t}),\n\t\t\t\tinstrumentations: [\n\t\t\t\t\tnew PinoInstrumentation({\n\t\t\t\t\t\tdisableLogSending: true,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tthis.otel.start();\n\t\t}\n\t}\n\n\tpublic async stop() {\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.otel?.shutdown().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.pinoLogger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["pino","module","assert","trace","context"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ import pino, { Logger } from 'pino';
|
|
|
5
5
|
/**
|
|
6
6
|
* Use init to create a kmicro instance and directly start (init) it
|
|
7
7
|
*/
|
|
8
|
-
declare function init(nats: string, serviceName: string, version: string, description?: string): Promise<Kmicro>;
|
|
8
|
+
declare function init(nats: string, serviceName: string, version: string, description?: string, enableOtel?: boolean): Promise<Kmicro>;
|
|
9
9
|
interface Callable {
|
|
10
10
|
call(target: string, payload: Uint8Array, options?: {
|
|
11
11
|
/**
|
|
@@ -26,8 +26,9 @@ declare class Kmicro implements Callable {
|
|
|
26
26
|
version: string;
|
|
27
27
|
description: string | undefined;
|
|
28
28
|
});
|
|
29
|
-
getLogger(module?: string): pino.
|
|
30
|
-
|
|
29
|
+
getLogger(module?: string): pino.Logger<never, boolean>;
|
|
30
|
+
getNc(): NatsConnection;
|
|
31
|
+
init(natsURI: string, enableOtel?: boolean): Promise<void>;
|
|
31
32
|
stop(): Promise<void>;
|
|
32
33
|
addEndpoint(name: string, handler: (context_: RequestContext, data: Uint8Array) => Promise<Uint8Array>): void;
|
|
33
34
|
/**
|
|
@@ -60,7 +61,7 @@ declare class RequestContext {
|
|
|
60
61
|
currentService: string;
|
|
61
62
|
header: Record<string, string>;
|
|
62
63
|
});
|
|
63
|
-
getLogger(module?: string): pino.
|
|
64
|
+
getLogger(module?: string): pino.Logger<never, boolean>;
|
|
64
65
|
call(target: string, payload: Uint8Array, options?: {
|
|
65
66
|
/**
|
|
66
67
|
* @default 5000 ms
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import pino, { Logger } from 'pino';
|
|
|
5
5
|
/**
|
|
6
6
|
* Use init to create a kmicro instance and directly start (init) it
|
|
7
7
|
*/
|
|
8
|
-
declare function init(nats: string, serviceName: string, version: string, description?: string): Promise<Kmicro>;
|
|
8
|
+
declare function init(nats: string, serviceName: string, version: string, description?: string, enableOtel?: boolean): Promise<Kmicro>;
|
|
9
9
|
interface Callable {
|
|
10
10
|
call(target: string, payload: Uint8Array, options?: {
|
|
11
11
|
/**
|
|
@@ -26,8 +26,9 @@ declare class Kmicro implements Callable {
|
|
|
26
26
|
version: string;
|
|
27
27
|
description: string | undefined;
|
|
28
28
|
});
|
|
29
|
-
getLogger(module?: string): pino.
|
|
30
|
-
|
|
29
|
+
getLogger(module?: string): pino.Logger<never, boolean>;
|
|
30
|
+
getNc(): NatsConnection;
|
|
31
|
+
init(natsURI: string, enableOtel?: boolean): Promise<void>;
|
|
31
32
|
stop(): Promise<void>;
|
|
32
33
|
addEndpoint(name: string, handler: (context_: RequestContext, data: Uint8Array) => Promise<Uint8Array>): void;
|
|
33
34
|
/**
|
|
@@ -60,7 +61,7 @@ declare class RequestContext {
|
|
|
60
61
|
currentService: string;
|
|
61
62
|
header: Record<string, string>;
|
|
62
63
|
});
|
|
63
|
-
getLogger(module?: string): pino.
|
|
64
|
+
getLogger(module?: string): pino.Logger<never, boolean>;
|
|
64
65
|
call(target: string, payload: Uint8Array, options?: {
|
|
65
66
|
/**
|
|
66
67
|
* @default 5000 ms
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// src/KMicro.ts
|
|
2
|
-
import assert from "
|
|
2
|
+
import assert from "assert";
|
|
3
3
|
import { Svcm } from "@nats-io/services";
|
|
4
4
|
import { connect, headers } from "@nats-io/transport-node";
|
|
5
5
|
import {
|
|
6
|
-
SpanKind,
|
|
7
|
-
SpanStatusCode,
|
|
8
6
|
context,
|
|
9
7
|
propagation,
|
|
8
|
+
SpanKind,
|
|
9
|
+
SpanStatusCode,
|
|
10
10
|
trace
|
|
11
11
|
} from "@opentelemetry/api";
|
|
12
12
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
|
|
13
13
|
import { PinoInstrumentation } from "@opentelemetry/instrumentation-pino";
|
|
14
|
-
import {
|
|
14
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
15
15
|
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
16
16
|
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
17
17
|
import {
|
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
ATTR_RPC_SERVICE
|
|
21
21
|
} from "@opentelemetry/semantic-conventions/incubating";
|
|
22
22
|
import pino from "pino";
|
|
23
|
-
async function init(nats, serviceName, version, description) {
|
|
23
|
+
async function init(nats, serviceName, version, description, enableOtel = true) {
|
|
24
24
|
const kmicro = new Kmicro({
|
|
25
25
|
name: serviceName,
|
|
26
26
|
version,
|
|
27
27
|
description
|
|
28
28
|
});
|
|
29
|
-
await kmicro.init(nats);
|
|
29
|
+
await kmicro.init(nats, enableOtel);
|
|
30
30
|
return kmicro;
|
|
31
31
|
}
|
|
32
32
|
var Kmicro = class {
|
|
@@ -42,7 +42,11 @@ var Kmicro = class {
|
|
|
42
42
|
getLogger(module) {
|
|
43
43
|
return this.pinoLogger.child({ module });
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
getNc() {
|
|
46
|
+
assert(this.nc);
|
|
47
|
+
return this.nc;
|
|
48
|
+
}
|
|
49
|
+
async init(natsURI, enableOtel = true) {
|
|
46
50
|
const natsUrl = new URL(natsURI);
|
|
47
51
|
this.nc = await connect({
|
|
48
52
|
name: this.meta.name,
|
|
@@ -57,20 +61,22 @@ var Kmicro = class {
|
|
|
57
61
|
description: this.meta.description
|
|
58
62
|
});
|
|
59
63
|
this.group = this.service.addGroup(this.meta.name);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
if (enableOtel) {
|
|
65
|
+
this.otel = new NodeSDK({
|
|
66
|
+
serviceName: this.meta.name,
|
|
67
|
+
traceExporter: new OTLPTraceExporter(),
|
|
68
|
+
resource: resourceFromAttributes({
|
|
69
|
+
[ATTR_SERVICE_NAME]: this.meta.name,
|
|
70
|
+
[ATTR_MESSAGING_SYSTEM]: "nats"
|
|
71
|
+
}),
|
|
72
|
+
instrumentations: [
|
|
73
|
+
new PinoInstrumentation({
|
|
74
|
+
disableLogSending: true
|
|
75
|
+
})
|
|
76
|
+
]
|
|
77
|
+
});
|
|
78
|
+
this.otel.start();
|
|
79
|
+
}
|
|
74
80
|
}
|
|
75
81
|
async stop() {
|
|
76
82
|
await this.service?.stop().catch((error) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/KMicro.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { type NatsConnection, connect, headers } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\tcontext,\n\tpropagation,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\nimport { PinoInstrumentation } from \"@opentelemetry/instrumentation-pino\";\nimport { Resource } from \"@opentelemetry/resources\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\";\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\n\t});\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.Logger;\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({ module });\n\t}\n\n\tpublic async init(natsURI: string) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t\tthis.otel = new NodeSDK({\n\t\t\tserviceName: this.meta.name,\n\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\tresource: new Resource({\n\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t[ATTR_MESSAGING_SYSTEM]: \"nats\",\n\t\t\t}),\n\t\t\tinstrumentations: [\n\t\t\t\tnew PinoInstrumentation({\n\t\t\t\t\tdisableLogSending: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t});\n\n\t\tthis.otel.start();\n\t}\n\n\tpublic async stop() {\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.otel?.shutdown().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.pinoLogger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["trace","context"]}
|
|
1
|
+
{"version":3,"sources":["../src/KMicro.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { connect, headers, type NatsConnection } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\nimport { PinoInstrumentation } from \"@opentelemetry/instrumentation-pino\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\";\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n\tenableOtel = true,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\n\t});\n\tawait kmicro.init(nats, enableOtel);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.Logger;\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({ module });\n\t}\n\n\tpublic getNc(): NatsConnection {\n\t\tassert(this.nc);\n\t\treturn this.nc;\n\t}\n\n\tpublic async init(natsURI: string, enableOtel = true) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t\tif (enableOtel) {\n\t\t\tthis.otel = new NodeSDK({\n\t\t\t\tserviceName: this.meta.name,\n\t\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\t\tresource: resourceFromAttributes({\n\t\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t\t[ATTR_MESSAGING_SYSTEM]: \"nats\",\n\t\t\t\t}),\n\t\t\t\tinstrumentations: [\n\t\t\t\t\tnew PinoInstrumentation({\n\t\t\t\t\t\tdisableLogSending: true,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tthis.otel.start();\n\t\t}\n\t}\n\n\tpublic async stop() {\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.otel?.shutdown().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.pinoLogger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["trace","context"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kultify/kmicro-js",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,26 +49,35 @@
|
|
|
49
49
|
"author": "Kultify GmbH",
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@nats-io/services": "3.
|
|
53
|
-
"@nats-io/transport-node": "3.
|
|
52
|
+
"@nats-io/services": "3.1.0",
|
|
53
|
+
"@nats-io/transport-node": "3.1.0",
|
|
54
54
|
"@opentelemetry/api": "^1.9.0",
|
|
55
|
-
"@opentelemetry/core": "^
|
|
56
|
-
"@opentelemetry/exporter-trace-otlp-proto": "^0.
|
|
57
|
-
"@opentelemetry/instrumentation-pino": "^0.
|
|
58
|
-
"@opentelemetry/resources": "^
|
|
59
|
-
"@opentelemetry/sdk-node": "^0.
|
|
60
|
-
"@opentelemetry/sdk-trace-node": "^
|
|
61
|
-
"@opentelemetry/semantic-conventions": "^1.
|
|
62
|
-
"pino": "^9.
|
|
55
|
+
"@opentelemetry/core": "^2.0.1",
|
|
56
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.203.0",
|
|
57
|
+
"@opentelemetry/instrumentation-pino": "^0.50.0",
|
|
58
|
+
"@opentelemetry/resources": "^2.0.1",
|
|
59
|
+
"@opentelemetry/sdk-node": "^0.203.0",
|
|
60
|
+
"@opentelemetry/sdk-trace-node": "^2.0.1",
|
|
61
|
+
"@opentelemetry/semantic-conventions": "^1.36.0",
|
|
62
|
+
"pino": "^9.9.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@biomejs/biome": "
|
|
66
|
-
"@
|
|
67
|
-
"@
|
|
65
|
+
"@biomejs/biome": "2.2.2",
|
|
66
|
+
"@testcontainers/nats": "^11.5.1",
|
|
67
|
+
"@tsconfig/node20": "^20.1.6",
|
|
68
|
+
"@types/node": "^24.3.0",
|
|
68
69
|
"jaeger-client": "^3.19.0",
|
|
69
70
|
"moleculer": "^0.14.35",
|
|
70
|
-
"tsup": "^8.
|
|
71
|
-
"typescript": "5.
|
|
72
|
-
"vitest": "^2.
|
|
71
|
+
"tsup": "^8.5.0",
|
|
72
|
+
"typescript": "5.9.2",
|
|
73
|
+
"vitest": "^3.2.4"
|
|
74
|
+
},
|
|
75
|
+
"pnpm": {
|
|
76
|
+
"onlyBuiltDependencies": [
|
|
77
|
+
"cpu-features",
|
|
78
|
+
"esbuild",
|
|
79
|
+
"protobufjs",
|
|
80
|
+
"ssh2"
|
|
81
|
+
]
|
|
73
82
|
}
|
|
74
83
|
}
|