Skip to content

Commit 0182691

Browse files
author
Taois
committed
feat: 日志优化
1 parent 4bfb75a commit 0182691

File tree

3 files changed

+187
-127
lines changed

3 files changed

+187
-127
lines changed

controllers/fastlogger.js

Lines changed: 105 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,114 +6,131 @@ import {fileURLToPath} from 'url';
66
import {createStream} from 'rotating-file-stream';
77
import dotenv from 'dotenv';
88

9-
dotenv.config();
10-
11-
const LOG_WITH_FILE = Number(process.env.LOG_WITH_FILE) || 0;
12-
const LOG_LEVEL = process.env.LOG_LEVEL && ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].includes(process.env.LOG_LEVEL) ? process.env.LOG_LEVEL : 'info';
13-
const COOKIE_AUTH_CODE = process.env.COOKIE_AUTH_CODE || 'drpys';
14-
// console.log('LOG_WITH_FILE:', LOG_WITH_FILE);
15-
// console.log('LOG_LEVEL:', LOG_LEVEL);
16-
// console.log('COOKIE_AUTH_CODE:', COOKIE_AUTH_CODE);
17-
let _logger = true;
18-
let logStream = null;
19-
209
const __filename = fileURLToPath(import.meta.url);
2110
const __dirname = path.dirname(__filename);
22-
const logDirectory = path.join(__dirname, '../logs');
2311

24-
// 检测操作系统
25-
const isWindows = process.platform === 'win32';
12+
// 使用 Symbol 作为全局键,防止命名冲突
13+
const FASTIFY_INSTANCE_KEY = Symbol.for('drpy-node.fastify.instances');
2614

27-
// 自定义时间戳函数
28-
const customTimestamp = () => {
29-
const now = new Date();
30-
return `,"time":"${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}"`;
31-
};
15+
// 初始化函数,仅执行一次
16+
function initializeFastify() {
17+
if (globalThis[FASTIFY_INSTANCE_KEY]) {
18+
return globalThis[FASTIFY_INSTANCE_KEY];
19+
}
3220

33-
// 安全的文件路径生成函数
34-
const safeFileNameGenerator = (time, index) => {
35-
if (!time) return "output.log";
21+
dotenv.config();
3622

37-
// 确保文件名中不包含路径分隔符
38-
const dateStr = `${time.getFullYear()}-${String(time.getMonth() + 1).padStart(2, '0')}-${String(time.getDate()).padStart(2, '0')}`;
39-
return `output-${dateStr}.log.${index || 1}`;
40-
};
23+
const LOG_WITH_FILE = Number(process.env.LOG_WITH_FILE) || 0;
24+
const LOG_LEVEL = process.env.LOG_LEVEL && ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].includes(process.env.LOG_LEVEL) ? process.env.LOG_LEVEL : 'info';
4125

26+
let _logger = true;
27+
let logStream = null;
28+
const logDirectory = path.join(__dirname, '../logs');
4229

43-
if (LOG_WITH_FILE) {
44-
if (!fs.existsSync(logDirectory)) {
45-
fs.mkdirSync(logDirectory, {recursive: true});
46-
}
30+
// 自定义时间戳函数
31+
const customTimestamp = () => {
32+
const now = new Date();
33+
return `,"time":"${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}"`;
34+
};
4735

48-
// 配置选项
49-
const streamOptions = {
50-
size: '500M',
51-
// compress: isWindows ? false : 'gzip', // Windows 上禁用压缩
52-
compress: false,
53-
interval: '1d',
54-
path: logDirectory,
55-
maxFiles: 30
36+
// 安全的文件路径生成函数
37+
const safeFileNameGenerator = (time, index) => {
38+
if (!time) return "output.log";
39+
const dateStr = `${time.getFullYear()}-${String(time.getMonth() + 1).padStart(2, '0')}-${String(time.getDate()).padStart(2, '0')}`;
40+
return `output-${dateStr}.log.${index || 1}`;
5641
};
5742

43+
if (LOG_WITH_FILE) {
44+
if (!fs.existsSync(logDirectory)) {
45+
try {
46+
fs.mkdirSync(logDirectory, {recursive: true});
47+
} catch (e) {
48+
console.error('[FastLogger] Failed to create log directory:', e);
49+
}
50+
}
5851

59-
// 创建日志流
60-
logStream = createStream(safeFileNameGenerator, streamOptions);
52+
const streamOptions = {
53+
size: '500M',
54+
compress: false,
55+
interval: '1d',
56+
path: logDirectory,
57+
maxFiles: 30
58+
};
59+
60+
try {
61+
logStream = createStream(safeFileNameGenerator, streamOptions);
62+
logStream.on('error', (err) => {
63+
// console.error('日志流错误:', err);
64+
});
65+
logStream.on('rotated', (filename) => {
66+
console.log('日志轮转完成:', filename);
67+
});
68+
69+
_logger = pino({
70+
level: LOG_LEVEL,
71+
serializers: {
72+
req: pino.stdSerializers.req,
73+
res: pino.stdSerializers.res,
74+
},
75+
timestamp: customTimestamp,
76+
}, logStream);
77+
console.log('日志输出到文件');
78+
} catch (error) {
79+
console.error('[FastLogger] Failed to initialize file logger, falling back to console:', error);
80+
_logger = pino({
81+
level: LOG_LEVEL,
82+
timestamp: customTimestamp,
83+
});
84+
}
85+
} else {
86+
_logger = pino({
87+
level: LOG_LEVEL,
88+
serializers: {
89+
req: pino.stdSerializers.req,
90+
res: pino.stdSerializers.res,
91+
},
92+
timestamp: customTimestamp,
93+
});
94+
console.log('日志输出到控制台');
95+
}
6196

62-
// 添加错误处理
63-
logStream.on('error', (err) => {
64-
// console.error('日志流错误:', err);
97+
const _fastify = Fastify({
98+
logger: _logger,
6599
});
66100

67-
logStream.on('rotated', (filename) => {
68-
console.log('日志轮转完成:', filename);
101+
const _wsApp = Fastify({
102+
logger: _logger,
69103
});
70104

71-
_logger = pino({
72-
level: LOG_LEVEL,
73-
serializers: {
74-
req: pino.stdSerializers.req,
75-
res: pino.stdSerializers.res,
76-
},
77-
timestamp: customTimestamp,
78-
}, logStream);
79-
80-
console.log('日志输出到文件');
81-
} else {
82-
_logger = pino({
83-
level: LOG_LEVEL,
84-
serializers: {
85-
req: pino.stdSerializers.req,
86-
res: pino.stdSerializers.res,
87-
},
88-
timestamp: customTimestamp,
105+
// 添加CORS支持的钩子
106+
[_fastify, _wsApp].forEach(server => {
107+
server.addHook('onRequest', async (request, reply) => {
108+
reply.header('Access-Control-Allow-Origin', '*');
109+
reply.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
110+
reply.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
111+
reply.header('Access-Control-Allow-Credentials', 'true');
112+
113+
if (request.method === 'OPTIONS') {
114+
reply.status(200).send();
115+
return;
116+
}
117+
});
89118
});
90-
console.log('日志输出到控制台');
119+
120+
const instances = {
121+
fastify: _fastify,
122+
wsApp: _wsApp,
123+
logger: _logger
124+
};
125+
126+
globalThis[FASTIFY_INSTANCE_KEY] = instances;
127+
return instances;
91128
}
92129

93-
export const fastify = Fastify({
94-
logger: _logger,
95-
});
96-
97-
export const wsApp = Fastify({
98-
logger: _logger,
99-
});
100-
101-
// 添加CORS支持的钩子
102-
[fastify, wsApp].forEach(server => {
103-
server.addHook('onRequest', async (request, reply) => {
104-
// 设置CORS头部
105-
reply.header('Access-Control-Allow-Origin', '*');
106-
reply.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
107-
reply.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
108-
reply.header('Access-Control-Allow-Credentials', 'true');
109-
110-
// 处理预检请求
111-
if (request.method === 'OPTIONS') {
112-
reply.status(200).send();
113-
return;
114-
}
115-
});
116-
});
130+
const {fastify: fastifyInstance, wsApp: wsAppInstance} = initializeFastify();
131+
132+
export const fastify = fastifyInstance;
133+
export const wsApp = wsAppInstance;
117134

118135
// 安全的轮转测试端点
119136
// if (LOG_WITH_FILE && logStream) {

0 commit comments

Comments
 (0)