251124:1700 Ready to Phase 7

This commit is contained in:
admin
2025-11-24 17:01:58 +07:00
parent 9360d78ea6
commit 4f45a69ed0
47 changed files with 2047 additions and 433 deletions
@@ -0,0 +1,45 @@
// File: src/modules/monitoring/controllers/health.controller.ts
import { Controller, Get } from '@nestjs/common';
import {
HealthCheckService,
HttpHealthIndicator,
HealthCheck,
TypeOrmHealthIndicator,
MemoryHealthIndicator,
DiskHealthIndicator,
} from '@nestjs/terminus';
import { MetricsService } from '../services/metrics.service';
@Controller()
export class HealthController {
constructor(
private health: HealthCheckService,
private http: HttpHealthIndicator,
private db: TypeOrmHealthIndicator,
private memory: MemoryHealthIndicator,
private disk: DiskHealthIndicator,
private metricsService: MetricsService,
) {}
@Get('health')
@HealthCheck()
check() {
return this.health.check([
// 1. ตรวจสอบการเชื่อมต่อ Database (MariaDB)
() => this.db.pingCheck('database'),
// 2. ตรวจสอบ Memory Heap (ไม่ควรเกิน 1GB สำหรับ Container นี้ - ปรับค่าตามจริง)
() => this.memory.checkHeap('memory_heap', 1024 * 1024 * 1024),
// 3. ตรวจสอบพื้นที่ Disk สำหรับ DMS Data (Threshold 90%)
// path '/' อาจต้องเปลี่ยนเป็น '/share/dms-data' ตาม Environment จริง
() =>
this.disk.checkStorage('storage', { path: '/', thresholdPercent: 0.9 }),
]);
}
@Get('metrics')
async getMetrics() {
return await this.metricsService.getMetrics();
}
}
@@ -0,0 +1,30 @@
// File: src/modules/monitoring/logger/winston.config.ts
import {
utilities as nestWinstonUtilities,
WinstonModuleOptions,
} from 'nest-winston';
import * as winston from 'winston';
/**
* ฟังก์ชันสร้าง Configuration สำหรับ Winston Logger
* - Development: แสดงผลแบบ Console อ่านง่าย
* - Production: แสดงผลแบบ JSON พร้อม Timestamp เพื่อการทำ Log Aggregation
*/
export const winstonConfig: WinstonModuleOptions = {
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
// เลือก Format ตาม Environment
process.env.NODE_ENV === 'production'
? winston.format.json() // Production ใช้ JSON
: nestWinstonUtilities.format.nestLike('LCBP3-DMS', {
prettyPrint: true,
colors: true,
}),
),
}),
// สามารถเพิ่ม File Transport หรือ HTTP Transport ไปยัง Log Server ได้ที่นี่
],
};
@@ -0,0 +1,23 @@
// File: src/modules/monitoring/monitoring.module.ts
import { Global, Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { HttpModule } from '@nestjs/axios';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { HealthController } from './controllers/health.controller';
import { MetricsService } from './services/metrics.service';
import { PerformanceInterceptor } from '../../common/interceptors/performance.interceptor';
@Global() // ทำให้ Module นี้ใช้งานได้ทั่วทั้ง App โดยไม่ต้อง Import ซ้ำ
@Module({
imports: [TerminusModule, HttpModule],
controllers: [HealthController],
providers: [
MetricsService,
{
provide: APP_INTERCEPTOR, // Register Global Interceptor
useClass: PerformanceInterceptor,
},
],
exports: [MetricsService],
})
export class MonitoringModule {}
@@ -0,0 +1,54 @@
// File: src/modules/monitoring/services/metrics.service.ts
import { Injectable } from '@nestjs/common';
import { Registry, Counter, Histogram, Gauge } from 'prom-client';
@Injectable()
export class MetricsService {
private readonly registry: Registry;
public readonly httpRequestsTotal: Counter<string>;
public readonly httpRequestDuration: Histogram<string>;
public readonly systemMemoryUsage: Gauge<string>;
constructor() {
this.registry = new Registry();
this.registry.setDefaultLabels({ app: 'lcbp3-backend' });
// นับจำนวน HTTP Request ทั้งหมด แยกตาม method, route, status_code
this.httpRequestsTotal = new Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status_code'],
registers: [this.registry],
});
// วัดระยะเวลา Response Time (Histogram)
this.httpRequestDuration = new Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.1, 0.2, 0.5, 1.0, 1.5, 2.0, 5.0], // Buckets สำหรับวัด Latency
registers: [this.registry],
});
// วัดการใช้ Memory (Gauge)
this.systemMemoryUsage = new Gauge({
name: 'system_memory_usage_bytes',
help: 'Heap memory usage in bytes',
registers: [this.registry],
});
// เริ่มเก็บ Metrics พื้นฐานของ Node.js (Optional)
// client.collectDefaultMetrics({ register: this.registry });
}
/**
* ดึงข้อมูล Metrics ทั้งหมดในรูปแบบ Text สำหรับ Prometheus Scrape
*/
async getMetrics(): Promise<string> {
// อัปเดต Memory Usage ก่อน Return
const memoryUsage = process.memoryUsage();
this.systemMemoryUsage.set(memoryUsage.heapUsed);
return this.registry.metrics();
}
}