@@ -8,8 +8,9 @@ const IS_WORKER = typeof window === 'undefined'
88// DO NOT use `constants.ts` here, because the files contains other dependencies that will fail in worker process
99const IS_DEV = IS_WORKER ? false : window . electron ?. process ?. env ?. NODE_ENV === 'development'
1010
11- const DEFAULT_LEVEL = IS_DEV ? LEVEL . SILLY : LEVEL . INFO
12- const MAIN_LOG_LEVEL = LEVEL . WARN
11+ // 更严格的生产环境日志级别控制
12+ const DEFAULT_LEVEL = IS_DEV ? LEVEL . DEBUG : LEVEL . WARN // 生产环境默认只记录警告以上
13+ const MAIN_LOG_LEVEL = IS_DEV ? LEVEL . WARN : LEVEL . ERROR // 生产环境主进程只记录错误
1314
1415// 日志导出相关接口
1516interface LogExportEntry {
@@ -54,9 +55,12 @@ class LoggerService {
5455 private module : string = ''
5556 private context : Record < string , any > = { }
5657
57- // 日志导出相关
58+ // 日志导出相关 - 优化内存管理
5859 private exportHistory : LogExportEntry [ ] = [ ]
59- private maxHistorySize : number = 10000
60+ private maxHistorySize : number = 1000 // 降低到 1000 条记录,减少内存占用
61+ private lastCleanupTime : number = 0
62+ private readonly CLEANUP_INTERVAL = 30000 // 30秒清理一次
63+ private readonly MEMORY_PRESSURE_THRESHOLD = 500 // 内存压力阈值
6064
6165 private constructor ( ) {
6266 if ( IS_DEV ) {
@@ -134,100 +138,82 @@ class LoggerService {
134138 return newLogger
135139 }
136140
137- // ---- 对象完全序列化方法 ----
138- private deepSerialize ( obj : any , visited = new WeakSet ( ) ) : any {
141+ // ---- 轻量化序列化方法 - 优化内存使用 ----
142+ private lightSerialize ( obj : any , maxDepth = 3 , currentDepth = 0 ) : any {
143+ // 超过最大深度,简化处理
144+ if ( currentDepth >= maxDepth ) {
145+ if ( obj === null || obj === undefined ) return obj
146+ if ( typeof obj === 'string' ) return obj . length > 100 ? obj . slice ( 0 , 100 ) + '...' : obj
147+ if ( typeof obj === 'number' || typeof obj === 'boolean' ) return obj
148+ return '[Max Depth Reached]'
149+ }
150+
139151 // 处理基本类型
140152 if ( obj === null || typeof obj !== 'object' ) {
141153 return obj
142154 }
143155
144- // 防止循环引用
145- if ( visited . has ( obj ) ) {
146- return '[Circular Reference]'
147- }
148- visited . add ( obj )
149-
150156 try {
151157 // 处理日期对象
152158 if ( obj instanceof Date ) {
153- return { __type : 'Date' , value : obj . toISOString ( ) }
159+ return obj . toISOString ( )
154160 }
155161
156- // 处理错误对象
162+ // 处理错误对象 - 简化
157163 if ( obj instanceof Error ) {
158164 return {
159165 __type : 'Error' ,
160166 name : obj . name ,
161167 message : obj . message ,
162- stack : obj . stack ,
163- ...Object . getOwnPropertyNames ( obj ) . reduce ( ( acc , key ) => {
164- acc [ key ] = this . deepSerialize ( ( obj as any ) [ key ] , visited )
165- return acc
166- } , { } as any )
168+ stack : obj . stack ?. split ( '\n' ) . slice ( 0 , 3 ) . join ( '\n' ) // 只保留前3行堆栈
167169 }
168170 }
169171
170- // 处理函数
172+ // 处理函数 - 极简化
171173 if ( typeof obj === 'function' ) {
172- return {
173- __type : 'Function' ,
174- name : obj . name ,
175- toString : obj . toString ( )
176- }
174+ return `[Function: ${ obj . name || 'anonymous' } ]`
177175 }
178176
179- // 处理数组
177+ // 处理数组 - 限制长度
180178 if ( Array . isArray ( obj ) ) {
181- return obj . map ( ( item ) => this . deepSerialize ( item , visited ) )
179+ const maxItems = 10
180+ if ( obj . length > maxItems ) {
181+ return [
182+ ...obj
183+ . slice ( 0 , maxItems )
184+ . map ( ( item ) => this . lightSerialize ( item , maxDepth , currentDepth + 1 ) ) ,
185+ `[... ${ obj . length - maxItems } more items]`
186+ ]
187+ }
188+ return obj . map ( ( item ) => this . lightSerialize ( item , maxDepth , currentDepth + 1 ) )
182189 }
183190
184- // 处理普通对象
191+ // 处理普通对象 - 只序列化可枚举属性
185192 const result : any = { }
193+ const keys = Object . keys ( obj )
194+ const maxKeys = 20 // 限制最多序列化20个属性
186195
187- // 获取所有属性(包括不可枚举的)
188- const keys = [
189- ...Object . keys ( obj ) ,
190- ...Object . getOwnPropertyNames ( obj ) . filter (
191- ( key ) => key !== 'constructor' && ! Object . keys ( obj ) . includes ( key )
192- )
193- ]
194-
195- for ( const key of keys ) {
196+ for ( let i = 0 ; i < Math . min ( keys . length , maxKeys ) ; i ++ ) {
197+ const key = keys [ i ]
196198 try {
197- const descriptor = Object . getOwnPropertyDescriptor ( obj , key )
198- if ( descriptor ) {
199- if ( descriptor . get || descriptor . set ) {
200- // 处理 getter/setter
201- result [ key ] = {
202- __type : 'Property' ,
203- hasGetter : ! ! descriptor . get ,
204- hasSetter : ! ! descriptor . set ,
205- enumerable : descriptor . enumerable ,
206- configurable : descriptor . configurable
207- }
208- } else {
209- // 普通属性
210- result [ key ] = this . deepSerialize ( descriptor . value , visited )
211- }
199+ // 跳过可能导致循环引用的属性
200+ if ( key . includes ( 'parent' ) || key . includes ( 'owner' ) || key . includes ( 'target' ) ) {
201+ result [ key ] = '[Skipped - Potential Circular]'
202+ continue
212203 }
204+ result [ key ] = this . lightSerialize ( obj [ key ] , maxDepth , currentDepth + 1 )
213205 } catch ( error ) {
214- result [ key ] = `[Error accessing property: ${
215- error instanceof Error ? error . message : 'Unknown error'
216- } ]`
206+ result [ key ] = '[Serialization Error]'
217207 }
218208 }
219209
220- // 添加原型信息
221- const proto = Object . getPrototypeOf ( obj )
222- if ( proto && proto !== Object . prototype ) {
223- result . __prototype = proto . constructor ?. name || '[Unknown Prototype]'
210+ if ( keys . length > maxKeys ) {
211+ result [ '[...]' ] = `${ keys . length - maxKeys } more properties`
224212 }
225213
226214 return result
227215 } catch ( error ) {
228- return `[Serialization Error: ${ error instanceof Error ? error . message : 'Unknown error' } ]`
229- } finally {
230- visited . delete ( obj )
216+ return '[Serialization Error]'
231217 }
232218 }
233219
@@ -520,33 +506,121 @@ class LoggerService {
520506
521507 // ---- 日志导出方法 ----
522508 /**
523- * 添加日志到导出历史
509+ * 添加日志到导出历史 - 优化内存管理,生产环境禁用
524510 */
525511 private addToExportHistory (
526512 level : LogLevel ,
527513 message : string ,
528514 data : any [ ] ,
529515 caller ?: string | null
530516 ) : void {
517+ // 生产环境完全禁用导出历史功能,节省内存
518+ if ( ! IS_DEV ) {
519+ return
520+ }
521+
522+ // 检查是否需要清理
523+ this . checkAndCleanupHistory ( )
524+
525+ // 对于高频日志,采用采样策略
526+ if ( this . shouldSkipForSampling ( level , message ) ) {
527+ return
528+ }
529+
531530 const entry : LogExportEntry = {
532531 timestamp : new Date ( ) . toISOString ( ) ,
533532 level,
534533 module : this . module ,
535534 window : this . window ,
536535 message,
537- data : data . length > 0 ? data . map ( ( item ) => this . deepSerialize ( item ) ) : undefined ,
538- context : Object . keys ( this . context ) . length > 0 ? this . deepSerialize ( this . context ) : undefined ,
536+ data : data . length > 0 ? data . map ( ( item ) => this . lightSerialize ( item , 2 ) ) : undefined ,
537+ context :
538+ Object . keys ( this . context ) . length > 0 ? this . lightSerialize ( this . context , 2 ) : undefined ,
539539 caller : caller || undefined
540540 }
541541
542542 this . exportHistory . push ( entry )
543543
544- // 限制历史记录数量
544+ // 更积极的内存管理
545545 if ( this . exportHistory . length > this . maxHistorySize ) {
546- this . exportHistory = this . exportHistory . slice ( - this . maxHistorySize )
546+ // 保留最近的记录,删除最旧的
547+ const keepCount = Math . floor ( this . maxHistorySize * 0.8 ) // 保留80%
548+ this . exportHistory . splice ( 0 , this . exportHistory . length - keepCount )
547549 }
548550 }
549551
552+ /**
553+ * 采样策略 - 对高频日志进行采样
554+ */
555+ private shouldSkipForSampling ( level : LogLevel , message : string ) : boolean {
556+ // 对于 SILLY 和 DEBUG 级别的高频消息进行采样
557+ if ( level === LEVEL . SILLY || level === LEVEL . DEBUG ) {
558+ // 检查是否为高频消息模式
559+ const isHighFrequency =
560+ message . includes ( 'time_update' ) ||
561+ message . includes ( 'MediaClock' ) ||
562+ message . includes ( 'throttle' ) ||
563+ message . includes ( 'performance' )
564+
565+ if ( isHighFrequency ) {
566+ // 只保留每10条记录中的1条
567+ return Math . random ( ) > 0.1
568+ }
569+ }
570+ return false
571+ }
572+
573+ /**
574+ * 检查并清理历史记录
575+ */
576+ private checkAndCleanupHistory ( ) : void {
577+ const now = Date . now ( )
578+
579+ // 定期清理
580+ if ( now - this . lastCleanupTime > this . CLEANUP_INTERVAL ) {
581+ this . performCleanup ( )
582+ this . lastCleanupTime = now
583+ }
584+
585+ // 内存压力检测
586+ if ( this . exportHistory . length > this . MEMORY_PRESSURE_THRESHOLD ) {
587+ this . performEmergencyCleanup ( )
588+ }
589+ }
590+
591+ /**
592+ * 执行常规清理
593+ */
594+ private performCleanup ( ) : void {
595+ const oldLength = this . exportHistory . length
596+
597+ // 清理30分钟前的记录
598+ const thirtyMinutesAgo = Date . now ( ) - 30 * 60 * 1000
599+ this . exportHistory = this . exportHistory . filter ( ( entry ) => {
600+ const entryTime = new Date ( entry . timestamp ) . getTime ( )
601+ return entryTime > thirtyMinutesAgo
602+ } )
603+
604+ if ( oldLength !== this . exportHistory . length ) {
605+ console . log ( `[LoggerService] 清理了 ${ oldLength - this . exportHistory . length } 条过期日志记录` )
606+ }
607+ }
608+
609+ /**
610+ * 执行紧急清理
611+ */
612+ private performEmergencyCleanup ( ) : void {
613+ const oldLength = this . exportHistory . length
614+
615+ // 只保留最近的记录
616+ const keepCount = Math . floor ( this . maxHistorySize * 0.5 )
617+ this . exportHistory . splice ( 0 , this . exportHistory . length - keepCount )
618+
619+ console . warn (
620+ `[LoggerService] 内存压力过大,执行紧急清理,删除了 ${ oldLength - this . exportHistory . length } 条记录`
621+ )
622+ }
623+
550624 /**
551625 * 导出日志
552626 */
0 commit comments