|
| 1 | +import { getNodeEnv } from '@constructive-io/graphql-env'; |
| 2 | +import { Logger } from '@pgpmjs/logger'; |
| 3 | +import { svcCache } from '@pgpmjs/server-utils'; |
| 4 | +import type { RequestHandler } from 'express'; |
| 5 | +import { getCacheStats } from 'graphile-cache'; |
| 6 | +import { getInFlightCount, getInFlightKeys } from './graphile'; |
| 7 | + |
| 8 | +const log = new Logger('debug-memory'); |
| 9 | + |
| 10 | +const toMB = (bytes: number): string => `${(bytes / 1024 / 1024).toFixed(1)} MB`; |
| 11 | + |
| 12 | +/** |
| 13 | + * Development-only debug endpoint for monitoring memory usage and cache state. |
| 14 | + * |
| 15 | + * Mounts GET /debug/memory which returns: |
| 16 | + * - Node.js process memory (heap, RSS, external, array buffers) |
| 17 | + * - Graphile cache stats (size, max, TTL, keys with ages) |
| 18 | + * - Service cache size |
| 19 | + * - In-flight handler creation count |
| 20 | + * - Process uptime |
| 21 | + * |
| 22 | + * This endpoint is only available when NODE_ENV=development. |
| 23 | + * In production, it returns 404. |
| 24 | + */ |
| 25 | +export const debugMemory: RequestHandler = (_req, res) => { |
| 26 | + if (getNodeEnv() !== 'development') { |
| 27 | + res.status(404).send('Not found'); |
| 28 | + return; |
| 29 | + } |
| 30 | + |
| 31 | + const mem = process.memoryUsage(); |
| 32 | + const cacheStats = getCacheStats(); |
| 33 | + |
| 34 | + const response = { |
| 35 | + memory: { |
| 36 | + heapUsed: toMB(mem.heapUsed), |
| 37 | + heapTotal: toMB(mem.heapTotal), |
| 38 | + rss: toMB(mem.rss), |
| 39 | + external: toMB(mem.external), |
| 40 | + arrayBuffers: toMB(mem.arrayBuffers), |
| 41 | + }, |
| 42 | + graphileCache: { |
| 43 | + size: cacheStats.size, |
| 44 | + max: cacheStats.max, |
| 45 | + ttl: `${(cacheStats.ttl / 1000 / 60).toFixed(0)} min`, |
| 46 | + keys: cacheStats.keys, |
| 47 | + }, |
| 48 | + svcCache: { |
| 49 | + size: svcCache.size, |
| 50 | + }, |
| 51 | + inFlight: { |
| 52 | + count: getInFlightCount(), |
| 53 | + keys: getInFlightKeys(), |
| 54 | + }, |
| 55 | + uptime: `${(process.uptime() / 60).toFixed(1)} min`, |
| 56 | + timestamp: new Date().toISOString(), |
| 57 | + }; |
| 58 | + |
| 59 | + log.debug('Memory snapshot:', response); |
| 60 | + res.json(response); |
| 61 | +}; |
0 commit comments