feat: add gateway management features and settings
- Implemented new API routes for handling logs and settings related to the gateway. - Added a new Gateway section in the General Settings panel to manage gateway status and auto-start options. - Introduced a state management hook for gateway settings, including status, logs, and auto-start functionality. - Updated configuration service to include gateway auto-start setting. - Enhanced internationalization support for new gateway-related messages. - Refactored existing settings store to accommodate new gateway settings. - Cleaned up code and improved logging functionality.
This commit is contained in:
@@ -13,6 +13,7 @@ const unlinkAsync = promisify(fs.unlink);
|
||||
|
||||
class LogService {
|
||||
private static _instance: LogService;
|
||||
private readonly logDirPath: string;
|
||||
|
||||
// 日志保留天数,默认7天
|
||||
private LOG_RETENTION_DAYS = 7;
|
||||
@@ -21,7 +22,8 @@ class LogService {
|
||||
private readonly CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
private constructor() {
|
||||
const logPath = path.join(getUserDataDir(), 'logs');
|
||||
this.logDirPath = path.join(getUserDataDir(), 'logs');
|
||||
const logPath = this.logDirPath;
|
||||
// c:users/{username}/AppData/Roaming/{appName}/logs
|
||||
|
||||
// 创建日志目录
|
||||
@@ -175,6 +177,54 @@ class LogService {
|
||||
this.info(`User Operation: ${operation} by ${userId}, Details: ${JSON.stringify(details)}`);
|
||||
}
|
||||
|
||||
public async readRecentLogText(tailLines: number = 200): Promise<string> {
|
||||
const safeTailLines = Number.isFinite(tailLines) ? Math.max(1, Math.floor(tailLines)) : 200;
|
||||
const filePath = this._getCurrentLogFilePath();
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const file = await fs.promises.open(filePath, 'r');
|
||||
|
||||
try {
|
||||
const fileStat = await file.stat();
|
||||
if (fileStat.size === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const chunkSize = 64 * 1024;
|
||||
let position = fileStat.size;
|
||||
let content = '';
|
||||
let lineCount = 0;
|
||||
|
||||
while (position > 0 && lineCount <= safeTailLines) {
|
||||
const bytesToRead = Math.min(chunkSize, position);
|
||||
position -= bytesToRead;
|
||||
|
||||
const buffer = Buffer.allocUnsafe(bytesToRead);
|
||||
await file.read(buffer, 0, bytesToRead, position);
|
||||
content = `${buffer.toString('utf-8')}${content}`;
|
||||
lineCount = content.split('\n').length - 1;
|
||||
}
|
||||
|
||||
const lines = content.split('\n');
|
||||
if (lines.length <= safeTailLines) {
|
||||
return content;
|
||||
}
|
||||
|
||||
return lines.slice(-safeTailLines).join('\n');
|
||||
} finally {
|
||||
await file.close();
|
||||
}
|
||||
}
|
||||
|
||||
private _getCurrentLogFilePath(): string {
|
||||
const today = new Date();
|
||||
const formattedDate = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
|
||||
return path.join(this.logDirPath, `${formattedDate}.log`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const logManager = LogService.getInstance();
|
||||
|
||||
Reference in New Issue
Block a user