@@ -6,57 +6,84 @@ import {fileURLToPath} from 'url';
66import { createStream } from 'rotating-file-stream' ;
77import dotenv from 'dotenv' ;
88
9- dotenv . config ( ) ; //加载 .env 文件
9+ dotenv . config ( ) ;
1010
11- const LOG_WITH_FILE = process . env . LOG_WITH_FILE ;
11+ const LOG_WITH_FILE = Number ( process . env . LOG_WITH_FILE ) || 0 ;
1212const LOG_LEVEL = process . env . LOG_LEVEL && [ 'trace' , 'debug' , 'info' , 'warn' , 'error' , 'fatal' ] . includes ( process . env . LOG_LEVEL ) ? process . env . LOG_LEVEL : 'info' ;
1313const COOKIE_AUTH_CODE = process . env . COOKIE_AUTH_CODE || 'drpys' ;
1414console . log ( 'LOG_WITH_FILE:' , LOG_WITH_FILE ) ;
1515console . log ( 'LOG_LEVEL:' , LOG_LEVEL ) ;
1616console . log ( 'COOKIE_AUTH_CODE:' , COOKIE_AUTH_CODE ) ;
1717let _logger = true ;
18+ let logStream = null ;
1819
19- // 自定义时间戳函数,格式为 YYYY-MM-DD HH:mm:ss
20+ const __filename = fileURLToPath ( import . meta. url ) ;
21+ const __dirname = path . dirname ( __filename ) ;
22+ const logDirectory = path . join ( __dirname , '../logs' ) ;
23+
24+ // 检测操作系统
25+ const isWindows = process . platform === 'win32' ;
26+
27+ // 自定义时间戳函数
2028const customTimestamp = ( ) => {
2129 const now = new Date ( ) ;
22- const yyyy = now . getFullYear ( ) ;
23- const mm = String ( now . getMonth ( ) + 1 ) . padStart ( 2 , '0' ) ;
24- const dd = String ( now . getDate ( ) ) . padStart ( 2 , '0' ) ;
25- const hours = String ( now . getHours ( ) ) . padStart ( 2 , '0' ) ;
26- const minutes = String ( now . getMinutes ( ) ) . padStart ( 2 , '0' ) ;
27- const seconds = String ( now . getSeconds ( ) ) . padStart ( 2 , '0' ) ;
28- const formattedTime = `${ yyyy } -${ mm } -${ dd } ${ hours } :${ minutes } :${ seconds } ` ;
29- return `,"time":"${ formattedTime } "` ; // 返回格式化后的时间戳
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+ } ;
32+
33+ // 安全的文件路径生成函数
34+ const safeFileNameGenerator = ( time , index ) => {
35+ if ( ! time ) return "output.log" ;
36+
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 } ` ;
3040} ;
3141
42+
3243if ( LOG_WITH_FILE ) {
33- const __filename = fileURLToPath ( import . meta. url ) ;
34- const __dirname = path . dirname ( __filename ) ;
35- const logDirectory = path . join ( __dirname , '../logs' ) ;
3644 if ( ! fs . existsSync ( logDirectory ) ) {
37- fs . mkdirSync ( logDirectory ) ;
45+ fs . mkdirSync ( logDirectory , { recursive : true } ) ;
3846 }
39- const logStream = createStream ( path . join ( logDirectory , 'output.log' ) , {
40- size : '500M' , // 设置最大文件大小为 500MB
41- compress : true , // 自动压缩旧的日志文件
42- encoding : 'utf8' , // 设置日志文件的编码为 utf8
43- interval : '1d' // 每天轮转一次日志
47+
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
56+ } ;
57+
58+
59+ // 创建日志流
60+ logStream = createStream ( safeFileNameGenerator , streamOptions ) ;
61+
62+ // 添加错误处理
63+ logStream . on ( 'error' , ( err ) => {
64+ // console.error('日志流错误:', err);
65+ } ) ;
66+
67+ logStream . on ( 'rotated' , ( filename ) => {
68+ console . log ( '日志轮转完成:' , filename ) ;
4469 } ) ;
70+
4571 _logger = pino ( {
46- level : LOG_LEVEL , // 设置记录的最低日志级别
72+ level : LOG_LEVEL ,
4773 serializers : {
48- req : pino . stdSerializers . req , // 标准请求序列化器
49- res : pino . stdSerializers . res , // 标准响应序列化器
74+ req : pino . stdSerializers . req ,
75+ res : pino . stdSerializers . res ,
5076 } ,
5177 timestamp : customTimestamp ,
5278 } , logStream ) ;
79+
5380 console . log ( '日志输出到文件' ) ;
5481} else {
5582 _logger = pino ( {
56- level : LOG_LEVEL , // 设置记录的最低日志级别
83+ level : LOG_LEVEL ,
5784 serializers : {
58- req : pino . stdSerializers . req , // 标准请求序列化器
59- res : pino . stdSerializers . res , // 标准响应序列化器
85+ req : pino . stdSerializers . req ,
86+ res : pino . stdSerializers . res ,
6087 } ,
6188 timestamp : customTimestamp ,
6289 } ) ;
@@ -66,3 +93,64 @@ if (LOG_WITH_FILE) {
6693export const fastify = Fastify ( {
6794 logger : _logger ,
6895} ) ;
96+
97+ // 安全的轮转测试端点
98+ // if (LOG_WITH_FILE && logStream) {
99+ // fastify.get('/test-rotate', async (request, reply) => {
100+ // try {
101+ // // 确保日志流可用
102+ // if (!logStream || typeof logStream.write !== 'function') {
103+ // throw new Error('日志流不可用');
104+ // }
105+ //
106+ // // 写入轮转前的日志
107+ // const preRotateLog = '--- 手动触发轮转前的测试日志 ---\n';
108+ // await new Promise((resolve, reject) => {
109+ // logStream.write(preRotateLog, 'utf8', (err) => {
110+ // if (err) reject(err);
111+ // else resolve();
112+ // });
113+ // });
114+ //
115+ // // 确保写入完成
116+ // await new Promise(resolve => setTimeout(resolve, 100));
117+ //
118+ // // 触发轮转
119+ // logStream.rotate();
120+ //
121+ // // 等待轮转完成
122+ // await new Promise((resolve) => {
123+ // logStream.once('rotated', resolve);
124+ // });
125+ //
126+ // // 确保日志流在轮转后仍然可用
127+ // if (!logStream || typeof logStream.write !== 'function') {
128+ // throw new Error('轮转后日志流不可用');
129+ // }
130+ //
131+ // // 写入轮转后的日志
132+ // const postRotateLog = '--- 手动触发轮转后的测试日志 ---\n';
133+ // await new Promise((resolve, reject) => {
134+ // logStream.write(postRotateLog, 'utf8', (err) => {
135+ // if (err) reject(err);
136+ // else resolve();
137+ // });
138+ // });
139+ //
140+ // reply.send({
141+ // status: 'success',
142+ // message: '日志轮转已手动触发',
143+ // logDirectory: path.resolve(logDirectory)
144+ // });
145+ // } catch (err) {
146+ // console.error('轮转过程中出错:', err);
147+ // reply.status(500).send({
148+ // status: 'error',
149+ // message: '轮转失败',
150+ // error: err.message
151+ // });
152+ // }
153+ // });
154+ //
155+ // console.log('测试端点已注册: GET /test-rotate');
156+ // }
0 commit comments