@taicode/common-base 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/output/error/error.d.ts +59 -9
  2. package/output/error/error.d.ts.map +1 -1
  3. package/output/error/error.js +50 -6
  4. package/output/error/index.d.ts +1 -1
  5. package/output/error/index.d.ts.map +1 -1
  6. package/output/logger/formatter.d.ts +71 -0
  7. package/output/logger/formatter.d.ts.map +1 -0
  8. package/output/logger/formatter.js +222 -0
  9. package/output/logger/formatter.test.d.ts +26 -0
  10. package/output/logger/formatter.test.d.ts.map +1 -0
  11. package/output/logger/formatter.test.js +315 -0
  12. package/output/logger/index.d.ts +3 -17
  13. package/output/logger/index.d.ts.map +1 -1
  14. package/output/logger/index.js +3 -34
  15. package/output/logger/logger.d.ts +51 -0
  16. package/output/logger/logger.d.ts.map +1 -0
  17. package/output/logger/logger.js +118 -0
  18. package/output/logger/logger.test.d.ts +19 -0
  19. package/output/logger/logger.test.d.ts.map +1 -1
  20. package/output/logger/logger.test.js +201 -15
  21. package/output/logger/transport.d.ts +124 -0
  22. package/output/logger/transport.d.ts.map +1 -0
  23. package/output/logger/transport.js +153 -0
  24. package/output/logger/transport.test.d.ts +2 -0
  25. package/output/logger/transport.test.d.ts.map +1 -0
  26. package/output/logger/transport.test.js +309 -0
  27. package/output/ring-cache/index.d.ts +6 -0
  28. package/output/ring-cache/index.d.ts.map +1 -0
  29. package/output/ring-cache/index.js +5 -0
  30. package/output/ring-cache/ring-cache.d.ts +125 -0
  31. package/output/ring-cache/ring-cache.d.ts.map +1 -0
  32. package/output/ring-cache/ring-cache.js +197 -0
  33. package/output/ring-cache/ring-cache.test.d.ts +2 -0
  34. package/output/ring-cache/ring-cache.test.d.ts.map +1 -0
  35. package/output/ring-cache/ring-cache.test.js +195 -0
  36. package/package.json +1 -1
@@ -1,33 +1,219 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import { Logger } from './index';
2
+ import { Logger } from './logger';
3
+ import { DefaultLogFormatter } from './formatter';
4
+ import { UserError, SystemError, UnknownError } from '../error';
5
+ import { MemoryTransport } from './transport'; // 测试向后兼容性
3
6
  describe('Logger', () => {
4
7
  it('应该默认记录 info 及以上级别', () => {
5
- const handler = vi.fn();
6
- const logger = new Logger({ handler });
8
+ const print = vi.fn();
9
+ const logger = new Logger({ print });
7
10
  logger.debug('debug');
8
11
  logger.info('info');
9
12
  logger.warn('warn');
10
13
  logger.error('error');
11
- expect(handler).not.toHaveBeenCalledWith('debug', 'debug');
12
- expect(handler).toHaveBeenCalledWith('info', 'info');
13
- expect(handler).toHaveBeenCalledWith('warn', 'warn');
14
- expect(handler).toHaveBeenCalledWith('error', 'error');
14
+ expect(print).not.toHaveBeenCalledWith('debug', 'debug');
15
+ expect(print).toHaveBeenCalledWith('info', 'info');
16
+ expect(print).toHaveBeenCalledWith('warn', 'warn');
17
+ expect(print).toHaveBeenCalledWith('error', 'error');
15
18
  });
16
19
  it('应该遵守日志级别', () => {
17
- const handler = vi.fn();
18
- const logger = new Logger({ level: 'warn', handler });
20
+ const print = vi.fn();
21
+ const logger = new Logger({ level: 'warn', print });
19
22
  logger.info('info');
20
23
  logger.warn('warn');
21
24
  logger.error('error');
22
- expect(handler).not.toHaveBeenCalledWith('info', 'info');
23
- expect(handler).toHaveBeenCalledWith('warn', 'warn');
24
- expect(handler).toHaveBeenCalledWith('error', 'error');
25
+ expect(print).not.toHaveBeenCalledWith('info', 'info');
26
+ expect(print).toHaveBeenCalledWith('warn', 'warn');
27
+ expect(print).toHaveBeenCalledWith('error', 'error');
25
28
  });
26
29
  it('应该允许自定义处理器', () => {
27
30
  const logs = [];
28
- const handler = (level, ...args) => logs.push([level, ...args]);
29
- const logger = new Logger({ handler });
31
+ const print = (level, ...args) => logs.push([level, ...args]);
32
+ const logger = new Logger({ print });
30
33
  logger.error('err', 123);
31
- expect(logs).toContainEqual(['error', 'err', 123]);
34
+ expect(logs).toContainEqual(['error', 'err', "123"]);
35
+ });
36
+ });
37
+ describe('Logger 错误处理', () => {
38
+ it('应该正确格式化 UserError', () => {
39
+ const mockPrint = vi.fn();
40
+ const logger = new Logger({ print: mockPrint });
41
+ const userError = new UserError('validation-failed', '邮箱格式无效', {
42
+ field: 'email',
43
+ value: 'invalid-email',
44
+ rule: 'email-format'
45
+ });
46
+ logger.error('测试用户错误:', userError);
47
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试用户错误:', expect.stringContaining('🚫 User Error [validation-failed]'));
48
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试用户错误:', expect.stringContaining('邮箱格式无效'));
49
+ });
50
+ it('应该正确格式化 SystemError', () => {
51
+ const mockPrint = vi.fn();
52
+ const logger = new Logger({ print: mockPrint });
53
+ const systemError = new SystemError('database-error', '数据库连接失败', {
54
+ table: 'users',
55
+ query: 'SELECT * FROM users',
56
+ operation: 'select'
57
+ });
58
+ logger.error('测试系统错误:', systemError);
59
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试系统错误:', expect.stringContaining('⚠️ System Error [database-error]'));
60
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试系统错误:', expect.stringContaining('数据库连接失败'));
61
+ });
62
+ it('应该正确格式化 UnknownError', () => {
63
+ const mockPrint = vi.fn();
64
+ const logger = new Logger({ print: mockPrint });
65
+ const unknownError = new UnknownError('未知错误', {
66
+ cause: 'something went wrong'
67
+ });
68
+ logger.error('测试未知错误:', unknownError);
69
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试未知错误:', expect.stringContaining('❓ Unknown Error'));
70
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试未知错误:', expect.stringContaining('未知错误'));
71
+ });
72
+ it('应该正确格式化普通 Error', () => {
73
+ const mockPrint = vi.fn();
74
+ const logger = new Logger({ print: mockPrint });
75
+ const genericError = new Error('普通错误');
76
+ logger.error('测试普通错误:', genericError);
77
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试普通错误:', expect.stringContaining('💥 Error'));
78
+ expect(mockPrint).toHaveBeenCalledWith('error', '测试普通错误:', expect.stringContaining('普通错误'));
79
+ });
80
+ it('应该支持自定义 LogFormatter 实例', () => {
81
+ const customFormatter = new DefaultLogFormatter({}, {
82
+ showStack: false,
83
+ useColors: false
84
+ });
85
+ const mockPrint = vi.fn();
86
+ const logger = new Logger({
87
+ print: mockPrint,
88
+ formatter: customFormatter
89
+ });
90
+ const error = new Error('测试错误');
91
+ logger.error(error);
92
+ const formattedError = mockPrint.mock.calls[0][1];
93
+ expect(formattedError).not.toContain('Stack:');
94
+ expect(formattedError).not.toContain('\x1b['); // ANSI color codes
95
+ });
96
+ it('应该支持自定义格式化选项', () => {
97
+ const customFormatter = new DefaultLogFormatter({}, {
98
+ showStack: false,
99
+ showContext: false,
100
+ useColors: false
101
+ });
102
+ const mockPrint = vi.fn();
103
+ const logger = new Logger({
104
+ print: mockPrint,
105
+ formatter: customFormatter
106
+ });
107
+ const userError = new UserError('test-error', '测试错误', { field: 'test' });
108
+ logger.error(userError);
109
+ const formattedError = mockPrint.mock.calls[0][1];
110
+ expect(formattedError).not.toContain('Stack:');
111
+ expect(formattedError).not.toContain('Context:');
112
+ expect(formattedError).not.toContain('\x1b['); // ANSI color codes
113
+ });
114
+ });
115
+ describe('Logger Transport 集成', () => {
116
+ it('应该支持 Transport 记录日志', () => {
117
+ const transport = new MemoryTransport();
118
+ const logger = new Logger({ transports: [transport] });
119
+ logger.info('测试消息', { data: 'value' });
120
+ const records = transport.getRecords();
121
+ expect(records).toHaveLength(1);
122
+ expect(records[0].level).toBe('info');
123
+ expect(records[0].args).toEqual(['测试消息', { data: 'value' }]);
124
+ expect(records[0].timestamp).toBeInstanceOf(Date);
125
+ });
126
+ it('应该支持多个 Transport', () => {
127
+ const transport1 = new MemoryTransport({ maxRecords: 10 });
128
+ const transport2 = new MemoryTransport({ maxRecords: 10 });
129
+ const logger = new Logger({ transports: [transport1, transport2] });
130
+ logger.error('错误消息');
131
+ expect(transport1.getRecords()).toHaveLength(1);
132
+ expect(transport2.getRecords()).toHaveLength(1);
133
+ expect(transport1.getRecords()[0].args).toEqual(['错误消息']);
134
+ expect(transport2.getRecords()[0].args).toEqual(['错误消息']);
135
+ });
136
+ it('应该支持动态添加和移除 Transport', () => {
137
+ const logger = new Logger();
138
+ const transport = new MemoryTransport();
139
+ // 添加 transport
140
+ logger.addTransport(transport);
141
+ logger.info('消息1');
142
+ expect(transport.getRecords()).toHaveLength(1);
143
+ // 移除 transport
144
+ logger.removeTransport('memory');
145
+ logger.info('消息2');
146
+ expect(transport.getRecords()).toHaveLength(1); // 应该还是1条
147
+ });
148
+ it('应该获取所有 Transport', () => {
149
+ const transport1 = new MemoryTransport();
150
+ const transport2 = new MemoryTransport();
151
+ const logger = new Logger({ transports: [transport1, transport2] });
152
+ const transports = logger.getTransports();
153
+ expect(transports).toHaveLength(2);
154
+ expect(transports[0].name).toBe('memory');
155
+ expect(transports[1].name).toBe('memory');
156
+ });
157
+ it('应该同时支持 Transport 和 print', () => {
158
+ const transport = new MemoryTransport();
159
+ const mockPrint = vi.fn();
160
+ const logger = new Logger({
161
+ transports: [transport],
162
+ print: mockPrint
163
+ });
164
+ logger.warn('警告消息');
165
+ // Transport 应该收到结构化数据
166
+ const records = transport.getRecords();
167
+ expect(records).toHaveLength(1);
168
+ expect(records[0].args).toEqual(['警告消息']);
169
+ // print 应该收到格式化的数据
170
+ expect(mockPrint).toHaveBeenCalledWith('warn', '警告消息');
171
+ });
172
+ it('应该处理 Transport 错误而不影响主程序', () => {
173
+ const faultyTransport = {
174
+ name: 'faulty',
175
+ log: () => { throw new Error('Transport 错误'); }
176
+ };
177
+ const logger = new Logger({ transports: [faultyTransport] });
178
+ // 不应该抛出错误
179
+ expect(() => {
180
+ logger.error('测试消息');
181
+ }).not.toThrow();
182
+ });
183
+ it('应该在没有 Transport 和 print 时使用默认输出', () => {
184
+ const consoleSpy = vi.spyOn(console, 'info').mockImplementation(() => { });
185
+ const logger = new Logger();
186
+ logger.info('默认输出测试');
187
+ expect(consoleSpy).toHaveBeenCalledWith('[INFO]', '默认输出测试');
188
+ consoleSpy.mockRestore();
189
+ });
190
+ it('应该关闭所有 Transport', async () => {
191
+ const mockClose1 = vi.fn();
192
+ const mockClose2 = vi.fn();
193
+ const transport1 = {
194
+ name: 'test1',
195
+ log: () => { },
196
+ close: mockClose1
197
+ };
198
+ const transport2 = {
199
+ name: 'test2',
200
+ log: () => { },
201
+ close: mockClose2
202
+ };
203
+ const logger = new Logger({ transports: [transport1, transport2] });
204
+ await logger.close();
205
+ expect(mockClose1).toHaveBeenCalled();
206
+ expect(mockClose2).toHaveBeenCalled();
207
+ });
208
+ });
209
+ describe('向后兼容性测试', () => {
210
+ it('Transport 类型别名应该正常工作', () => {
211
+ // 测试 Transport 类型别名是否可以正常使用
212
+ const transport = new MemoryTransport();
213
+ const logger = new Logger({ transports: [transport] });
214
+ logger.info('测试向后兼容性');
215
+ const records = transport.getRecords();
216
+ expect(records).toHaveLength(1);
217
+ expect(records[0].args).toEqual(['测试向后兼容性']);
32
218
  });
33
219
  });
@@ -0,0 +1,124 @@
1
+ /**
2
+ * LogTransport 抽象接口和实现
3
+ * LogTransport 负责处理和存储结构化的日志数据
4
+ */
5
+ import type { LogLevel } from './logger';
6
+ /**
7
+ * 日志记录接口
8
+ * 包含完整的结构化日志信息
9
+ */
10
+ export interface LogRecord {
11
+ /** 日志级别 */
12
+ level: LogLevel;
13
+ /** 时间戳 */
14
+ timestamp: Date;
15
+ /** 原始参数数组 */
16
+ args: any[];
17
+ /** 可选的附加元数据 */
18
+ metadata?: Record<string, any>;
19
+ }
20
+ /**
21
+ * LogTransport 抽象接口
22
+ * 负责处理结构化日志数据的存储和管理
23
+ */
24
+ export interface LogTransport {
25
+ /** LogTransport 名称 */
26
+ readonly name: string;
27
+ /** 最低日志级别 */
28
+ level?: LogLevel;
29
+ /** 是否启用 */
30
+ enabled?: boolean;
31
+ /**
32
+ * 处理日志记录
33
+ * @param record 结构化的日志记录
34
+ */
35
+ log(record: LogRecord): void | Promise<void>;
36
+ /**
37
+ * 关闭 LogTransport,清理资源
38
+ */
39
+ close?(): void | Promise<void>;
40
+ }
41
+ /**
42
+ * 内存 LogTransport 配置选项
43
+ */
44
+ export interface MemoryTransportOptions {
45
+ /** 最大存储的日志条数 */
46
+ maxRecords?: number;
47
+ /** 最低日志级别 */
48
+ level?: LogLevel;
49
+ /** 是否启用 */
50
+ enabled?: boolean;
51
+ }
52
+ /**
53
+ * 内存中的日志条目
54
+ */
55
+ export interface MemoryLogEntry extends LogRecord {
56
+ /** 唯一标识符 */
57
+ id: string;
58
+ }
59
+ /**
60
+ * 内存 LogTransport 实现
61
+ * 将结构化日志数据存储在内存中,支持查询和分析
62
+ * 使用RingCache实现高效的FIFO行为
63
+ */
64
+ export declare class MemoryTransport implements LogTransport {
65
+ readonly name: string;
66
+ level?: LogLevel;
67
+ enabled: boolean;
68
+ private cache;
69
+ private static readonly LOG_LEVELS;
70
+ constructor(options?: MemoryTransportOptions);
71
+ /**
72
+ * 检查是否应该处理此级别的日志
73
+ */
74
+ private shouldLog;
75
+ log(record: LogRecord): void;
76
+ /**
77
+ * 获取所有日志记录
78
+ */
79
+ getRecords(): readonly MemoryLogEntry[];
80
+ /**
81
+ * 根据级别获取日志记录
82
+ */
83
+ getRecordsByLevel(level: LogLevel): MemoryLogEntry[];
84
+ /**
85
+ * 根据时间范围获取日志记录
86
+ */
87
+ getRecordsByTimeRange(start: Date, end: Date): MemoryLogEntry[];
88
+ /**
89
+ * 搜索日志记录
90
+ * @param predicate 搜索条件函数
91
+ */
92
+ searchRecords(predicate: (record: MemoryLogEntry) => boolean): MemoryLogEntry[];
93
+ /**
94
+ * 根据参数内容搜索
95
+ * @param searchText 搜索文本
96
+ */
97
+ searchByContent(searchText: string): MemoryLogEntry[];
98
+ /**
99
+ * 获取最近的 N 条记录
100
+ */
101
+ getRecentRecords(count: number): MemoryLogEntry[];
102
+ /**
103
+ * 获取统计信息
104
+ */
105
+ getStats(): {
106
+ total: number;
107
+ byLevel: Record<LogLevel, number>;
108
+ oldestTimestamp?: Date;
109
+ newestTimestamp?: Date;
110
+ };
111
+ /**
112
+ * 清空所有记录
113
+ */
114
+ clear(): void;
115
+ /**
116
+ * 导出为 JSON 格式
117
+ */
118
+ exportToJSON(): string;
119
+ /**
120
+ * 关闭 LogTransport
121
+ */
122
+ close(): void;
123
+ }
124
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../source/logger/transport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGxC;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW;IACX,KAAK,EAAE,QAAQ,CAAA;IACf,UAAU;IACV,SAAS,EAAE,IAAI,CAAA;IACf,aAAa;IACb,IAAI,EAAE,GAAG,EAAE,CAAA;IACX,eAAe;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB,aAAa;IACb,KAAK,CAAC,EAAE,QAAQ,CAAA;IAEhB,WAAW;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE5C;;OAEG;IACH,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,gBAAgB;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa;IACb,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,WAAW;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,YAAY;IACZ,EAAE,EAAE,MAAM,CAAA;CACX;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,SAAgB,IAAI,EAAE,MAAM,CAAY;IACjC,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,OAAO,EAAE,OAAO,CAAQ;IAE/B,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAkD;gBAExE,OAAO,GAAE,sBAA2B;IAQhD;;OAEG;IACH,OAAO,CAAC,SAAS;IAeV,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAQnC;;OAEG;IACI,UAAU,IAAI,SAAS,cAAc,EAAE;IAO9C;;OAEG;IACI,iBAAiB,CAAC,KAAK,EAAE,QAAQ,GAAG,cAAc,EAAE;IAQ3D;;OAEG;IACI,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,cAAc,EAAE;IAQtE;;;OAGG;IACI,aAAa,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,GAAG,cAAc,EAAE;IAItF;;;OAGG;IACI,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,EAAE;IAsB5D;;OAEG;IACI,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,EAAE;IAOxD;;OAEG;IACI,QAAQ,IAAI;QACjB,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QACjC,eAAe,CAAC,EAAE,IAAI,CAAA;QACtB,eAAe,CAAC,EAAE,IAAI,CAAA;KACvB;IA4BD;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,YAAY,IAAI,MAAM;IAI7B;;OAEG;IACI,KAAK,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,153 @@
1
+ import { RingCache } from '../ring-cache';
2
+ /**
3
+ * 内存 LogTransport 实现
4
+ * 将结构化日志数据存储在内存中,支持查询和分析
5
+ * 使用RingCache实现高效的FIFO行为
6
+ */
7
+ export class MemoryTransport {
8
+ name = 'memory';
9
+ level;
10
+ enabled = true;
11
+ cache;
12
+ static LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
13
+ constructor(options = {}) {
14
+ this.level = options.level;
15
+ this.enabled = options.enabled ?? true;
16
+ this.cache = new RingCache({
17
+ capacity: options.maxRecords ?? 1000
18
+ });
19
+ }
20
+ /**
21
+ * 检查是否应该处理此级别的日志
22
+ */
23
+ shouldLog(level) {
24
+ if (!this.enabled) {
25
+ return false;
26
+ }
27
+ if (!this.level) {
28
+ return true;
29
+ }
30
+ const currentIndex = MemoryTransport.LOG_LEVELS.indexOf(level);
31
+ const minIndex = MemoryTransport.LOG_LEVELS.indexOf(this.level);
32
+ return currentIndex >= minIndex;
33
+ }
34
+ log(record) {
35
+ if (!this.shouldLog(record.level)) {
36
+ return;
37
+ }
38
+ this.cache.add(record);
39
+ }
40
+ /**
41
+ * 获取所有日志记录
42
+ */
43
+ getRecords() {
44
+ return this.cache.getAll().map(entry => ({
45
+ ...entry.data,
46
+ id: entry.id
47
+ }));
48
+ }
49
+ /**
50
+ * 根据级别获取日志记录
51
+ */
52
+ getRecordsByLevel(level) {
53
+ return this.cache.search(entry => entry.data.level === level)
54
+ .map(entry => ({
55
+ ...entry.data,
56
+ id: entry.id
57
+ }));
58
+ }
59
+ /**
60
+ * 根据时间范围获取日志记录
61
+ */
62
+ getRecordsByTimeRange(start, end) {
63
+ return this.cache.getByTimeRange(start, end)
64
+ .map(entry => ({
65
+ ...entry.data,
66
+ id: entry.id
67
+ }));
68
+ }
69
+ /**
70
+ * 搜索日志记录
71
+ * @param predicate 搜索条件函数
72
+ */
73
+ searchRecords(predicate) {
74
+ return this.getRecords().filter(predicate);
75
+ }
76
+ /**
77
+ * 根据参数内容搜索
78
+ * @param searchText 搜索文本
79
+ */
80
+ searchByContent(searchText) {
81
+ const lowerSearchText = searchText.toLowerCase();
82
+ return this.cache.search(entry => entry.data.args.some(arg => {
83
+ if (typeof arg === 'string') {
84
+ return arg.toLowerCase().includes(lowerSearchText);
85
+ }
86
+ if (typeof arg === 'object' && arg !== null) {
87
+ try {
88
+ return JSON.stringify(arg).toLowerCase().includes(lowerSearchText);
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }
94
+ return false;
95
+ })).map(entry => ({
96
+ ...entry.data,
97
+ id: entry.id
98
+ }));
99
+ }
100
+ /**
101
+ * 获取最近的 N 条记录
102
+ */
103
+ getRecentRecords(count) {
104
+ return this.cache.getRecent(count).map(entry => ({
105
+ ...entry.data,
106
+ id: entry.id
107
+ }));
108
+ }
109
+ /**
110
+ * 获取统计信息
111
+ */
112
+ getStats() {
113
+ const cacheStats = this.cache.getStats();
114
+ const all = this.cache.getAll();
115
+ const stats = {
116
+ total: cacheStats.size,
117
+ byLevel: {
118
+ debug: 0,
119
+ info: 0,
120
+ warn: 0,
121
+ error: 0
122
+ },
123
+ oldestTimestamp: cacheStats.oldestTimestamp,
124
+ newestTimestamp: cacheStats.newestTimestamp
125
+ };
126
+ if (all.length === 0) {
127
+ return stats;
128
+ }
129
+ // 统计各级别数量
130
+ all.forEach(entry => {
131
+ stats.byLevel[entry.data.level]++;
132
+ });
133
+ return stats;
134
+ }
135
+ /**
136
+ * 清空所有记录
137
+ */
138
+ clear() {
139
+ this.cache.clear();
140
+ }
141
+ /**
142
+ * 导出为 JSON 格式
143
+ */
144
+ exportToJSON() {
145
+ return JSON.stringify(this.getRecords(), null, 2);
146
+ }
147
+ /**
148
+ * 关闭 LogTransport
149
+ */
150
+ close() {
151
+ this.clear();
152
+ }
153
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transport.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../../source/logger/transport.test.ts"],"names":[],"mappings":""}