Skip to content

Commit 0766d7a

Browse files
committed
feat: add management server command and prometheus metrics support
1 parent 61a9a03 commit 0766d7a

13 files changed

Lines changed: 1781 additions & 285 deletions

DEPLOYMENT.md

Lines changed: 725 additions & 0 deletions
Large diffs are not rendered by default.

TODO.md

Lines changed: 0 additions & 206 deletions
This file was deleted.

example-audit-report.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"timestamp": "2025-10-08T20:22:54.660Z",
2+
"timestamp": "2025-10-11T16:56:56.846Z",
33
"total": 34,
44
"working": 34,
55
"partial": 0,

src/cli/program.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,22 @@ export function createProgram(): Command {
838838
}
839839
});
840840

841+
// Serve command for management server
842+
program
843+
.command('serve')
844+
.description('Start the management server for health checks and metrics')
845+
.option('-p, --port <port>', 'Port to listen on', '8080')
846+
.option('-c, --config <file>', 'Path to configuration file')
847+
.option('--production', 'Enable production mode with all safety features')
848+
.option('--json', 'Use structured JSON logging')
849+
.action(async _options => {
850+
const { createServeCommand } = await import('./serve');
851+
const serveCommand = createServeCommand();
852+
await serveCommand.parseAsync([process.argv[0], process.argv[1], ...process.argv.slice(3)], {
853+
from: 'user',
854+
});
855+
});
856+
841857
return program;
842858
}
843859

src/cli/serve.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env node
2+
/**
3+
* CLI command to start the management server for health checks and metrics
4+
*/
5+
import { Command } from 'commander';
6+
import { ModuleSystem } from '../module-system';
7+
import { loadConfig } from '../config';
8+
import { StructuredLoggerFactory } from '../module-system/structured-logger';
9+
import * as path from 'path';
10+
import * as fs from 'fs';
11+
12+
const logger = StructuredLoggerFactory.getLogger('serve-command');
13+
14+
export function createServeCommand(): Command {
15+
const cmd = new Command('serve');
16+
17+
cmd
18+
.description('Start the management server for health checks and metrics')
19+
.option('-p, --port <port>', 'Port to listen on', '8080')
20+
.option('-c, --config <file>', 'Path to configuration file')
21+
.option('--production', 'Enable production mode with all safety features')
22+
.option('--json', 'Use structured JSON logging')
23+
.action(async options => {
24+
try {
25+
// Load configuration
26+
const config = options.config
27+
? JSON.parse(fs.readFileSync(path.resolve(options.config), 'utf8'))
28+
: loadConfig(process.cwd());
29+
30+
const port = parseInt(options.port, 10);
31+
const isProduction = options.production || process.env.NODE_ENV === 'production';
32+
33+
// Configure structured logging if requested
34+
if (options.json) {
35+
StructuredLoggerFactory.configure({ format: 'json' });
36+
}
37+
38+
logger.info('Starting management server', {
39+
port,
40+
production: isProduction,
41+
jsonLogging: options.json,
42+
});
43+
44+
// Create module system with production features
45+
const moduleSystem = new ModuleSystem({
46+
resolution: {
47+
baseUrl: process.cwd(),
48+
...config.moduleSystem?.resolution,
49+
},
50+
metrics: true,
51+
circuitBreakers: true,
52+
logger: true,
53+
managementServer: true,
54+
managementPort: port,
55+
resourceLimits: {
56+
maxMemoryBytes: 1024 * 1024 * 1024, // 1GB
57+
maxFileHandles: 1000,
58+
maxCachedModules: 10000,
59+
...config.moduleSystem?.resourceLimits,
60+
},
61+
});
62+
63+
// Start the management server
64+
const actualPort = await moduleSystem.startManagementServer(port);
65+
66+
if (actualPort) {
67+
logger.info(`Management server started successfully`, {
68+
port: actualPort,
69+
endpoints: {
70+
health: `http://localhost:${actualPort}/health`,
71+
ready: `http://localhost:${actualPort}/health/ready`,
72+
metrics: `http://localhost:${actualPort}/metrics`,
73+
prometheus: `http://localhost:${actualPort}/metrics/prometheus`,
74+
},
75+
});
76+
77+
// Handle graceful shutdown
78+
const shutdown = async () => {
79+
logger.info('Shutting down management server...');
80+
await moduleSystem.shutdown();
81+
process.exit(0);
82+
};
83+
84+
process.on('SIGTERM', shutdown);
85+
process.on('SIGINT', shutdown);
86+
process.on('SIGHUP', shutdown);
87+
88+
// Keep the process alive
89+
process.stdin.resume();
90+
} else {
91+
logger.error('Failed to start management server');
92+
process.exit(1);
93+
}
94+
} catch (error) {
95+
logger.error('Error starting management server', error as Error);
96+
process.exit(1);
97+
}
98+
});
99+
100+
return cmd;
101+
}

src/module-system/module-loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class ModuleLoader {
7474
circularDependencyStrategy: options.circularDependencyStrategy || 'warn',
7575
externals: options.externals ?? [],
7676
maxCacheSize: options.maxCacheSize ?? 1000, // Default 1000 modules
77-
maxCacheMemory: options.maxCacheMemory ?? 100 * 1024 * 1024, // Default 100MB
77+
maxCacheMemory: options.maxCacheMemory ?? 512 * 1024 * 1024, // Default 512MB
7878
};
7979

8080
// Initialize production systems only when explicitly provided

0 commit comments

Comments
 (0)