@nest-packages/nestjs-trace-logger 0.1.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 (2) hide show
  1. package/README.md +447 -0
  2. package/package.json +24 -0
package/README.md ADDED
@@ -0,0 +1,447 @@
1
+ # @nest-packages/nestjs-trace-logger
2
+
3
+ 一个功能强大的 NestJS 日志追踪包,提供完整的 traceId 支持、上下文管理和自定义格式化功能。
4
+
5
+ ## 特性
6
+
7
+ - ✅ **完全继承 NestJS Logger** - 保持所有原生功能,API 完全兼容
8
+ - ✅ **自动 traceId 注入** - 使用 AsyncLocalStorage 自动在异步调用链中传递 traceId
9
+ - ✅ **支持 LogLevel 配置** - 兼容 `getLogLevels` 函数,支持生产/开发环境不同日志级别
10
+ - ✅ **自定义格式化器** - 支持默认、SLS、JSON 等多种格式化方式
11
+ - ✅ **中间件和拦截器** - 开箱即用的 TraceMiddleware 和 TraceInterceptor
12
+ - ✅ **类型安全** - 完整的 TypeScript 类型定义
13
+ - ✅ **零配置** - 默认配置即可使用,也支持深度自定义
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ npm install @nest-packages/nestjs-trace-logger
19
+ # 或
20
+ pnpm add @nest-packages/nestjs-trace-logger
21
+ # 或
22
+ yarn add @nest-packages/nestjs-trace-logger
23
+ ```
24
+
25
+ ### 依赖要求
26
+
27
+ - `@nestjs/common`: ^11.0.0
28
+ - `@nestjs/core`: ^11.0.0
29
+ - `uuid`: ^9.0.0
30
+ - `fast-safe-stringify`: ^2.1.0
31
+
32
+ ## 快速开始
33
+
34
+ ### 1. 在 main.ts 中配置
35
+
36
+ ```typescript
37
+ import { NestFactory } from '@nestjs/core';
38
+ import {
39
+ TraceConsoleLogger,
40
+ TraceMiddleware,
41
+ TraceInterceptor,
42
+ } from '@nest-packages/nestjs-trace-logger';
43
+ import { AppModule } from './app.module';
44
+
45
+ function getLogLevels(isProduction: boolean): LogLevel[] {
46
+ if (isProduction) {
47
+ return ['warn', 'error', 'log'];
48
+ }
49
+ return ['error', 'warn', 'log', 'verbose', 'debug'];
50
+ }
51
+
52
+ async function bootstrap() {
53
+ const app = await NestFactory.create(AppModule, {
54
+ logger: new TraceConsoleLogger({
55
+ logLevels: getLogLevels(process.env.NODE_ENV === 'production'),
56
+ compact: true,
57
+ json: false,
58
+ colors: true,
59
+ }),
60
+ });
61
+
62
+ // 注册 Trace 中间件(在健康检查之后)
63
+ const traceMiddleware = new TraceMiddleware();
64
+ app.use((req, res, next) => traceMiddleware.use(req, res, next));
65
+
66
+ // 注册 Trace 拦截器
67
+ app.useGlobalInterceptors(new TraceInterceptor());
68
+
69
+ await app.listen(3000);
70
+ }
71
+ bootstrap();
72
+ ```
73
+
74
+ ### 2. 在服务中使用
75
+
76
+ ```typescript
77
+ import { Injectable } from '@nestjs/common';
78
+ import { TraceLogger } from '@nest-packages/nestjs-trace-logger';
79
+
80
+ @Injectable()
81
+ export class MyService {
82
+ private readonly logger = new TraceLogger(MyService.name);
83
+
84
+ async doSomething() {
85
+ // 自动注入 traceId,支持对象上下文
86
+ this.logger.log('操作完成', { userId: 123, action: 'create' });
87
+
88
+ // 支持 NestJS Logger 的所有方法
89
+ this.logger.debug('调试信息');
90
+ this.logger.warn('警告信息');
91
+ this.logger.error('错误信息', 'stack trace');
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## API 文档
97
+
98
+ ### TraceContextService
99
+
100
+ 用于管理请求上下文和 traceId 的服务类。
101
+
102
+ ```typescript
103
+ import { TraceContextService } from '@nest-packages/nestjs-trace-logger';
104
+
105
+ // 获取当前 traceId
106
+ const traceId = TraceContextService.getTraceId();
107
+
108
+ // 运行函数并设置 traceId(同步)
109
+ TraceContextService.run('trace-id-123', () => {
110
+ // 在这个函数内部,traceId 自动可用
111
+ const id = TraceContextService.getTraceId(); // 'trace-id-123'
112
+ });
113
+
114
+ // 运行函数并设置 traceId(异步)
115
+ await TraceContextService.runAsync('trace-id-123', async () => {
116
+ // 异步函数内部,traceId 自动可用
117
+ const id = TraceContextService.getTraceId(); // 'trace-id-123'
118
+ });
119
+
120
+ // 设置自定义上下文数据
121
+ TraceContextService.set('userId', 123);
122
+ const userId = TraceContextService.get<number>('userId'); // 123
123
+
124
+ // 获取完整上下文
125
+ const context = TraceContextService.getContext();
126
+ ```
127
+
128
+ ### TraceLogger
129
+
130
+ 完全继承 NestJS Logger 的日志类,自动注入 traceId。
131
+
132
+ ```typescript
133
+ import { TraceLogger } from '@nest-packages/nestjs-trace-logger';
134
+
135
+ // 创建实例
136
+ const logger = new TraceLogger('MyService');
137
+
138
+ // 使用默认格式化器
139
+ logger.log('消息', { key: 'value' });
140
+ // 输出: [traceId] 消息 | {"traceId":"abc123","key":"value"}
141
+
142
+ // 使用自定义格式化器
143
+ import { JsonFormatter } from '@nest-packages/nestjs-trace-logger';
144
+ logger.setFormatter(new JsonFormatter());
145
+ logger.log('消息', { key: 'value' });
146
+ // 输出: {"message":"消息","timestamp":"2024-01-01T00:00:00.000Z","traceId":"abc123","key":"value"}
147
+ ```
148
+
149
+ ### TraceConsoleLogger
150
+
151
+ 类似 ConsoleLogger,支持 LogLevel 配置。
152
+
153
+ ```typescript
154
+ import { TraceConsoleLogger, LogLevel } from '@nest-packages/nestjs-trace-logger';
155
+
156
+ const logger = new TraceConsoleLogger({
157
+ logLevels: ['error', 'warn', 'log'] as LogLevel[],
158
+ compact: true,
159
+ json: false,
160
+ colors: true,
161
+ formatter: new SlsFormatter(), // 可选:自定义格式化器
162
+ });
163
+ ```
164
+
165
+ ### TraceMiddleware
166
+
167
+ 自动从请求头获取或生成 traceId 的中间件。
168
+
169
+ ```typescript
170
+ import { TraceMiddleware } from '@nest-packages/nestjs-trace-logger';
171
+
172
+ // 在 main.ts 中注册
173
+ const traceMiddleware = new TraceMiddleware();
174
+ app.use((req, res, next) => traceMiddleware.use(req, res, next));
175
+ ```
176
+
177
+ **功能:**
178
+ - 从 `x-request-id` 请求头获取 traceId
179
+ - 如果没有,自动生成 UUID 并截取前 8 位
180
+ - 在响应头中设置 `X-Request-ID`
181
+ - 使用 AsyncLocalStorage 存储上下文
182
+
183
+ ### TraceInterceptor
184
+
185
+ 确保 NestJS 执行上下文中 traceId 可用的拦截器。
186
+
187
+ ```typescript
188
+ import { TraceInterceptor } from '@nest-packages/nestjs-trace-logger';
189
+
190
+ // 在 main.ts 中注册
191
+ app.useGlobalInterceptors(new TraceInterceptor());
192
+ ```
193
+
194
+ ## 格式化器
195
+
196
+ ### DefaultFormatter(默认)
197
+
198
+ 格式:`[traceId] message | {context}`
199
+
200
+ ```typescript
201
+ import { DefaultFormatter } from '@nest-packages/nestjs-trace-logger';
202
+
203
+ const logger = new TraceLogger('MyService', new DefaultFormatter());
204
+ logger.log('操作完成', { userId: 123 });
205
+ // 输出: [abc123] 操作完成 | {"traceId":"abc123","userId":123}
206
+ ```
207
+
208
+ ### SlsFormatter(阿里云 SLS)
209
+
210
+ 适配阿里云 SLS 日志格式,traceId 包含在 context 中。
211
+
212
+ ```typescript
213
+ import { SlsFormatter } from '@nest-packages/nestjs-trace-logger';
214
+
215
+ const logger = new TraceLogger('MyService', new SlsFormatter());
216
+ logger.log('操作完成', { userId: 123 });
217
+ // 输出: 操作完成 | {"traceId":"abc123","userId":123}
218
+ ```
219
+
220
+ ### JsonFormatter(JSON 格式)
221
+
222
+ 输出完整的 JSON 格式日志。
223
+
224
+ ```typescript
225
+ import { JsonFormatter } from '@nest-packages/nestjs-trace-logger';
226
+
227
+ const logger = new TraceLogger('MyService', new JsonFormatter());
228
+ logger.log('操作完成', { userId: 123 });
229
+ // 输出: {"message":"操作完成","timestamp":"2024-01-01T00:00:00.000Z","traceId":"abc123","userId":123}
230
+ ```
231
+
232
+ ### 自定义格式化器
233
+
234
+ ```typescript
235
+ import { IFormatter, LogContext } from '@nest-packages/nestjs-trace-logger';
236
+
237
+ class CustomFormatter implements IFormatter {
238
+ format(message: string, traceId?: string, context?: LogContext): string {
239
+ return `[${traceId || 'N/A'}] ${message} - ${JSON.stringify(context || {})}`;
240
+ }
241
+ }
242
+
243
+ const logger = new TraceLogger('MyService', new CustomFormatter());
244
+ ```
245
+
246
+ ## 高级用法
247
+
248
+ ### 在队列任务中使用
249
+
250
+ ```typescript
251
+ import { TraceContextService } from '@nest-packages/nestjs-trace-logger';
252
+
253
+ @Processor('my-queue')
254
+ export class MyProcessor {
255
+ @Process()
256
+ async handle(job: Job) {
257
+ const traceId = job.data.traceId || 'generated-id';
258
+
259
+ await TraceContextService.runAsync(traceId, async () => {
260
+ // 在这个异步函数中,traceId 自动可用
261
+ const logger = new TraceLogger(MyProcessor.name);
262
+ logger.log('处理任务', { jobId: job.id });
263
+ });
264
+ }
265
+ }
266
+ ```
267
+
268
+ ### 继承 TraceLogger 创建自定义 Logger
269
+
270
+ ```typescript
271
+ import { TraceLogger, LogContext } from '@nest-packages/nestjs-trace-logger';
272
+
273
+ export class AlarmLogger extends TraceLogger {
274
+ constructor(context: string) {
275
+ super(context);
276
+ }
277
+
278
+ log(message: string, context?: LogContext | string): void {
279
+ if (context && typeof context === 'object') {
280
+ super.log(message, context as LogContext);
281
+ } else {
282
+ super.log(message, context);
283
+ }
284
+ }
285
+ }
286
+ ```
287
+
288
+ ### 使用 LoggerManager
289
+
290
+ ```typescript
291
+ import { LoggerManager, TraceLogger } from '@nest-packages/nestjs-trace-logger';
292
+
293
+ // 设置自定义 Logger 工厂
294
+ LoggerManager.setLoggerFactory((context: string) => {
295
+ return new TraceLogger(context, new SlsFormatter());
296
+ });
297
+
298
+ // 创建 Logger
299
+ const logger = LoggerManager.createLogger('MyService');
300
+ ```
301
+
302
+ ### 在模块配置中使用
303
+
304
+ ```typescript
305
+ import { TraceLogger } from '@nest-packages/nestjs-trace-logger';
306
+
307
+ @Module({
308
+ imports: [
309
+ SomeModule.forRootAsync({
310
+ useFactory: () => ({
311
+ loggerFactory: (context: string) => new TraceLogger(context),
312
+ }),
313
+ }),
314
+ ],
315
+ })
316
+ export class AppModule {}
317
+ ```
318
+
319
+ ## 配置选项
320
+
321
+ ### TraceConsoleLoggerOptions
322
+
323
+ ```typescript
324
+ interface TraceConsoleLoggerOptions {
325
+ /**
326
+ * 日志级别数组
327
+ * @example ['error', 'warn', 'log', 'verbose', 'debug']
328
+ */
329
+ logLevels?: LogLevel[];
330
+
331
+ /**
332
+ * 是否使用紧凑格式
333
+ * @default false
334
+ */
335
+ compact?: boolean;
336
+
337
+ /**
338
+ * 是否输出 JSON 格式
339
+ * @default false
340
+ */
341
+ json?: boolean;
342
+
343
+ /**
344
+ * 是否使用颜色
345
+ * @default true
346
+ */
347
+ colors?: boolean;
348
+
349
+ /**
350
+ * 自定义格式化器
351
+ */
352
+ formatter?: IFormatter;
353
+ }
354
+ ```
355
+
356
+ ## 最佳实践
357
+
358
+ ### 1. 日志级别配置
359
+
360
+ 根据环境配置不同的日志级别:
361
+
362
+ ```typescript
363
+ function getLogLevels(isProduction: boolean): LogLevel[] {
364
+ if (isProduction) {
365
+ return ['warn', 'error', 'log'];
366
+ }
367
+ return ['error', 'warn', 'log', 'verbose', 'debug'];
368
+ }
369
+ ```
370
+
371
+ ### 2. 在异步操作中保持 traceId
372
+
373
+ 使用 `TraceContextService.runAsync` 确保异步操作中 traceId 可用:
374
+
375
+ ```typescript
376
+ await TraceContextService.runAsync(traceId, async () => {
377
+ // 所有异步操作都会自动包含 traceId
378
+ await someAsyncOperation();
379
+ await anotherAsyncOperation();
380
+ });
381
+ ```
382
+
383
+ ### 3. 使用对象上下文
384
+
385
+ 传递结构化数据而不是字符串拼接:
386
+
387
+ ```typescript
388
+ // ✅ 推荐
389
+ logger.log('用户登录', { userId: 123, ip: '192.168.1.1' });
390
+
391
+ // ❌ 不推荐
392
+ logger.log(`用户登录: userId=${userId}, ip=${ip}`);
393
+ ```
394
+
395
+ ### 4. 错误日志记录
396
+
397
+ ```typescript
398
+ try {
399
+ // 业务逻辑
400
+ } catch (error) {
401
+ logger.error('操作失败', {
402
+ error: error.message,
403
+ stack: error.stack,
404
+ userId: 123
405
+ });
406
+ }
407
+ ```
408
+
409
+ ## 类型定义
410
+
411
+ ```typescript
412
+ // TraceContext
413
+ interface TraceContext {
414
+ traceId: string;
415
+ startTime: number;
416
+ [key: string]: any;
417
+ }
418
+
419
+ // LogContext
420
+ type LogContext = Record<string, unknown>;
421
+
422
+ // ILogger
423
+ interface ILogger {
424
+ log(message: string, ...context: any[]): void;
425
+ debug(message: string, ...context: any[]): void;
426
+ warn(message: string, ...context: any[]): void;
427
+ error(message: string, ...context: any[]): void;
428
+ }
429
+
430
+ // IFormatter
431
+ interface IFormatter {
432
+ format(message: string, traceId?: string, context?: LogContext): string;
433
+ }
434
+ ```
435
+
436
+ ## 许可证
437
+
438
+ MIT
439
+
440
+ ## 贡献
441
+
442
+ 欢迎提交 Issue 和 Pull Request!
443
+
444
+ ## 相关链接
445
+
446
+ - [NestJS 官方文档](https://docs.nestjs.com/)
447
+ - [AsyncLocalStorage 文档](https://nodejs.org/api/async_hooks.html#async_hooks_class_asynclocalstorage)
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@nest-packages/nestjs-trace-logger",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "peerDependencies": {
10
+ "@nestjs/common": "^11.0.0",
11
+ "@nestjs/core": "^11.0.0"
12
+ },
13
+ "dependencies": {
14
+ "uuid": "^9.0.0",
15
+ "fast-safe-stringify": "^2.1.0"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.build.json"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "license": "MIT"
24
+ }