@@ -6,114 +6,131 @@ import {fileURLToPath} from 'url';
66import { createStream } from 'rotating-file-stream' ;
77import 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-
209const __filename = fileURLToPath ( import . meta. url ) ;
2110const __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