feat(phase-2): workstream 7 — Prometheus + Grafana Monitoring

- Add prom-client 15; shared registry in src/metrics/registry.ts (7 metrics)
- HTTP request counter + duration histogram via metricsMiddleware
- DB query duration histogram wrapping pg Pool.query
- Redis command duration histogram via typed instrumentRedisMethod wrapper
- agentidp_tokens_issued_total in OAuth2Service
- agentidp_agents_registered_total in AgentService
- GET /metrics unauthenticated endpoint (Prometheus text format)
- docker-compose.monitoring.yml overlay (Prometheus + Grafana)
- Grafana auto-provisioned datasource + pre-built AgentIdP dashboard
- docs/devops/operations.md monitoring section added
- 36/36 unit tests passing, 100% coverage on new metrics code
- Fix pre-existing unused import in tests/integration/agents.test.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SentryAgent.ai Developer
2026-03-29 06:13:41 +00:00
parent 7d6e248a14
commit a504964e5f
21 changed files with 1053 additions and 15 deletions

View File

@@ -32,9 +32,11 @@ import { createTokenRouter } from './routes/token.js';
import { createCredentialsRouter } from './routes/credentials.js';
import { createAuditRouter } from './routes/audit.js';
import { createHealthRouter } from './routes/health.js';
import { createMetricsRouter } from './routes/metrics.js';
import { errorHandler } from './middleware/errorHandler.js';
import { createOpaMiddleware } from './middleware/opa.js';
import { metricsMiddleware } from './middleware/metrics.js';
import { createVaultClientFromEnv } from './vault/VaultClient.js';
import { RedisClientType } from 'redis';
import path from 'path';
@@ -75,6 +77,11 @@ export async function createApp(): Promise<Application> {
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// ────────────────────────────────────────────────────────────────
// Prometheus HTTP metrics middleware — must be before all routes
// ────────────────────────────────────────────────────────────────
app.use(metricsMiddleware);
// ────────────────────────────────────────────────────────────────
// Infrastructure singletons
// ────────────────────────────────────────────────────────────────
@@ -144,6 +151,9 @@ export async function createApp(): Promise<Application> {
// Health check — unauthenticated, no OPA
app.use('/health', createHealthRouter(pool, redis as RedisClientType));
// Prometheus metrics — unauthenticated, internal scraping only
app.use('/metrics', createMetricsRouter());
app.use(`${API_BASE}/agents`, createAgentsRouter(agentController, opaMiddleware));
app.use(
`${API_BASE}/agents/:agentId/credentials`,