system health 추가

This commit is contained in:
2025-12-15 09:18:49 +09:00
parent edf8681ea0
commit 15c0ad0a1a
4 changed files with 114 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ import { GenomeModule } from './genome/genome.module';
import { MptModule } from './mpt/mpt.module';
import { DashboardModule } from './dashboard/dashboard.module';
import { GeneModule } from './gene/gene.module';
import { SystemModule } from './system/system.module';
@Module({
imports: [
@@ -61,6 +62,7 @@ import { GeneModule } from './gene/gene.module';
// 기타
HelpModule,
SystemModule,
],
controllers: [AppController],
providers: [AppService, JwtStrategy],

View File

@@ -0,0 +1,14 @@
import { Controller, Get } from '@nestjs/common';
import { SystemService, SystemHealthResponse } from './system.service';
import { Public } from '../common/decorators/public.decorator';
@Controller('system')
export class SystemController {
constructor(private readonly systemService: SystemService) {}
@Public()
@Get('health')
async getHealth(): Promise<SystemHealthResponse> {
return this.systemService.getHealth();
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { SystemController } from './system.controller';
import { SystemService } from './system.service';
@Module({
controllers: [SystemController],
providers: [SystemService],
})
export class SystemModule {}

View File

@@ -0,0 +1,89 @@
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { InjectRedis } from '@nestjs-modules/ioredis';
import Redis from 'ioredis';
export interface SystemHealthResponse {
status: 'ok' | 'error';
timestamp: string;
environment: string;
database: {
host: string;
port: number;
database: string;
user: string;
status: 'connected' | 'disconnected';
error?: string;
};
redis: {
host: string;
port: number;
status: 'connected' | 'disconnected';
error?: string;
};
}
@Injectable()
export class SystemService {
constructor(
private configService: ConfigService,
@InjectDataSource() private dataSource: DataSource,
@InjectRedis() private redis: Redis,
) {}
async getHealth(): Promise<SystemHealthResponse> {
const dbHealth = await this.checkDatabase();
const redisHealth = await this.checkRedis();
return {
status: dbHealth.status === 'connected' && redisHealth.status === 'connected' ? 'ok' : 'error',
timestamp: new Date().toISOString(),
environment: this.configService.get('NODE_ENV') || 'development',
database: dbHealth,
redis: redisHealth,
};
}
private async checkDatabase() {
const config = {
host: this.configService.get('POSTGRES_HOST') || 'unknown',
port: parseInt(this.configService.get('POSTGRES_PORT')) || 5432,
database: this.configService.get('POSTGRES_DB') || 'unknown',
user: this.configService.get('POSTGRES_USER') || 'unknown',
};
try {
await this.dataSource.query('SELECT 1');
return { ...config, status: 'connected' as const };
} catch (error) {
return { ...config, status: 'disconnected' as const, error: error.message };
}
}
private async checkRedis() {
const redisUrl = this.configService.get('REDIS_URL') || '';
let host = this.configService.get('REDIS_HOST') || 'unknown';
let port = parseInt(this.configService.get('REDIS_PORT')) || 6379;
if (redisUrl) {
try {
const url = new URL(redisUrl);
host = url.hostname;
port = parseInt(url.port) || 6379;
} catch {}
}
try {
const pong = await this.redis.ping();
return {
host,
port,
status: pong === 'PONG' ? 'connected' as const : 'disconnected' as const,
};
} catch (error) {
return { host, port, status: 'disconnected' as const, error: error.message };
}
}
}