Skip to content

feat: add /metrics endpoint for observability#6

Open
GodsBoy wants to merge 2 commits intomainfrom
feat/metrics-endpoint
Open

feat: add /metrics endpoint for observability#6
GodsBoy wants to merge 2 commits intomainfrom
feat/metrics-endpoint

Conversation

@GodsBoy
Copy link
Owner

@GodsBoy GodsBoy commented Mar 7, 2026

Summary

  • Adds a MetricsCollector class (src/metrics.ts) that tracks webhook event counts, processing duration, error counts, and AI call metrics
  • Exposes a GET /metrics endpoint on the Express server for monitoring
  • Includes 6 unit tests covering all collector functionality

Changes

  • src/metrics.ts — New MetricsCollector class with recordEvent(), recordError(), recordAICall(), getSnapshot(), and reset() methods
  • src/index.ts — Wire up /metrics route
  • tests/metrics.test.ts — Full test coverage

Test plan

  • pnpm build passes
  • pnpm test passes (91 tests)
  • Manually verify /metrics returns JSON with expected shape

Add MetricsCollector class that tracks:
- Webhook event counts and processing duration
- Error counts by type
- AI call metrics (total, failures, avg duration)
- Server uptime

Exposes data via GET /metrics endpoint for monitoring.
Includes 6 unit tests for the collector.
@GodsBoy
Copy link
Owner Author

GodsBoy commented Mar 7, 2026

PR Summary

Summary

This PR adds observability to the RepoKeeper application by introducing a MetricsCollector class that tracks webhook events, processing duration, errors, and AI call metrics. A new /metrics endpoint is exposed on the Express server to expose this data as JSON for monitoring purposes.

Files Changed

  • src/metrics.ts — New MetricsCollector class with methods to record events, errors, AI calls, and retrieve a snapshot of current metrics
  • src/index.ts — Added import and GET /metrics route that returns metrics.getSnapshot() as JSON
  • tests/metrics.test.ts — New test file with 6 unit tests covering all collector functionality

Flags

  • Breaking changes detected? No
  • Tests added or modified? Yes — 6 new tests added, all passing
  • Documentation updated? No

Files Changed (3)

  • src/index.ts (+5/-0) [modified]
  • src/metrics.ts (+102/-0) [added]
  • tests/metrics.test.ts (+60/-0) [added]

Size: medium (167 lines changed)
Generated by RepoKeeper

@GodsBoy
Copy link
Owner Author

GodsBoy commented Mar 7, 2026

PR Summary

Summary

This PR adds a new observability feature by introducing a MetricsCollector class that tracks webhook events, processing duration, errors, and AI call metrics. The collector is exposed via a new GET /metrics endpoint on the Express server, enabling real-time monitoring of application health and performance.

Files Changed

  • src/metrics.ts — New MetricsCollector class with methods to record events, errors, and AI calls, plus a singleton export
  • src/index.ts — Added import and /metrics route handler that returns metrics snapshot as JSON
  • tests/metrics.test.ts — Full test suite with 6 tests covering all collector functionality

Flags

  • Breaking changes? No
  • Tests added or modified? Yes (6 new tests added)
  • Documentation updated? No

Files Changed (3)

  • src/index.ts (+5/-0) [modified]
  • src/metrics.ts (+102/-0) [added]
  • tests/metrics.test.ts (+60/-0) [added]

Size: medium (167 lines changed)
Generated by RepoKeeper

Copy link
Owner Author

@GodsBoy GodsBoy left a comment

Choose a reason for hiding this comment

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

RepoKeeper Code Review

The pull request adds a metrics collection system with a new /metrics endpoint. The implementation is generally solid with good test coverage, but there are security and integration concerns that need addressing before merge.

Found 6 issue(s): 0 blocking, 2 warning(s), 4 suggestion(s)


Review by RepoKeeper

res.json({ status: 'ok', version: '0.1.0' });
});

app.get('/metrics', (_req, res) => {
Copy link
Owner Author

Choose a reason for hiding this comment

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

⚠️ WARNING

The /metrics endpoint exposes internal application metrics without any authentication or authorization checks. This could leak sensitive operational information to unauthorized users. Consider adding authentication middleware or restricting this endpoint to localhost only.

recordEvent(eventType: string, durationMs: number): void {
const existing = this.events.get(eventType);
if (existing) {
existing.count++;
Copy link
Owner Author

Choose a reason for hiding this comment

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

⚠️ WARNING

Calling new Date().toISOString() on every event recording (lines 38, 44) creates unnecessary object allocations. Consider using a single timestamp per batch or caching the current time to improve performance in high-throughput scenarios.

@@ -0,0 +1,102 @@
import { log } from './logger.js';
Copy link
Owner Author

Choose a reason for hiding this comment

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

💡 SUGGESTION

The MetricsCollector class is exported as a singleton instance but is never actually integrated with the rest of the application. The webhook handler, AI providers, and GitHub client don't call recordEvent(), recordError(), or recordAICall(). Add instrumentation throughout the codebase to make this metrics collection functional.

private startedAt: string;
private events: Map<string, MetricEntry> = new Map();
private errors: Map<string, number> = new Map();
private aiCallCount = 0;
Copy link
Owner Author

Choose a reason for hiding this comment

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

💡 SUGGESTION

Memory leak potential: The events and errors Maps grow unbounded over the application's lifetime. For long-running applications, consider implementing a sliding window or TTL-based eviction strategy to prevent excessive memory consumption.

@@ -0,0 +1,60 @@
import { describe, it, expect, beforeEach } from 'vitest';
Copy link
Owner Author

Choose a reason for hiding this comment

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

💡 SUGGESTION

The test file only tests the MetricsCollector class in isolation. Add integration tests in src/index.ts to verify that the /metrics endpoint is properly secured, returns valid JSON, and integrates correctly with the Express app.

res.json({ status: 'ok', version: '0.1.0' });
});

app.get('/metrics', (_req, res) => {
Copy link
Owner Author

Choose a reason for hiding this comment

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

💡 SUGGESTION

The /metrics endpoint doesn't set appropriate HTTP headers (e.g., Content-Type is not explicitly set, no Cache-Control headers). Add explicit response headers for clarity and to prevent caching of dynamic metrics data.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant