@unrdf/hooks 26.4.8 → 26.5.5

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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/examples/hook-chains/node_modules/.bin/jiti +2 -2
  3. package/examples/hook-chains/node_modules/.bin/msw +4 -4
  4. package/examples/hook-chains/node_modules/.bin/terser +2 -2
  5. package/examples/hook-chains/node_modules/.bin/tsc +2 -2
  6. package/examples/hook-chains/node_modules/.bin/tsserver +2 -2
  7. package/examples/hook-chains/node_modules/.bin/tsx +2 -2
  8. package/examples/hook-chains/node_modules/.bin/validate-hooks +2 -2
  9. package/examples/hook-chains/node_modules/.bin/vite +4 -4
  10. package/examples/hook-chains/node_modules/.bin/vitest +2 -2
  11. package/examples/hook-chains/node_modules/.bin/yaml +4 -4
  12. package/examples/hook-chains/package.json +3 -3
  13. package/examples/hooks-marketplace.mjs +10 -10
  14. package/examples/knowledge-hook-manager-usage.mjs +1 -1
  15. package/examples/policy-hooks/node_modules/.bin/jiti +2 -2
  16. package/examples/policy-hooks/node_modules/.bin/msw +4 -4
  17. package/examples/policy-hooks/node_modules/.bin/terser +2 -2
  18. package/examples/policy-hooks/node_modules/.bin/tsc +2 -2
  19. package/examples/policy-hooks/node_modules/.bin/tsserver +2 -2
  20. package/examples/policy-hooks/node_modules/.bin/tsx +2 -2
  21. package/examples/policy-hooks/node_modules/.bin/validate-hooks +2 -2
  22. package/examples/policy-hooks/node_modules/.bin/vite +4 -4
  23. package/examples/policy-hooks/node_modules/.bin/vitest +2 -2
  24. package/examples/policy-hooks/node_modules/.bin/yaml +4 -4
  25. package/examples/policy-hooks/package.json +3 -3
  26. package/examples/production-policy-chain.mjs +54 -0
  27. package/examples/semantic-inference-hook.mjs +66 -0
  28. package/examples/validate-hooks.mjs +1 -1
  29. package/package.json +10 -5
  30. package/src/define.mjs +3 -0
  31. package/src/hooks/condition-evaluator.mjs +2 -0
  32. package/src/hooks/dependency-graph.mjs +388 -0
  33. package/src/hooks/observability.mjs +67 -74
  34. package/src/hooks/parallel-executor.mjs +295 -0
  35. package/src/hooks/policy-pack.mjs +2 -2
  36. package/src/hooks/schemas.mjs +1 -0
  37. package/src/hooks/wasm4pm-conformance-bridge.mjs +25 -0
  38. package/src/hooks/worker-pool.mjs +478 -0
  39. package/examples/hook-chains/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  40. package/examples/hook-chains/unrdf-hooks-example-chains-5.0.0.tgz +0 -0
  41. package/examples/policy-hooks/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  42. package/examples/policy-hooks/unrdf-hooks-example-policy-5.0.0.tgz +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unrdf/hooks",
3
- "version": "26.4.8",
3
+ "version": "26.5.5",
4
4
  "description": "UNRDF Knowledge Hooks - Policy Definition and Execution Framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,7 +10,10 @@
10
10
  "exports": {
11
11
  ".": "./src/index.mjs",
12
12
  "./define": "./src/define.mjs",
13
- "./executor": "./src/executor.mjs"
13
+ "./executor": "./src/executor.mjs",
14
+ "./parallel-executor": "./src/hooks/parallel-executor.mjs",
15
+ "./dependency-graph": "./src/hooks/dependency-graph.mjs",
16
+ "./worker-pool": "./src/hooks/worker-pool.mjs"
14
17
  },
15
18
  "sideEffects": false,
16
19
  "files": [
@@ -48,12 +51,14 @@
48
51
  ],
49
52
  "dependencies": {
50
53
  "@noble/hashes": "^1.4.0",
51
- "@unrdf/core": "26.4.4",
52
- "@unrdf/oxigraph": "26.4.4",
54
+ "@opentelemetry/api": "^1.7.0",
55
+ "@unrdf/core": "workspace:*",
56
+ "@unrdf/otel": "workspace:*",
57
+ "@unrdf/oxigraph": "workspace:*",
53
58
  "citty": "^0.1.6",
54
59
  "eyereasoner": "^10",
55
60
  "sparqljs": "^3.7.3",
56
- "zod": "^4.1.13"
61
+ "zod": "^4.3.6"
57
62
  },
58
63
  "devDependencies": {
59
64
  "@types/node": "^24.10.1",
package/src/define.mjs CHANGED
@@ -48,6 +48,9 @@ export const THRESHOLD = 'threshold';
48
48
  /** @type {'count'} Count-based condition */
49
49
  export const COUNT = 'count';
50
50
 
51
+ /** @type {'semantic-inference'} Open Ontologies reasoning query */
52
+ export const SEMANTIC_INFERENCE = 'semantic-inference';
53
+
51
54
  /** @type {'window'} Sliding window temporal condition */
52
55
  export const WINDOW = 'window';
53
56
 
@@ -403,6 +403,8 @@ export async function evaluateCondition(condition, graph, options = {}) {
403
403
  return await evaluateWindow(condition, graph, resolver, env, options);
404
404
  case 'n3':
405
405
  return await evaluateN3(condition, graph, resolver, env);
406
+ case 'semantic-inference':
407
+ return await evaluateSemanticInference(condition, graph, resolver, env);
406
408
  default:
407
409
  throw new Error(`Unsupported condition kind: ${condition.kind}`);
408
410
  }
@@ -0,0 +1,388 @@
1
+ /**
2
+ * @file Dependency Graph - Topological sort with cycle detection for parallel hook execution
3
+ * @module hooks/dependency-graph
4
+ */
5
+
6
+ import { z } from 'zod';
7
+
8
+ /* ========================================================================= */
9
+ /* Zod Schemas */
10
+ /* ========================================================================= */
11
+
12
+ export const HookDependencySchema = z.object({
13
+ hookId: z.string(),
14
+ dependsOn: z.array(z.string()).optional().default([]),
15
+ metadata: z.record(z.string(), z.unknown()).optional(),
16
+ });
17
+
18
+ /* ========================================================================= */
19
+ /* Dependency Graph Class */
20
+ /* ========================================================================= */
21
+
22
+ /**
23
+ * Dependency graph for topological sorting and cycle detection.
24
+ *
25
+ * @class DependencyGraph
26
+ */
27
+ export class DependencyGraph {
28
+ /**
29
+ * Create a new dependency graph.
30
+ */
31
+ constructor() {
32
+ /** @type {Map<string, Set<string>>} - hookId → set of dependencies */
33
+ this.dependencies = new Map();
34
+
35
+ /** @type {Map<string, Set<string>>} - hookId → set of dependents (reverse graph) */
36
+ this.dependents = new Map();
37
+
38
+ /** @type {Set<string>} - all registered hook IDs */
39
+ this.nodes = new Set();
40
+ }
41
+
42
+ /**
43
+ * Add a node (hook) to the graph.
44
+ *
45
+ * @param {string} hookId - Hook identifier
46
+ * @param {string[]} [dependencies=[]] - List of hook IDs this hook depends on
47
+ */
48
+ addNode(hookId, dependencies = []) {
49
+ const nodeExists = this.nodes.has(hookId);
50
+
51
+ // Initialize dependency and dependent sets
52
+ this.dependencies.set(hookId, new Set(dependencies));
53
+ this.dependents.set(hookId, new Set());
54
+ this.nodes.add(hookId);
55
+
56
+ // Update reverse graph (dependents)
57
+ for (const depId of dependencies) {
58
+ // Add the dependency as a node if it doesn't exist
59
+ if (!this.nodes.has(depId)) {
60
+ this.nodes.add(depId);
61
+ this.dependencies.set(depId, new Set());
62
+ this.dependents.set(depId, new Set());
63
+ }
64
+
65
+ // Add current hook as dependent of the dependency
66
+ this.dependents.get(depId).add(hookId);
67
+
68
+ // If node already existed, remove old dependency relationships
69
+ if (nodeExists) {
70
+ // Note: We're keeping the new dependencies, so old ones are effectively replaced
71
+ // The dependents sets are updated above
72
+ }
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Add multiple nodes to the graph.
78
+ *
79
+ * @param {Array<{hookId: string, dependsOn?: string[]}>} nodes - Nodes to add
80
+ */
81
+ addNodes(nodes) {
82
+ for (const node of nodes) {
83
+ this.addNode(node.hookId, node.dependsOn || []);
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Remove a node from the graph.
89
+ *
90
+ * @param {string} hookId - Hook identifier to remove
91
+ * @returns {boolean} True if node was removed
92
+ */
93
+ removeNode(hookId) {
94
+ if (!this.nodes.has(hookId)) {
95
+ return false;
96
+ }
97
+
98
+ // Remove from dependency sets of dependent nodes
99
+ const dependents = this.dependents.get(hookId) || new Set();
100
+ for (const dependentId of dependents) {
101
+ this.dependencies.get(dependentId)?.delete(hookId);
102
+ }
103
+
104
+ // Remove from dependent sets of dependency nodes
105
+ const dependencies = this.dependencies.get(hookId) || new Set();
106
+ for (const depId of dependencies) {
107
+ this.dependents.get(depId)?.delete(hookId);
108
+ }
109
+
110
+ // Clean up maps
111
+ this.dependencies.delete(hookId);
112
+ this.dependents.delete(hookId);
113
+ this.nodes.delete(hookId);
114
+
115
+ return true;
116
+ }
117
+
118
+ /**
119
+ * Check if the graph contains a cycle.
120
+ *
121
+ * Uses depth-first search with coloring (white/gray/black) to detect back edges.
122
+ *
123
+ * @returns {{hasCycle: boolean, cycle?: string[]}} - Cycle detection result
124
+ */
125
+ detectCycle() {
126
+ const WHITE = 0; // Unvisited
127
+ const GRAY = 1; // Visiting (in current path)
128
+ const BLACK = 2; // Visited (not in current path)
129
+
130
+ /** @type {Map<string, number>} */
131
+ const color = new Map();
132
+
133
+ // Initialize all nodes as white
134
+ for (const node of this.nodes) {
135
+ color.set(node, WHITE);
136
+ }
137
+
138
+ /** @type {string[]} */
139
+ const cycle = [];
140
+
141
+ /**
142
+ * Depth-first search to detect back edges.
143
+ *
144
+ * @param {string} node - Current node
145
+ * @returns {boolean} - True if cycle found
146
+ */
147
+ const dfs = (node) => {
148
+ color.set(node, GRAY);
149
+
150
+ const dependencies = this.dependencies.get(node) || new Set();
151
+ for (const dep of dependencies) {
152
+ const depColor = color.get(dep);
153
+
154
+ if (depColor === GRAY) {
155
+ // Back edge found - cycle detected
156
+ cycle.push(node, dep);
157
+ return true;
158
+ }
159
+
160
+ if (depColor === WHITE) {
161
+ if (dfs(dep)) {
162
+ cycle.push(node);
163
+ return true;
164
+ }
165
+ }
166
+ }
167
+
168
+ color.set(node, BLACK);
169
+ return false;
170
+ };
171
+
172
+ // Run DFS from each white node
173
+ for (const node of this.nodes) {
174
+ if (color.get(node) === WHITE) {
175
+ if (dfs(node)) {
176
+ // Reverse to get correct order
177
+ cycle.reverse();
178
+ return { hasCycle: true, cycle };
179
+ }
180
+ }
181
+ }
182
+
183
+ return { hasCycle: false };
184
+ }
185
+
186
+ /**
187
+ * Perform topological sort (Kahn's algorithm).
188
+ *
189
+ * Returns an array of layers, where each layer contains hooks that can be
190
+ * executed in parallel. Hooks in layer N depend only on hooks in layers < N.
191
+ *
192
+ * @returns {{layers: string[][], hasCycle: boolean, cycle?: string[]}} - Topological sort result
193
+ */
194
+ topologicalSort() {
195
+ // First check for cycles
196
+ const cycleDetection = this.detectCycle();
197
+ if (cycleDetection.hasCycle) {
198
+ return {
199
+ layers: [],
200
+ hasCycle: true,
201
+ cycle: cycleDetection.cycle,
202
+ };
203
+ }
204
+
205
+ /** @type {Map<string, number>} - hookId → in-degree (number of unmet dependencies) */
206
+ const inDegree = new Map();
207
+
208
+ // Initialize in-degrees
209
+ for (const node of this.nodes) {
210
+ const deps = this.dependencies.get(node) || new Set();
211
+ // Only count dependencies that are actually registered nodes
212
+ inDegree.set(node, [...deps].filter(dep => this.nodes.has(dep)).length);
213
+ }
214
+
215
+ /** @type {string[]} - Queue of nodes with in-degree 0 */
216
+ const queue = [];
217
+
218
+ // Find all nodes with in-degree 0
219
+ for (const [node, degree] of inDegree) {
220
+ if (degree === 0) {
221
+ queue.push(node);
222
+ }
223
+ }
224
+
225
+ /** @type {string[][]} - Result layers */
226
+ const layers = [];
227
+
228
+ // Process nodes in batches (layers)
229
+ while (queue.length > 0) {
230
+ // Current layer: all nodes currently in queue can execute in parallel
231
+ layers.push([...queue]);
232
+
233
+ // Process all nodes in current layer
234
+ /** @type {string[]} */
235
+ const currentLayer = [...queue];
236
+ queue.length = 0; // Clear queue
237
+
238
+ // For each node in current layer, reduce in-degree of its dependents
239
+ for (const node of currentLayer) {
240
+ const dependents = this.dependents.get(node) || new Set();
241
+ for (const dependent of dependents) {
242
+ const newDegree = (inDegree.get(dependent) || 0) - 1;
243
+ inDegree.set(dependent, newDegree);
244
+
245
+ // If in-degree becomes 0, add to next layer
246
+ if (newDegree === 0) {
247
+ queue.push(dependent);
248
+ }
249
+ }
250
+ }
251
+ }
252
+
253
+ // Check if all nodes were processed (should be true if no cycles)
254
+ const processedCount = layers.reduce((sum, layer) => sum + layer.length, 0);
255
+ const hasCycle = processedCount !== this.nodes.size;
256
+
257
+ return {
258
+ layers,
259
+ hasCycle,
260
+ cycle: hasCycle ? [] : undefined,
261
+ };
262
+ }
263
+
264
+ /**
265
+ * Get all dependencies for a hook (transitive closure).
266
+ *
267
+ * @param {string} hookId - Hook identifier
268
+ * @returns {Set<string>} - Set of all transitive dependencies
269
+ */
270
+ getTransitiveDependencies(hookId) {
271
+ const visited = new Set();
272
+ const result = new Set();
273
+
274
+ const dfs = (node) => {
275
+ if (visited.has(node)) {
276
+ return;
277
+ }
278
+
279
+ visited.add(node);
280
+ const deps = this.dependencies.get(node) || new Set();
281
+ for (const dep of deps) {
282
+ result.add(dep);
283
+ dfs(dep);
284
+ }
285
+ };
286
+
287
+ dfs(hookId);
288
+ return result;
289
+ }
290
+
291
+ /**
292
+ * Get all dependents for a hook (transitive closure).
293
+ *
294
+ * @param {string} hookId - Hook identifier
295
+ * @returns {Set<string>} - Set of all transitive dependents
296
+ */
297
+ getTransitiveDependents(hookId) {
298
+ const visited = new Set();
299
+ const result = new Set();
300
+
301
+ const dfs = (node) => {
302
+ if (visited.has(node)) {
303
+ return;
304
+ }
305
+
306
+ visited.add(node);
307
+ const deps = this.dependents.get(node) || new Set();
308
+ for (const dep of deps) {
309
+ result.add(dep);
310
+ dfs(dep);
311
+ }
312
+ };
313
+
314
+ dfs(hookId);
315
+ return result;
316
+ }
317
+
318
+ /**
319
+ * Get statistics about the dependency graph.
320
+ *
321
+ * @returns {{nodeCount: number, edgeCount: number, maxDepth: number, avgBranchingFactor: number}}
322
+ */
323
+ getStats() {
324
+ const nodeCount = this.nodes.size;
325
+ let edgeCount = 0;
326
+
327
+ for (const [, deps] of this.dependencies) {
328
+ edgeCount += deps.size;
329
+ }
330
+
331
+ // Calculate max depth (longest path)
332
+ const { layers } = this.topologicalSort();
333
+ const maxDepth = layers.length;
334
+
335
+ // Calculate average branching factor (avg dependents per node)
336
+ const avgBranchingFactor =
337
+ nodeCount > 0
338
+ ? [...this.dependents.values()].reduce((sum, deps) => sum + deps.size, 0) / nodeCount
339
+ : 0;
340
+
341
+ return {
342
+ nodeCount,
343
+ edgeCount,
344
+ maxDepth,
345
+ avgBranchingFactor: parseFloat(avgBranchingFactor.toFixed(2)),
346
+ };
347
+ }
348
+
349
+ /**
350
+ * Clear all nodes from the graph.
351
+ */
352
+ clear() {
353
+ this.dependencies.clear();
354
+ this.dependents.clear();
355
+ this.nodes.clear();
356
+ }
357
+ }
358
+
359
+ /* ========================================================================= */
360
+ /* Factory Functions */
361
+ /* ========================================================================= */
362
+
363
+ /**
364
+ * Create a dependency graph from hook definitions.
365
+ *
366
+ * @param {Array<{id: string, dependsOn?: string[]}>} hooks - Hook definitions
367
+ * @returns {DependencyGraph} - Populated dependency graph
368
+ */
369
+ export function createDependencyGraph(hooks) {
370
+ const graph = new DependencyGraph();
371
+
372
+ for (const hook of hooks) {
373
+ graph.addNode(hook.id, hook.dependsOn || []);
374
+ }
375
+
376
+ return graph;
377
+ }
378
+
379
+ /**
380
+ * Build execution layers from hooks (convenience function).
381
+ *
382
+ * @param {Array<{id: string, dependsOn?: string[]}>} hooks - Hook definitions
383
+ * @returns {{layers: any[][], hasCycle: boolean, cycle?: string[]}} - Topological sort result
384
+ */
385
+ export function buildExecutionLayers(hooks) {
386
+ const graph = createDependencyGraph(hooks);
387
+ return graph.topologicalSort();
388
+ }
@@ -4,8 +4,7 @@
4
4
  *
5
5
  * @description
6
6
  * Implements comprehensive observability with OpenTelemetry traces, metrics,
7
- * and logging for the UNRDF Knowledge Engine. Provides backpressure monitoring,
8
- * error isolation, and performance tracking.
7
+ * and logging for the UNRDF Knowledge Engine. Uses daemon SDK as single source of truth.
9
8
  */
10
9
 
11
10
  import { _randomUUID } from 'crypto';
@@ -13,6 +12,35 @@ import { _z } from 'zod';
13
12
  import { ObservabilityConfigSchema, PerformanceMetricsSchema } from './schemas.mjs';
14
13
  import { getRuntimeConfig } from '../context/config.mjs';
15
14
 
15
+ // Import daemon SDK functions (single source of truth)
16
+ let getTracer, getMeter;
17
+ try {
18
+ const daemonSdk = await import('@unrdf/daemon/integrations/otel-sdk.mjs');
19
+ getTracer = daemonSdk.getTracer;
20
+ getMeter = daemonSdk.getMeter;
21
+ } catch {
22
+ // Daemon SDK not available (e.g., in standalone hooks usage)
23
+ console.warn('[Observability] Daemon SDK not available - will use fallback mode');
24
+ }
25
+
26
+ // Import generated semantic convention constants
27
+ import {
28
+ ATTR_UNRDF_HOOK_ID,
29
+ ATTR_UNRDF_HOOK_NAME,
30
+ ATTR_UNRDF_HOOK_CONDITION_KIND,
31
+ ATTR_UNRDF_HOOK_EFFECT_KIND,
32
+ ATTR_UNRDF_HOOK_ENABLED,
33
+ ATTR_UNRDF_HOOK_SATISFIED,
34
+ ATTR_UNRDF_HOOK_PRIORITY,
35
+ ATTR_UNRDF_HOOK_QUADS_ADDED,
36
+ ATTR_UNRDF_HOOK_HOOKS_SATISFIED,
37
+ ATTR_UNRDF_HOOK_HOOKS_TOTAL,
38
+ ATTR_UNRDF_TRANSACTION_ID,
39
+ ATTR_UNRDF_TRANSACTION_ISOLATION_LEVEL,
40
+ ATTR_UNRDF_TRANSACTION_OPERATION_COUNT,
41
+ ATTR_UNRDF_TRANSACTION_RESULT,
42
+ } from '@unrdf/otel/generated';
43
+
16
44
  /**
17
45
  * OpenTelemetry observability manager
18
46
  */
@@ -48,63 +76,29 @@ export class ObservabilityManager {
48
76
  if (this.initialized) return;
49
77
 
50
78
  try {
51
- // Dynamic import of OpenTelemetry packages
52
- const { NodeSDK } = await import('@opentelemetry/sdk-node');
53
- const { getNodeAutoInstrumentations } =
54
- await import('@opentelemetry/auto-instrumentations-node');
55
- const { Resource } = await import('@opentelemetry/resources');
56
- const { SemanticResourceAttributes } = await import('@opentelemetry/semantic-conventions');
57
- const { OTLPTraceExporter } = await import('@opentelemetry/exporter-otlp-http');
58
- const { OTLPMetricExporter } = await import('@opentelemetry/exporter-otlp-http');
59
- const { PeriodicExportingMetricReader } = await import('@opentelemetry/sdk-metrics');
60
- const { trace, metrics } = await import('@opentelemetry/api');
61
-
62
- // Create resource
63
- const resource = new Resource({
64
- [SemanticResourceAttributes.SERVICE_NAME]: this.config.serviceName,
65
- [SemanticResourceAttributes.SERVICE_VERSION]: this.config.serviceVersion,
66
- ...this.config.resourceAttributes,
67
- });
68
-
69
- // Create exporters
70
- const traceExporter = new OTLPTraceExporter({
71
- url: this.config.endpoint ? `${this.config.endpoint}/v1/traces` : undefined,
72
- headers: this.config.headers,
73
- });
74
-
75
- const metricExporter = new OTLPMetricExporter({
76
- url: this.config.endpoint ? `${this.config.endpoint}/v1/metrics` : undefined,
77
- headers: this.config.headers,
78
- });
79
-
80
- // Create metric reader
81
- const metricReader = new PeriodicExportingMetricReader({
82
- exporter: metricExporter,
83
- exportIntervalMillis: this.config.scheduledDelayMillis,
84
- exportTimeoutMillis: this.config.exportTimeoutMillis,
85
- });
86
-
87
- // Initialize SDK
88
- const sdk = new NodeSDK({
89
- resource,
90
- traceExporter: this.config.enableTracing ? traceExporter : undefined,
91
- metricReader: this.config.enableMetrics ? metricReader : undefined,
92
- instrumentations: this.config.enableTracing ? [getNodeAutoInstrumentations()] : [],
93
- });
94
-
95
- await sdk.start();
96
-
97
- // Get tracer and meter
98
- this.tracer = trace.getTracer(this.config.serviceName, this.config.serviceVersion);
99
- this.meter = metrics.getMeter(this.config.serviceName, this.config.serviceVersion);
100
-
101
- // Create custom metrics
102
- this._createCustomMetrics();
103
-
104
- this.initialized = true;
105
- console.log(`[Observability] Initialized with service: ${this.config.serviceName}`);
79
+ // Use daemon SDK as single source of truth
80
+ if (typeof getTracer === 'function' && typeof getMeter === 'function') {
81
+ this.tracer = getTracer();
82
+ this.meter = getMeter();
83
+
84
+ if (!this.tracer || !this.meter) {
85
+ console.warn('[Observability] Daemon SDK not initialized - using fallback');
86
+ this._initializeFallback();
87
+ return;
88
+ }
89
+
90
+ // Create custom metrics using daemon's meter
91
+ this._createCustomMetrics();
92
+
93
+ this.initialized = true;
94
+ console.log(`[Observability] Initialized with daemon SDK for service: ${this.config.serviceName}`);
95
+ } else {
96
+ // Daemon SDK not available - use fallback
97
+ console.warn('[Observability] Daemon SDK not available - using fallback mode');
98
+ this._initializeFallback();
99
+ }
106
100
  } catch (error) {
107
- console.warn(`[Observability] Failed to initialize OpenTelemetry: ${error.message}`);
101
+ console.warn(`[Observability] Failed to initialize with daemon SDK: ${error.message}`);
108
102
  // Fallback to console logging
109
103
  this._initializeFallback();
110
104
  }
@@ -117,42 +111,42 @@ export class ObservabilityManager {
117
111
  _createCustomMetrics() {
118
112
  if (!this.meter) return;
119
113
 
120
- // Transaction metrics
121
- this.transactionCounter = this.meter.createCounter('kgc_transactions_total', {
114
+ // Transaction metrics (using unrdf.* prefix from registry)
115
+ this.transactionCounter = this.meter.createCounter('unrdf_transactions_total', {
122
116
  description: 'Total number of transactions processed',
123
117
  });
124
118
 
125
- this.transactionDuration = this.meter.createHistogram('kgc_transaction_duration_ms', {
119
+ this.transactionDuration = this.meter.createHistogram('unrdf_transaction_duration_ms', {
126
120
  description: 'Transaction processing duration in milliseconds',
127
121
  unit: 'ms',
128
122
  });
129
123
 
130
- this.hookExecutionCounter = this.meter.createCounter('kgc_hooks_executed_total', {
124
+ this.hookExecutionCounter = this.meter.createCounter('unrdf_hooks_executed_total', {
131
125
  description: 'Total number of hooks executed',
132
126
  });
133
127
 
134
- this.hookDuration = this.meter.createHistogram('kgc_hook_duration_ms', {
128
+ this.hookDuration = this.meter.createHistogram('unrdf_hook_duration_ms', {
135
129
  description: 'Hook execution duration in milliseconds',
136
130
  unit: 'ms',
137
131
  });
138
132
 
139
- this.errorCounter = this.meter.createCounter('kgc_errors_total', {
133
+ this.errorCounter = this.meter.createCounter('unrdf_errors_total', {
140
134
  description: 'Total number of errors',
141
135
  });
142
136
 
143
- this.memoryGauge = this.meter.createUpDownCounter('kgc_memory_usage_bytes', {
137
+ this.memoryGauge = this.meter.createUpDownCounter('unrdf_memory_usage_bytes', {
144
138
  description: 'Memory usage in bytes',
145
139
  });
146
140
 
147
- this.cacheHitCounter = this.meter.createCounter('kgc_cache_hits_total', {
141
+ this.cacheHitCounter = this.meter.createCounter('unrdf_cache_hits_total', {
148
142
  description: 'Total cache hits',
149
143
  });
150
144
 
151
- this.cacheMissCounter = this.meter.createCounter('kgc_cache_misses_total', {
145
+ this.cacheMissCounter = this.meter.createCounter('unrdf_cache_misses_total', {
152
146
  description: 'Total cache misses',
153
147
  });
154
148
 
155
- this.queueDepthGauge = this.meter.createUpDownCounter('kgc_queue_depth', {
149
+ this.queueDepthGauge = this.meter.createUpDownCounter('unrdf_queue_depth', {
156
150
  description: 'Current queue depth',
157
151
  });
158
152
  }
@@ -177,10 +171,9 @@ export class ObservabilityManager {
177
171
  return { transactionId, startTime: Date.now() };
178
172
  }
179
173
 
180
- const span = this.tracer.startSpan('kgc.transaction', {
174
+ const span = this.tracer.startSpan('unrdf.transaction', {
181
175
  attributes: {
182
- 'kgc.transaction.id': transactionId,
183
- 'kgc.service.name': this.config.serviceName,
176
+ [ATTR_UNRDF_TRANSACTION_ID]: transactionId,
184
177
  ...attributes,
185
178
  },
186
179
  });
@@ -239,11 +232,11 @@ export class ObservabilityManager {
239
232
  }
240
233
 
241
234
  const parentSpan = this.activeSpans.get(transactionId)?.span;
242
- const span = this.tracer.startSpan('kgc.hook', {
235
+ const span = this.tracer.startSpan('unrdf.hook', {
243
236
  parent: parentSpan,
244
237
  attributes: {
245
- 'kgc.hook.id': hookId,
246
- 'kgc.transaction.id': transactionId,
238
+ [ATTR_UNRDF_HOOK_ID]: hookId,
239
+ [ATTR_UNRDF_TRANSACTION_ID]: transactionId,
247
240
  ...attributes,
248
241
  },
249
242
  });