@ultrst-armada/krnl 1.0.8 → 1.0.9

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.
@@ -50,6 +50,7 @@ __export(index_exports, {
50
50
  ServiceRegistry: () => ServiceRegistry,
51
51
  ServiceRuntime: () => ServiceRuntime,
52
52
  ServiceStateStore: () => ServiceStateStore,
53
+ TelemetryController: () => TelemetryController,
53
54
  UdpProtocolAdapter: () => UdpProtocolAdapter,
54
55
  WebSocketProtocolAdapter: () => WebSocketProtocolAdapter,
55
56
  WorkerExecutionBoundary: () => WorkerExecutionBoundary,
@@ -58,7 +59,10 @@ __export(index_exports, {
58
59
  createServiceDefinition: () => createServiceDefinition,
59
60
  createServiceFacade: () => createServiceFacade,
60
61
  createServiceProxy: () => createServiceProxy,
62
+ deltaResources: () => deltaResources,
61
63
  gutts: () => gutts,
64
+ sampleResources: () => sampleResources,
65
+ telemetryNow: () => telemetryNow,
62
66
  validateOrchestrationDAG: () => validateOrchestrationDAG,
63
67
  validateServiceDefinition: () => validateServiceDefinition
64
68
  });
@@ -128,6 +132,227 @@ var LifecycleManager = class {
128
132
  }
129
133
  };
130
134
 
135
+ // src/telemetry/TelemetryController.ts
136
+ var import_node_crypto = require("crypto");
137
+
138
+ // src/telemetry/TelemetryResources.ts
139
+ var runtimeProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
140
+ var runtimePerformance = typeof globalThis !== "undefined" ? globalThis.performance : void 0;
141
+ function telemetryNow() {
142
+ return runtimePerformance?.now ? runtimePerformance.now() : Date.now();
143
+ }
144
+ function sampleResources() {
145
+ const memory = runtimeProcess?.memoryUsage?.();
146
+ const cpu = runtimeProcess?.cpuUsage?.();
147
+ const eventLoop = runtimePerformance?.eventLoopUtilization?.();
148
+ return {
149
+ cpuUserMicros: cpu?.user,
150
+ cpuSystemMicros: cpu?.system,
151
+ heapUsedBytes: memory?.heapUsed,
152
+ heapTotalBytes: memory?.heapTotal,
153
+ rssBytes: memory?.rss,
154
+ externalBytes: memory?.external,
155
+ arrayBuffersBytes: memory?.arrayBuffers,
156
+ eventLoopUtilization: eventLoop?.utilization,
157
+ scope: memory || cpu || eventLoop ? "process" : "runtime"
158
+ };
159
+ }
160
+ function deltaResources(start, end) {
161
+ const delta = (a, b) => a === void 0 || b === void 0 ? void 0 : b - a;
162
+ return {
163
+ cpuUserMicros: delta(start.cpuUserMicros, end.cpuUserMicros),
164
+ cpuSystemMicros: delta(start.cpuSystemMicros, end.cpuSystemMicros),
165
+ heapUsedBytes: delta(start.heapUsedBytes, end.heapUsedBytes),
166
+ heapTotalBytes: delta(start.heapTotalBytes, end.heapTotalBytes),
167
+ rssBytes: delta(start.rssBytes, end.rssBytes),
168
+ externalBytes: delta(start.externalBytes, end.externalBytes),
169
+ arrayBuffersBytes: delta(start.arrayBuffersBytes, end.arrayBuffersBytes),
170
+ eventLoopUtilization: delta(start.eventLoopUtilization, end.eventLoopUtilization),
171
+ scope: start.scope
172
+ };
173
+ }
174
+
175
+ // src/telemetry/TelemetryController.ts
176
+ var id = (prefix) => `${prefix}_${(0, import_node_crypto.randomUUID)()}`;
177
+ function percentiles(values) {
178
+ if (!values.length) return { min: 0, mean: 0, p50: 0, p90: 0, p95: 0, p99: 0, max: 0 };
179
+ const sorted = [...values].sort((a, b) => a - b);
180
+ const pick = (p) => sorted[Math.min(sorted.length - 1, Math.floor((sorted.length - 1) * p))];
181
+ return {
182
+ min: sorted[0],
183
+ mean: sorted.reduce((sum, value) => sum + value, 0) / sorted.length,
184
+ p50: pick(0.5),
185
+ p90: pick(0.9),
186
+ p95: pick(0.95),
187
+ p99: pick(0.99),
188
+ max: sorted[sorted.length - 1]
189
+ };
190
+ }
191
+ var TelemetryController = class {
192
+ constructor(serviceId, options = {}) {
193
+ this.serviceId = serviceId;
194
+ this.mode = options.mode ?? "off";
195
+ this.maxSamples = Math.max(1, options.maxSamples ?? 2048);
196
+ this.maxRecentInvocations = Math.max(1, options.maxRecentInvocations ?? 100);
197
+ }
198
+ serviceId;
199
+ mode;
200
+ maxSamples;
201
+ maxRecentInvocations;
202
+ samples = [];
203
+ active = /* @__PURE__ */ new Map();
204
+ totalInvocationCount = 0;
205
+ totalSuccessCount = 0;
206
+ totalErrorCount = 0;
207
+ lastInvocationAt;
208
+ enable(mode = "standard") {
209
+ this.mode = mode;
210
+ }
211
+ disable() {
212
+ this.mode = "off";
213
+ this.active.clear();
214
+ }
215
+ setMode(mode) {
216
+ this.mode = mode;
217
+ if (mode === "off") this.active.clear();
218
+ }
219
+ getMode() {
220
+ return this.mode;
221
+ }
222
+ status() {
223
+ return {
224
+ enabled: this.mode !== "off",
225
+ mode: this.mode,
226
+ serviceId: this.serviceId,
227
+ invocationCount: this.totalInvocationCount,
228
+ activeInvocations: this.active.size,
229
+ lastInvocationAt: this.lastInvocationAt
230
+ };
231
+ }
232
+ begin(target, kind, correlationId, parentSpanId) {
233
+ if (this.mode === "off") {
234
+ return {
235
+ invocationId: "",
236
+ traceId: "",
237
+ spanId: "",
238
+ parentSpanId,
239
+ end: () => void 0
240
+ };
241
+ }
242
+ const invocationId = id("inv");
243
+ const spanId = id("span");
244
+ const traceId = parentSpanId ? this.findTraceId(parentSpanId) ?? id("trace") : id("trace");
245
+ const active = {
246
+ invocationId,
247
+ traceId,
248
+ spanId,
249
+ parentSpanId,
250
+ serviceId: this.serviceId,
251
+ target,
252
+ kind,
253
+ correlationId,
254
+ startedAt: telemetryNow(),
255
+ resourcesStart: this.mode === "standard" ? void 0 : sampleResources()
256
+ };
257
+ this.active.set(invocationId, active);
258
+ return {
259
+ invocationId,
260
+ traceId,
261
+ spanId,
262
+ parentSpanId,
263
+ end: (error) => this.finish(active, error)
264
+ };
265
+ }
266
+ reset() {
267
+ this.samples.length = 0;
268
+ this.active.clear();
269
+ this.totalInvocationCount = 0;
270
+ this.totalSuccessCount = 0;
271
+ this.totalErrorCount = 0;
272
+ this.lastInvocationAt = void 0;
273
+ }
274
+ snapshot() {
275
+ const invocations = this.samples.slice();
276
+ const durations = invocations.map((item) => item.durationMs);
277
+ const targetMap = /* @__PURE__ */ new Map();
278
+ for (const invocation of invocations) {
279
+ const key = `${invocation.kind}:${invocation.target}`;
280
+ const group = targetMap.get(key) ?? [];
281
+ group.push(invocation);
282
+ targetMap.set(key, group);
283
+ }
284
+ const targets = [...targetMap.values()].map((group) => ({
285
+ target: group[0].target,
286
+ kind: group[0].kind,
287
+ count: group.length,
288
+ successCount: group.filter((item) => item.status === "completed").length,
289
+ errorCount: group.filter((item) => item.status === "failed").length,
290
+ durationMs: percentiles(group.map((item) => item.durationMs)),
291
+ lastInvocationAt: group[group.length - 1]?.completedAt
292
+ }));
293
+ return {
294
+ serviceId: this.serviceId,
295
+ mode: this.mode,
296
+ capturedAt: Date.now(),
297
+ status: this.status(),
298
+ totals: {
299
+ invocationCount: this.totalInvocationCount,
300
+ successCount: this.totalSuccessCount,
301
+ errorCount: this.totalErrorCount,
302
+ durationMs: percentiles(durations)
303
+ },
304
+ targets,
305
+ activeInvocations: this.active.size,
306
+ recentInvocations: invocations.slice(-this.maxRecentInvocations)
307
+ };
308
+ }
309
+ functionality(name) {
310
+ return this.snapshot().targets.find((target) => target.kind === "functionality" && target.target === name);
311
+ }
312
+ functionalities() {
313
+ return this.snapshot().targets.filter((target) => target.kind === "functionality");
314
+ }
315
+ findTraceId(parentSpanId) {
316
+ for (let index = this.samples.length - 1; index >= 0; index -= 1) {
317
+ if (this.samples[index].spanId === parentSpanId) return this.samples[index].traceId;
318
+ }
319
+ for (const active of this.active.values()) {
320
+ if (active.spanId === parentSpanId) return active.traceId;
321
+ }
322
+ return void 0;
323
+ }
324
+ finish(active, error) {
325
+ if (!this.active.delete(active.invocationId)) return;
326
+ const completedAt = telemetryNow();
327
+ const resourcesEnd = this.mode === "standard" ? void 0 : sampleResources();
328
+ const invocation = {
329
+ invocationId: active.invocationId,
330
+ traceId: active.traceId,
331
+ spanId: active.spanId,
332
+ parentSpanId: active.parentSpanId,
333
+ serviceId: active.serviceId,
334
+ target: active.target,
335
+ kind: active.kind,
336
+ correlationId: active.correlationId,
337
+ startedAt: active.startedAt,
338
+ completedAt,
339
+ durationMs: Math.max(0, completedAt - active.startedAt),
340
+ status: error === void 0 ? "completed" : "failed",
341
+ error: error === void 0 ? void 0 : {
342
+ name: error instanceof Error ? error.name : "Error",
343
+ message: error instanceof Error ? error.message : String(error)
344
+ },
345
+ resources: active.resourcesStart && resourcesEnd ? { start: active.resourcesStart, end: resourcesEnd, delta: deltaResources(active.resourcesStart, resourcesEnd) } : void 0
346
+ };
347
+ this.samples.push(invocation);
348
+ this.totalInvocationCount += 1;
349
+ if (invocation.status === "completed") this.totalSuccessCount += 1;
350
+ else this.totalErrorCount += 1;
351
+ if (this.samples.length > this.maxSamples) this.samples.splice(0, this.samples.length - this.maxSamples);
352
+ this.lastInvocationAt = Date.now();
353
+ }
354
+ };
355
+
131
356
  // src/services/ServiceInstance.ts
132
357
  var ServiceInstance = class {
133
358
  constructor(definition) {
@@ -135,6 +360,7 @@ var ServiceInstance = class {
135
360
  this.id = definition.id;
136
361
  this.name = definition.name;
137
362
  this.version = definition.version;
363
+ this.telemetry = new TelemetryController(this.id);
138
364
  this.lifecycle = new LifecycleManager();
139
365
  if (definition.state) {
140
366
  this.stateStore = new ServiceStateStore(definition.state.initial);
@@ -144,6 +370,7 @@ var ServiceInstance = class {
144
370
  id;
145
371
  name;
146
372
  version;
373
+ telemetry;
147
374
  stateStore;
148
375
  lifecycle;
149
376
  initialized = false;
@@ -208,7 +435,19 @@ var ServiceInstance = class {
208
435
  if (!operation) {
209
436
  throw new Error("[Service:" + this.name + "] Operation '" + op + "' not found.");
210
437
  }
211
- return await operation.handler(input, ctx);
438
+ if (ctx.metadata?.__krnlTelemetryInternal === true) {
439
+ return await operation.handler(input, ctx);
440
+ }
441
+ const parentSpanId = typeof ctx.metadata?.__krnlTelemetryParentSpanId === "string" ? ctx.metadata.__krnlTelemetryParentSpanId : void 0;
442
+ const handle = this.telemetry.begin(op, "service", ctx.correlationId, parentSpanId);
443
+ try {
444
+ const output = await operation.handler(input, ctx);
445
+ handle.end();
446
+ return output;
447
+ } catch (error) {
448
+ handle.end(error);
449
+ throw error;
450
+ }
212
451
  }
213
452
  getState() {
214
453
  return this.stateStore?.getState() ?? Object.freeze({});
@@ -240,6 +479,7 @@ var ServiceProxy = class {
240
479
  this.id = definition.id;
241
480
  this.name = definition.name;
242
481
  this.version = definition.version;
482
+ this.telemetry = new TelemetryController(this.id);
243
483
  this.stateCache = { ...definition.state?.initial ?? {} };
244
484
  }
245
485
  definition;
@@ -248,6 +488,7 @@ var ServiceProxy = class {
248
488
  id;
249
489
  name;
250
490
  version;
491
+ telemetry;
251
492
  stateCache;
252
493
  eventHandlers = /* @__PURE__ */ new Map();
253
494
  lifecycle = new LifecycleManager();
@@ -305,11 +546,21 @@ var ServiceProxy = class {
305
546
  payload: input,
306
547
  timestamp: Date.now()
307
548
  };
308
- const response = await this.adapter.send(this.endpoint, envelope);
309
- if (response.error) {
310
- throw new Error("[ServiceProxy:" + this.name + "] Remote error: " + response.error);
549
+ const parentSpanId = typeof ctx.metadata?.__krnlTelemetryParentSpanId === "string" ? ctx.metadata.__krnlTelemetryParentSpanId : void 0;
550
+ const handle = this.telemetry.begin(op, "service", ctx.correlationId, parentSpanId);
551
+ try {
552
+ const response = await this.adapter.send(this.endpoint, envelope);
553
+ if (response.error) {
554
+ const error = new Error("[ServiceProxy:" + this.name + "] Remote error: " + response.error);
555
+ handle.end(error);
556
+ throw error;
557
+ }
558
+ handle.end();
559
+ return response.payload;
560
+ } catch (error) {
561
+ handle.end(error);
562
+ throw error;
311
563
  }
312
- return response.payload;
313
564
  }
314
565
  getState() {
315
566
  return Object.freeze({ ...this.stateCache });
@@ -457,22 +708,22 @@ var FunctionalityFacade = class {
457
708
  definition;
458
709
  eventBus;
459
710
  events;
460
- constructor(id, definition, options = {}) {
461
- if (!id || typeof id !== "string") {
711
+ constructor(id2, definition, options = {}) {
712
+ if (!id2 || typeof id2 !== "string") {
462
713
  throw new Error("[FunctionalityFacade] Functionality id must be a non-empty string.");
463
714
  }
464
715
  if (!definition || typeof definition.execute !== "function") {
465
- throw new Error(`[FunctionalityFacade:${id}] Functionality must define execute().`);
716
+ throw new Error(`[FunctionalityFacade:${id2}] Functionality must define execute().`);
466
717
  }
467
- this.id = id;
468
- this.name = definition.name || id;
718
+ this.id = id2;
719
+ this.name = definition.name || id2;
469
720
  this.description = definition.description || "";
470
721
  this.bubbleEvents = options.bubbleEvents ?? definition.bubbleEvents ?? true;
471
722
  this.definition = definition;
472
723
  this.eventBus = new EventBus();
473
724
  for (const reserved of ["triggered", "completed", "failed"]) {
474
725
  if (definition.events && reserved in definition.events) {
475
- throw new Error(`[FunctionalityFacade:${id}] Event '${reserved}' is reserved for functionality lifecycle.`);
726
+ throw new Error(`[FunctionalityFacade:${id2}] Event '${reserved}' is reserved for functionality lifecycle.`);
476
727
  }
477
728
  }
478
729
  const eventNames = [
@@ -586,11 +837,11 @@ var PriorityQueue = class {
586
837
  return item.run;
587
838
  }
588
839
  enqueue(run, options) {
589
- const { priority = 0, id } = options ?? {};
840
+ const { priority = 0, id: id2 } = options ?? {};
590
841
  const { size } = this;
591
842
  const element = {
592
843
  priority,
593
- id,
844
+ id: id2,
594
845
  run
595
846
  };
596
847
  if (size === 0) {
@@ -607,16 +858,16 @@ var PriorityQueue = class {
607
858
  const index = lowerBound(this.#queue, element, (a, b) => a.priority === b.priority ? 0 : b.priority - a.priority);
608
859
  this.#queue.splice(index, 0, element);
609
860
  }
610
- setPriority(id, priority) {
611
- const index = this.#findIndex((element) => element.id === id);
861
+ setPriority(id2, priority) {
862
+ const index = this.#findIndex((element) => element.id === id2);
612
863
  if (index === -1) {
613
- throw new ReferenceError(`No promise function with the id "${id}" exists in the queue.`);
864
+ throw new ReferenceError(`No promise function with the id "${id2}" exists in the queue.`);
614
865
  }
615
866
  if (this.#queue[index].priority === priority) {
616
867
  return;
617
868
  }
618
869
  const [item] = this.#queue.splice(index, 1);
619
- this.enqueue(item.run, { priority, id });
870
+ this.enqueue(item.run, { priority, id: id2 });
620
871
  }
621
872
  remove(idOrRun) {
622
873
  const index = this.#findIndex((element) => (typeof idOrRun === "string" ? element.id : element.run) === idOrRun);
@@ -1032,17 +1283,17 @@ var PQueue = class extends EventTarget {
1032
1283
  }
1033
1284
  }
1034
1285
  async #add(function_, options, waitingTask) {
1035
- const id = options.id ?? (this.#idAssigner++).toString();
1286
+ const id2 = options.id ?? (this.#idAssigner++).toString();
1036
1287
  options = {
1037
1288
  timeout: this.#timeout,
1038
1289
  ...options,
1039
- id
1290
+ id: id2
1040
1291
  };
1041
1292
  validateTimeout(options.timeout);
1042
1293
  if (options.priority !== void 0 && (typeof options.priority !== "number" || Number.isNaN(options.priority))) {
1043
1294
  throw new TypeError(`Expected \`priority\` to be a number, got \`${String(options.priority)}\` (${typeof options.priority})`);
1044
1295
  }
1045
- waitingTask.id = id;
1296
+ waitingTask.id = id2;
1046
1297
  waitingTask.priority = options.priority ?? 0;
1047
1298
  return new Promise((resolve, reject) => {
1048
1299
  if (options.signal?.aborted) {
@@ -1059,7 +1310,7 @@ var PQueue = class extends EventTarget {
1059
1310
  }
1060
1311
  this.#pending++;
1061
1312
  const runningTask = {
1062
- id,
1313
+ id: id2,
1063
1314
  priority: waitingTask.priority,
1064
1315
  startTime: Date.now(),
1065
1316
  timeout: options.timeout
@@ -1126,7 +1377,7 @@ var PQueue = class extends EventTarget {
1126
1377
  if (this.#queue instanceof PriorityQueue) {
1127
1378
  this.#queue.remove(run);
1128
1379
  } else {
1129
- this.#queue.remove(id);
1380
+ this.#queue.remove(id2);
1130
1381
  }
1131
1382
  reject(signal.reason);
1132
1383
  this.#processQueue();
@@ -1202,18 +1453,18 @@ var PQueue = class extends EventTarget {
1202
1453
  // '🦀' runs last
1203
1454
  ```
1204
1455
  */
1205
- setPriority(id, priority) {
1456
+ setPriority(id2, priority) {
1206
1457
  if (typeof priority !== "number" || !Number.isFinite(priority)) {
1207
1458
  throw new TypeError(`Expected \`priority\` to be a finite number, got \`${priority}\` (${typeof priority})`);
1208
1459
  }
1209
1460
  for (const waitingTask of this.#waitingTasks) {
1210
- if (waitingTask.id === id) {
1211
- this.#queue.setPriority(id, priority);
1461
+ if (waitingTask.id === id2) {
1462
+ this.#queue.setPriority(id2, priority);
1212
1463
  waitingTask.priority = priority;
1213
1464
  return;
1214
1465
  }
1215
1466
  }
1216
- throw new ReferenceError(`No promise function with the id "${id}" exists in the queue.`);
1467
+ throw new ReferenceError(`No promise function with the id "${id2}" exists in the queue.`);
1217
1468
  }
1218
1469
  /**
1219
1470
  Adds a sync or async task to the queue.
@@ -1556,7 +1807,7 @@ var TimeoutError = class extends DOMException {
1556
1807
  };
1557
1808
 
1558
1809
  // src/orchestration/canonical/KrnlQ.ts
1559
- var import_node_crypto = require("crypto");
1810
+ var import_node_crypto2 = require("crypto");
1560
1811
 
1561
1812
  // src/orchestration/canonical/model.ts
1562
1813
  function validateOrchestrationDAG(steps) {
@@ -1623,8 +1874,8 @@ function validateOrchestrationDAG(steps) {
1623
1874
  }
1624
1875
  }
1625
1876
  const queue = [];
1626
- for (const [id, deg] of inDegree.entries()) {
1627
- if (deg === 0) queue.push(id);
1877
+ for (const [id2, deg] of inDegree.entries()) {
1878
+ if (deg === 0) queue.push(id2);
1628
1879
  }
1629
1880
  const order = [];
1630
1881
  while (queue.length > 0) {
@@ -1760,7 +2011,7 @@ var KrnlWorkerPool = class {
1760
2011
  // src/orchestration/canonical/KrnlQ.ts
1761
2012
  function generateSecureId(prefix) {
1762
2013
  try {
1763
- return `${prefix}_${(0, import_node_crypto.randomUUID)()}`;
2014
+ return `${prefix}_${(0, import_node_crypto2.randomUUID)()}`;
1764
2015
  } catch {
1765
2016
  return `${prefix}_${Math.random().toString(36).substring(2, 11)}_${Date.now()}`;
1766
2017
  }
@@ -1828,9 +2079,9 @@ var KrnlQueue = class {
1828
2079
  if (this.jobs.size <= this.maxRetainedJobs) return;
1829
2080
  const excess = this.jobs.size - this.maxRetainedJobs;
1830
2081
  let pruned = 0;
1831
- for (const [id, record] of this.jobs.entries()) {
2082
+ for (const [id2, record] of this.jobs.entries()) {
1832
2083
  if (record.status === "completed" || record.status === "failed" || record.status === "cancelled") {
1833
- this.jobs.delete(id);
2084
+ this.jobs.delete(id2);
1834
2085
  pruned++;
1835
2086
  if (pruned >= excess) break;
1836
2087
  }
@@ -2444,6 +2695,7 @@ var ServiceFacade = class {
2444
2695
  defaultFrontend;
2445
2696
  instance;
2446
2697
  queue;
2698
+ telemetry;
2447
2699
  constructor(config) {
2448
2700
  if (!config || !config.id || typeof config.id !== "string") {
2449
2701
  throw new Error("[ServiceFacade] ServiceFacade requires a valid id.");
@@ -2473,6 +2725,7 @@ var ServiceFacade = class {
2473
2725
  operations: {}
2474
2726
  });
2475
2727
  }
2728
+ this.telemetry = this.instance.telemetry;
2476
2729
  this.queue = new KrnlQueue({
2477
2730
  queueName: `krnl_queue_${this.id}`,
2478
2731
  concurrency: config.concurrency ?? config.queueOptions?.concurrency ?? 10,
@@ -2516,6 +2769,8 @@ var ServiceFacade = class {
2516
2769
  */
2517
2770
  async call(op, input, ctx) {
2518
2771
  const correlationId = ctx?.correlationId || `corr_${Math.random().toString(36).substring(2, 11)}`;
2772
+ const telemetryParent = typeof ctx?.metadata?.__krnlTelemetryParentSpanId === "string" ? ctx.metadata.__krnlTelemetryParentSpanId : void 0;
2773
+ const telemetryHandle = this.telemetry.begin(op, "service", correlationId, telemetryParent);
2519
2774
  const commandId = `cmd_${this.id}_${op}_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
2520
2775
  const command = {
2521
2776
  id: commandId,
@@ -2525,26 +2780,48 @@ var ServiceFacade = class {
2525
2780
  idempotencyKey: ctx?.idempotencyKey,
2526
2781
  createdAt: Date.now()
2527
2782
  };
2528
- const result = await this.queue.executeCommand(command, async (payload, workerCtx) => {
2529
- WorkerExecutionBoundary.assertWorkerContext(workerCtx);
2530
- const functionality = this.functionalities[op];
2531
- if (functionality) {
2532
- return await functionality.execute(payload, {
2533
- serviceId: this.id,
2534
- functionalityId: functionality.id,
2783
+ try {
2784
+ const result = await this.queue.executeCommand(command, async (payload, workerCtx) => {
2785
+ WorkerExecutionBoundary.assertWorkerContext(workerCtx);
2786
+ const functionality = this.functionalities[op];
2787
+ if (functionality) {
2788
+ const functionalityTelemetry = this.telemetry.begin(
2789
+ functionality.name,
2790
+ "functionality",
2791
+ workerCtx.correlationId,
2792
+ telemetryHandle.spanId
2793
+ );
2794
+ try {
2795
+ return await functionality.execute(payload, {
2796
+ serviceId: this.id,
2797
+ functionalityId: functionality.id,
2798
+ correlationId: workerCtx.correlationId,
2799
+ state: this.instance.getState()
2800
+ });
2801
+ } catch (error) {
2802
+ functionalityTelemetry.end(error);
2803
+ throw error;
2804
+ } finally {
2805
+ functionalityTelemetry.end();
2806
+ }
2807
+ }
2808
+ return await this.instance.call(op, payload, {
2535
2809
  correlationId: workerCtx.correlationId,
2536
- state: this.instance.getState()
2810
+ idempotencyKey: command.idempotencyKey,
2811
+ metadata: { __krnlTelemetryInternal: true }
2537
2812
  });
2538
- }
2539
- return await this.instance.call(op, payload, {
2540
- correlationId: workerCtx.correlationId,
2541
- idempotencyKey: command.idempotencyKey
2542
2813
  });
2543
- });
2544
- if (result.status === "FAILED") {
2545
- throw new Error(result.error || `[ServiceFacade:${this.id}] Operation '${op}' execution failed.`);
2814
+ if (result.status === "FAILED") {
2815
+ const error = new Error(result.error || `[ServiceFacade:${this.id}] Operation '${op}' execution failed.`);
2816
+ telemetryHandle.end(error);
2817
+ throw error;
2818
+ }
2819
+ telemetryHandle.end();
2820
+ return result.data;
2821
+ } catch (error) {
2822
+ telemetryHandle.end(error);
2823
+ throw error;
2546
2824
  }
2547
- return result.data;
2548
2825
  }
2549
2826
  /**
2550
2827
  * External caller callable boundary for functionality orchestration execution.
@@ -2558,6 +2835,18 @@ var ServiceFacade = class {
2558
2835
  );
2559
2836
  }
2560
2837
  const correlationId = options.correlationId || `corr_${Math.random().toString(36).substring(2, 11)}`;
2838
+ const serviceTelemetryHandle = this.telemetry.begin(
2839
+ `orchestrate:${orchestrationName}`,
2840
+ "service",
2841
+ correlationId,
2842
+ typeof options.metadata?.__krnlTelemetryParentSpanId === "string" ? options.metadata.__krnlTelemetryParentSpanId : void 0
2843
+ );
2844
+ const telemetryHandle = this.telemetry.begin(
2845
+ orchestrationName,
2846
+ "orchestration",
2847
+ correlationId,
2848
+ serviceTelemetryHandle.spanId
2849
+ );
2561
2850
  const commandId = `cmd_orch_${this.id}_${orchestrationName}_${Date.now()}`;
2562
2851
  const command = {
2563
2852
  id: commandId,
@@ -2605,7 +2894,8 @@ var ServiceFacade = class {
2605
2894
  ...s.compensation,
2606
2895
  handler: async (compCtx) => {
2607
2896
  await this.call(s.compensation.target, compCtx.results[s.id], {
2608
- correlationId: compCtx.correlationId
2897
+ correlationId: compCtx.correlationId,
2898
+ metadata: { __krnlTelemetryParentSpanId: telemetryHandle.spanId }
2609
2899
  });
2610
2900
  }
2611
2901
  };
@@ -2621,7 +2911,8 @@ var ServiceFacade = class {
2621
2911
  stepPayload.input = stepCtx.results.input;
2622
2912
  }
2623
2913
  return await this.call(s.target, stepPayload, {
2624
- correlationId: stepCtx.correlationId
2914
+ correlationId: stepCtx.correlationId,
2915
+ metadata: { __krnlTelemetryParentSpanId: telemetryHandle.spanId }
2625
2916
  });
2626
2917
  }
2627
2918
  };
@@ -2641,7 +2932,8 @@ var ServiceFacade = class {
2641
2932
  const nestedResult = await this.orchestrate(childOrchId, childInput, {
2642
2933
  correlationId: childCtx.correlationId,
2643
2934
  timeoutMs: childOrch.timeoutMs,
2644
- abortSignal: options.abortSignal
2935
+ abortSignal: options.abortSignal,
2936
+ metadata: { __krnlTelemetryParentSpanId: telemetryHandle.spanId }
2645
2937
  });
2646
2938
  if (nestedResult.status !== "COMPLETED") {
2647
2939
  throw new Error(nestedResult.error || `Nested orchestration "${childOrchId}" failed.`);
@@ -2689,8 +2981,13 @@ var ServiceFacade = class {
2689
2981
  });
2690
2982
  }
2691
2983
  if (cmdResult.status === "FAILED" || orchestrationResult?.status === "FAILED") {
2692
- throw new Error(orchestrationResult?.error || cmdResult.error || `[ServiceFacade:${this.id}] Orchestration failed.`);
2984
+ const error = new Error(orchestrationResult?.error || cmdResult.error || `[ServiceFacade:${this.id}] Orchestration failed.`);
2985
+ telemetryHandle.end(error);
2986
+ serviceTelemetryHandle.end(error);
2987
+ throw error;
2693
2988
  }
2989
+ telemetryHandle.end();
2990
+ serviceTelemetryHandle.end();
2694
2991
  return cmdResult.data;
2695
2992
  }
2696
2993
  /**
@@ -3349,9 +3646,9 @@ var ServiceRuntime = class {
3349
3646
  // src/discovery/ServiceDiscovery.ts
3350
3647
  var ServiceDiscovery = class {
3351
3648
  peers = /* @__PURE__ */ new Map();
3352
- registerPeer(id, name, endpoints) {
3353
- this.peers.set(id, {
3354
- id,
3649
+ registerPeer(id2, name, endpoints) {
3650
+ this.peers.set(id2, {
3651
+ id: id2,
3355
3652
  name,
3356
3653
  endpoints,
3357
3654
  lastSeen: Date.now()
@@ -3360,8 +3657,8 @@ var ServiceDiscovery = class {
3360
3657
  getPeers() {
3361
3658
  return Array.from(this.peers.values());
3362
3659
  }
3363
- findPeer(id) {
3364
- return this.peers.get(id);
3660
+ findPeer(id2) {
3661
+ return this.peers.get(id2);
3365
3662
  }
3366
3663
  };
3367
3664
 
@@ -3837,6 +4134,7 @@ var gutts = __toESM(require("@dinilmusick/gutts"), 1);
3837
4134
  ServiceRegistry,
3838
4135
  ServiceRuntime,
3839
4136
  ServiceStateStore,
4137
+ TelemetryController,
3840
4138
  UdpProtocolAdapter,
3841
4139
  WebSocketProtocolAdapter,
3842
4140
  WorkerExecutionBoundary,
@@ -3845,7 +4143,10 @@ var gutts = __toESM(require("@dinilmusick/gutts"), 1);
3845
4143
  createServiceDefinition,
3846
4144
  createServiceFacade,
3847
4145
  createServiceProxy,
4146
+ deltaResources,
3848
4147
  gutts,
4148
+ sampleResources,
4149
+ telemetryNow,
3849
4150
  validateOrchestrationDAG,
3850
4151
  validateServiceDefinition
3851
4152
  });