Skip to content

feat: implement telemetry and observability layer#170

Open
shantanushok wants to merge 2 commits into
Memact:mainfrom
shantanushok:refactored/endpoints
Open

feat: implement telemetry and observability layer#170
shantanushok wants to merge 2 commits into
Memact:mainfrom
shantanushok:refactored/endpoints

Conversation

@shantanushok

@shantanushok shantanushok commented Jul 18, 2026

Copy link
Copy Markdown

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

  • Other: Infrastructure

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

  • Unit tests added/updated
  • Manual testing done (describe below)
  • Integration tests pass

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

  • Code follows the repo's style guidelines
  • Self-reviewed before opening PR
  • No breaking changes to protocol-level interfaces (or documented in description)
  • CHANGELOG updated if applicable

Linked Issue

Closes #128

Copilot AI review requested due to automatic review settings July 18, 2026 15:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 /health and /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.

Comment on lines +29 to +43
const span = collector.startSpan(eventType);
try {
const result = fn(...args);
const payload = extractPayload ? extractPayload(args, result) : {};
span.end(payload);
metrics.operationTotal.inc(1, { type: eventType });
if (typeof span.end === "function" && payload.duration_ms) {
metrics.operationDuration.observe(payload.duration_ms);
}
return result;
} catch (error) {
span.end({ error: error.message });
metrics.errorTotal.inc(1, { type: eventType });
throw error;
}
Comment on lines +214 to +217
return {
query: String(args[0] || "").slice(0, 120),
result_count: results.length,
};
Comment thread src/telemetry.mjs Outdated
* span timing, buffered flush, and metrics aggregation.
*
* @param {Object} [options={}]
* @param {number} [options.bufferSize=200] - Max events to buffer before auto-flush
Comment thread src/telemetry.mjs Outdated
Comment thread src/stats-server.mjs Outdated
Comment thread src/engine.mjs Outdated
Comment thread src/engine.mjs Outdated
Comment on lines 1472 to 1476
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 || [])),
};
Comment thread src/engine.mjs
enumerable: true
});

return results;
Comment thread src/telemetry.mjs
Comment on lines +58 to +61
type,
timestamp: new Date().toISOString(),
trace_id: context.trace_id || generateTraceId(),
duration_ms: context.duration_ms ?? null,
Comment thread src/telemetry.mjs
Comment on lines +192 to +194
function startSpan(eventType, context = {}) {
const traceId = context.trace_id || generateTraceId();
const startTime = performance.now();
@shantanushok

Copy link
Copy Markdown
Author

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 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Medium] Refactor API endpoint for Telemetry & Observability

2 participants