feat: implement telemetry and observability layer#170
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new telemetry/observability layer to the Memact engine by introducing a lightweight telemetry collector + in-process metrics registry, plus an instrumented-engine wrapper and new stats-server endpoints to expose health and metrics.
Changes:
- Added a telemetry collector (
src/telemetry.mjs) with pub/sub events, span timing, buffering, sinks, and basic per-operation aggregation. - Added a metrics registry (
src/telemetry-metrics.mjs) and an instrumented engine decorator (src/instrumented-engine.mjs) to emit events and record metrics around engine operations. - Extended the stats server with
/healthand/metrics, and updated engine/store stats factoring + tests to cover the new modules.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| test/telemetry.test.mjs | Adds unit coverage for collector emit/on/off/span/flush/metrics/reset behaviors. |
| test/telemetry-metrics.test.mjs | Adds unit coverage for counter/gauge/histogram and registry snapshot/reset. |
| test/instrumented-engine.test.mjs | Verifies instrumented engine pass-through correctness and event emission. |
| test/audit-trail-test.mjs | Switches audit verification from auditTrailLog output to telemetry event capture. |
| src/telemetry.mjs | Implements the core telemetry collector/event bus and span timing. |
| src/telemetry-metrics.mjs | Implements counters/gauges/histograms and a standard registry factory. |
| src/stats-server.mjs | Adds /health and /metrics endpoints and wires in optional collector. |
| src/instrumented-engine.mjs | Adds decorator wrapper that instruments engine operations with telemetry + metrics. |
| src/engine.mjs | Factors store stats computation and removes Object.defineProperty auditTrailLog attachment. |
| package.json | Exposes new telemetry modules via package exports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * span timing, buffered flush, and metrics aggregation. | ||
| * | ||
| * @param {Object} [options={}] | ||
| * @param {number} [options.bufferSize=200] - Max events to buffer before auto-flush |
| graph: buildMemoryGraph(memories, memoryStore.relations || []), | ||
| relations: memoryStore.relations || [], | ||
| actions: [...(memoryStore.actions || []), finalAction], | ||
| stats: { | ||
| ...(memoryStore.stats || {}), | ||
| memoryCount: memories.length, | ||
| activityMemoryCount: memories.filter((memory) => memory.type === "activity_memory").length, | ||
| intentMemoryCount: memories.filter(isIntentMemory).length, | ||
| schemaMemoryCount: memories.filter(isSchemaMemory).length, | ||
| }, | ||
| stats: computeStoreStats(memories, buildMemoryGraph(memories, memoryStore.relations || [])), | ||
| }; |
| type, | ||
| timestamp: new Date().toISOString(), | ||
| trace_id: context.trace_id || generateTraceId(), | ||
| duration_ms: context.duration_ms ?? null, |
| function startSpan(eventType, context = {}) { | ||
| const traceId = context.trace_id || generateTraceId(); | ||
| const startTime = performance.now(); |
|
I have addressed the above comments in the latest commit if you do have any suggestions , changes or modifications I may have missed or misunderstood please reach out on this conversation or on the discord channel . |
|
@keepsloading Hey! I tried to merge this but it has merge conflicts with |
# Conflicts: # src/stats-server.mjs # src/telemetry.mjs # test/telemetry.test.mjs
Added test for invalid trace_id handling in span.
Summary
This PR introduces a robust Telemetry and Observability layer to the Memact engine. It implements a zero-dependency, pluggable architecture using a pub/sub event bus, metrics aggregation (counters, gauges, histograms) it wraps the engine functions without modifying their underlying logic. It exposes these insights via new /metrics and /health HTTP endpoints, laying the foundation for log storage and system monitoring. Trace context IDs are fully W3C-compatible (32-character hex strings) to allow potential transition to OpenTelemetry SDK in the future.
Protocol Alignment
Changes Made
1 ] src/telemetry.mjs : Core telemetry event bus supporting span timing, typed events, wildcard subscribers, and buffered sink flushing. Generates W3C-compliant trace IDs.
2 ] src/telemetry-metrics.mjs : Lightweight, in-process metrics registry supplying Counters, Gauges, and Histograms for operation tracking.
3 ] src/instrumented-engine.mjs : Decorator wrapper that overlays span telemetry and metrics onto all public engine.mjs operations.
4 ] src/engine.mjs : Removed the auditTrailLog Object.defineProperty in retrieveMemories and extracted redundant inline stat computations into a shared computeStoreStats helper.
5 ] src/stats-server.mjs : Added the GET /metrics and GET /health endpoints, maintaining compatibility for the root / stats route.
6 ] test/audit-trail-test.mjs : Migrated to utilize the new telemetry collector pattern instead of the legacy object properties.
7 ] test/telemetry.test.mjs : Verifies the event bus behavior, ensuring correct pub/sub routing, span timing, sink invocation, and trace ID generation.
8 ] test/telemetry-metrics.test.mjs : Tests the initialization and aggregation boundaries of all standard operational metrics (counters, histogram percentiles, gauges).
9 ] test/instrumented-engine.test.mjs : Confirms the decorator cleanly wraps engine functions, correctly emits events upon memory lifecycle operations, and safely bypasses when disabled.
10] package.json - added the path of the new files created.
Testing
1] Added 3 new dedicated test suites containing 59 new assertions.
2] Verified W3C trace context format validation.
3] All 184 tests in the suite pass successfully with zero regressions.
Checklist
Linked Issue
Closes #128