auto commit
This commit is contained in:
parent
83f95cd94b
commit
93b364be2e
@ -58,6 +58,11 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
# - redis
|
# - redis
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
|
@ -12,8 +12,8 @@ services:
|
|||||||
# 개발 환경에서는 healthcheck 비활성화
|
# 개발 환경에서는 healthcheck 비활성화
|
||||||
volumes:
|
volumes:
|
||||||
- ../../wacefems/uploads:/app/uploads
|
- ../../wacefems/uploads:/app/uploads
|
||||||
healthcheck:
|
# healthcheck:
|
||||||
disable: true
|
# disable: true
|
||||||
|
|
||||||
fems-app:
|
fems-app:
|
||||||
ports:
|
ports:
|
||||||
|
80
fems-api/src/controllers/app/health/health.controller.js
Normal file
80
fems-api/src/controllers/app/health/health.controller.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// src/controllers/app/health/health.controller.js
|
||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const logger = require("../../../config/logger");
|
||||||
|
const { getSystemStatus } = require("../../../services/system.service");
|
||||||
|
|
||||||
|
// 기본 health check
|
||||||
|
router.get("/", async (req, res) => {
|
||||||
|
try {
|
||||||
|
// 시스템 기본 상태 반환
|
||||||
|
res.json({
|
||||||
|
status: "healthy",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
serverTime: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("Health check failed:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
status: "unhealthy",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
error: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 상세 health check
|
||||||
|
router.get("/detail", async (req, res) => {
|
||||||
|
try {
|
||||||
|
// 시스템 상세 상태 조회
|
||||||
|
const systemStatus = await getSystemStatus();
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
status: "healthy",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
serverTime: new Date().toISOString(),
|
||||||
|
details: {
|
||||||
|
database: systemStatus.database,
|
||||||
|
redis: systemStatus.redis,
|
||||||
|
services: systemStatus.services,
|
||||||
|
uptime: process.uptime(),
|
||||||
|
memory: process.memoryUsage(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("Detailed health check failed:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
status: "unhealthy",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
error: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Edge 서버 상태 확인용 특별 엔드포인트
|
||||||
|
router.get("/edge", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const edgeId = req.header("X-Edge-ID");
|
||||||
|
logger.info(`Health check from Edge server: ${edgeId}`);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
status: "healthy",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
serverTime: new Date().toISOString(),
|
||||||
|
edgeServer: {
|
||||||
|
id: edgeId,
|
||||||
|
lastCheck: new Date().toISOString(),
|
||||||
|
connectionStatus: "connected",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("Edge health check failed:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
status: "unhealthy",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
error: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -13,7 +13,9 @@ const personnelController = require("../controllers/app/personnel/personnel.cont
|
|||||||
const partsController = require("../controllers/app/parts/parts.controller");
|
const partsController = require("../controllers/app/parts/parts.controller");
|
||||||
const equipmentPartsController = require("../controllers/app/equipmentParts/equipmentParts.controller"); // 추가
|
const equipmentPartsController = require("../controllers/app/equipmentParts/equipmentParts.controller"); // 추가
|
||||||
const departmentController = require("../controllers/app/department/department.controller");
|
const departmentController = require("../controllers/app/department/department.controller");
|
||||||
|
const healthController = require("../controllers/app/health/health.controller");
|
||||||
|
|
||||||
|
router.use("/health", healthController);
|
||||||
router.use("/auth", authController);
|
router.use("/auth", authController);
|
||||||
router.use("/users", usersController);
|
router.use("/users", usersController);
|
||||||
router.use("/dashboard", dashboardController);
|
router.use("/dashboard", dashboardController);
|
||||||
|
123
fems-api/src/services/system.service.js
Normal file
123
fems-api/src/services/system.service.js
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// src/services/system.service.js
|
||||||
|
const Redis = require("ioredis");
|
||||||
|
const mongoose = require("mongoose");
|
||||||
|
const logger = require("../config/logger");
|
||||||
|
const config = require("../config/config");
|
||||||
|
|
||||||
|
class SystemService {
|
||||||
|
constructor() {
|
||||||
|
this.redis = new Redis(config.redis);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSystemStatus() {
|
||||||
|
try {
|
||||||
|
// Redis 상태 체크
|
||||||
|
// const redisStatus = await this.checkRedisStatus();
|
||||||
|
|
||||||
|
// 데이터베이스 상태 체크
|
||||||
|
// const dbStatus = await this.checkDatabaseStatus();
|
||||||
|
|
||||||
|
// 서비스 상태 체크
|
||||||
|
const servicesStatus = await this.checkServicesStatus();
|
||||||
|
|
||||||
|
return {
|
||||||
|
// database: dbStatus,
|
||||||
|
// redis: redisStatus,
|
||||||
|
services: servicesStatus,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("Failed to get system status:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// async checkRedisStatus() {
|
||||||
|
// try {
|
||||||
|
// await this.redis.ping();
|
||||||
|
// return {
|
||||||
|
// status: "healthy",
|
||||||
|
// latency: await this.measureRedisLatency(),
|
||||||
|
// };
|
||||||
|
// } catch (error) {
|
||||||
|
// logger.error("Redis health check failed:", error);
|
||||||
|
// return {
|
||||||
|
// status: "unhealthy",
|
||||||
|
// error: error.message,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async checkDatabaseStatus() {
|
||||||
|
// try {
|
||||||
|
// const status = mongoose.connection.readyState;
|
||||||
|
// const statusMap = {
|
||||||
|
// 0: "disconnected",
|
||||||
|
// 1: "connected",
|
||||||
|
// 2: "connecting",
|
||||||
|
// 3: "disconnecting",
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// status: status === 1 ? "healthy" : "unhealthy",
|
||||||
|
// state: statusMap[status],
|
||||||
|
// latency: await this.measureDatabaseLatency(),
|
||||||
|
// };
|
||||||
|
// } catch (error) {
|
||||||
|
// logger.error("Database health check failed:", error);
|
||||||
|
// return {
|
||||||
|
// status: "unhealthy",
|
||||||
|
// error: error.message,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
async checkServicesStatus() {
|
||||||
|
// 필요한 서비스들의 상태 체크
|
||||||
|
const services = {
|
||||||
|
api: await this.checkAPIStatus(),
|
||||||
|
scheduler: await this.checkSchedulerStatus(),
|
||||||
|
worker: await this.checkWorkerStatus(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
async measureRedisLatency() {
|
||||||
|
const start = process.hrtime();
|
||||||
|
await this.redis.ping();
|
||||||
|
const [seconds, nanoseconds] = process.hrtime(start);
|
||||||
|
return (seconds * 1000 + nanoseconds / 1000000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
async measureDatabaseLatency() {
|
||||||
|
const start = process.hrtime();
|
||||||
|
await mongoose.connection.db.admin().ping();
|
||||||
|
const [seconds, nanoseconds] = process.hrtime(start);
|
||||||
|
return (seconds * 1000 + nanoseconds / 1000000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkAPIStatus() {
|
||||||
|
return {
|
||||||
|
status: "healthy",
|
||||||
|
uptime: process.uptime(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkSchedulerStatus() {
|
||||||
|
// 스케줄러 상태 체크 로직
|
||||||
|
return {
|
||||||
|
status: "healthy",
|
||||||
|
lastRun: new Date().toISOString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkWorkerStatus() {
|
||||||
|
// 워커 상태 체크 로직
|
||||||
|
return {
|
||||||
|
status: "healthy",
|
||||||
|
activeWorkers: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new SystemService();
|
Loading…
Reference in New Issue
Block a user