Files
ai-showcase-platform/lib/database-monitor.ts

167 lines
4.6 KiB
TypeScript

// =====================================================
// 資料庫連線監控工具
// =====================================================
import { db } from './database';
export class DatabaseMonitor {
private static instance: DatabaseMonitor;
private connectionCount = 0;
private maxConnections = 0;
private isMonitoring = false;
private monitorInterval: NodeJS.Timeout | null = null;
private constructor() {}
public static getInstance(): DatabaseMonitor {
if (!DatabaseMonitor.instance) {
DatabaseMonitor.instance = new DatabaseMonitor();
}
return DatabaseMonitor.instance;
}
// 開始監控
public startMonitoring(intervalMs: number = 30000) {
if (this.isMonitoring) {
console.log('⚠️ 資料庫監控已在運行中');
return;
}
this.isMonitoring = true;
console.log('🔍 開始監控資料庫連線狀態...');
this.monitorInterval = setInterval(async () => {
await this.checkConnectionStatus();
}, intervalMs);
// 立即執行一次檢查
this.checkConnectionStatus();
}
// 停止監控
public stopMonitoring() {
if (this.monitorInterval) {
clearInterval(this.monitorInterval);
this.monitorInterval = null;
}
this.isMonitoring = false;
console.log('⏹️ 資料庫監控已停止');
}
// 檢查連線狀態
private async checkConnectionStatus() {
try {
// 檢查當前連線數
const statusResult = await db.queryOne(`
SHOW STATUS LIKE 'Threads_connected'
`);
const currentConnections = statusResult?.Value || 0;
this.connectionCount = parseInt(currentConnections);
// 檢查最大連線數
const maxConnResult = await db.queryOne(`
SHOW VARIABLES LIKE 'max_connections'
`);
this.maxConnections = parseInt(maxConnResult?.Value || '100');
// 檢查連線使用率
const usagePercentage = (this.connectionCount / this.maxConnections) * 100;
// 記錄狀態
console.log(`📊 資料庫連線狀態: ${this.connectionCount}/${this.maxConnections} (${usagePercentage.toFixed(1)}%)`);
// 警告檢查
if (usagePercentage > 80) {
console.warn(`⚠️ 資料庫連線使用率過高: ${usagePercentage.toFixed(1)}%`);
} else if (usagePercentage > 60) {
console.log(`⚠️ 資料庫連線使用率較高: ${usagePercentage.toFixed(1)}%`);
}
// 檢查長時間運行的查詢
await this.checkLongRunningQueries();
} catch (error) {
console.error('❌ 資料庫監控錯誤:', error);
}
}
// 檢查長時間運行的查詢
private async checkLongRunningQueries() {
try {
const longQueries = await db.query(`
SELECT
ID,
USER,
HOST,
DB,
COMMAND,
TIME,
STATE,
INFO
FROM information_schema.PROCESSLIST
WHERE TIME > 30
AND COMMAND != 'Sleep'
ORDER BY TIME DESC
LIMIT 5
`);
if (longQueries.length > 0) {
console.warn(`⚠️ 發現 ${longQueries.length} 個長時間運行的查詢:`);
longQueries.forEach((query, index) => {
console.warn(` ${index + 1}. 用戶: ${query.USER}, 時間: ${query.TIME}s, 狀態: ${query.STATE}`);
if (query.INFO && query.INFO.length > 100) {
console.warn(` 查詢: ${query.INFO.substring(0, 100)}...`);
} else if (query.INFO) {
console.warn(` 查詢: ${query.INFO}`);
}
});
}
} catch (error) {
console.error('❌ 檢查長時間查詢時發生錯誤:', error);
}
}
// 獲取連線統計
public getConnectionStats() {
return {
currentConnections: this.connectionCount,
maxConnections: this.maxConnections,
usagePercentage: (this.connectionCount / this.maxConnections) * 100,
isMonitoring: this.isMonitoring
};
}
// 強制釋放空閒連線
public async releaseIdleConnections() {
try {
const result = await db.query(`
KILL
(SELECT GROUP_CONCAT(ID)
FROM information_schema.PROCESSLIST
WHERE COMMAND = 'Sleep'
AND TIME > 300)
`);
console.log('🔄 已嘗試釋放空閒連線');
return true;
} catch (error) {
console.error('❌ 釋放空閒連線失敗:', error);
return false;
}
}
// 獲取連線池狀態
public getPoolStatus() {
// 這裡可以添加更多連線池狀態信息
return {
isMonitoring: this.isMonitoring,
lastCheck: new Date().toISOString()
};
}
}
// 導出單例實例
export const dbMonitor = DatabaseMonitor.getInstance();