@lark-apaas/nestjs-logger 1.0.1-alpha.1 → 1.0.1-alpha.2
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.
- package/README.md +87 -4
- package/dist/index.cjs +26 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +26 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,9 @@ import { LoggerModule } from '@lark-apaas/nestjs-logger';
|
|
|
36
36
|
export class AppModule {}
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
### 2. 使用 Logger
|
|
39
|
+
### 2. 使用 Logger(完全兼容 NestJS 官方 API)
|
|
40
|
+
|
|
41
|
+
本库完全遵循 NestJS 官方 Logger API,无缝替换官方 Logger。
|
|
40
42
|
|
|
41
43
|
```typescript
|
|
42
44
|
import { Injectable, Logger } from '@nestjs/common';
|
|
@@ -46,14 +48,87 @@ export class MyService {
|
|
|
46
48
|
private readonly logger = new Logger(MyService.name);
|
|
47
49
|
|
|
48
50
|
doSomething() {
|
|
51
|
+
// 简单日志
|
|
49
52
|
this.logger.log('This is an info log');
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.logger.
|
|
53
|
+
|
|
54
|
+
// 带 context 的日志(最后一个参数)
|
|
55
|
+
this.logger.log('User logged in', 'AuthModule');
|
|
56
|
+
// ↑ context
|
|
57
|
+
|
|
58
|
+
// 多个参数会用空格连接
|
|
59
|
+
this.logger.log('User', userId, 'logged in from', ip);
|
|
60
|
+
// 输出: User 123 logged in from 192.168.1.1
|
|
61
|
+
|
|
62
|
+
// 使用模板字符串
|
|
63
|
+
this.logger.log(`User ${userId} logged in from ${ip}`);
|
|
64
|
+
|
|
65
|
+
// 多参数 + context
|
|
66
|
+
this.logger.log('Processing order', orderId, 'OrderService');
|
|
67
|
+
// ↑ context
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
handleError() {
|
|
71
|
+
try {
|
|
72
|
+
// 业务逻辑
|
|
73
|
+
} catch (error) {
|
|
74
|
+
// Error 日志 + stack trace(官方推荐方式)
|
|
75
|
+
this.logger.error('Failed to process', error.stack);
|
|
76
|
+
// ↑ 第一个参数自动识别为 stack
|
|
77
|
+
|
|
78
|
+
// Error + stack + context
|
|
79
|
+
this.logger.error('Payment failed', error.stack, 'PaymentService');
|
|
80
|
+
// ↑ stack ↑ context
|
|
81
|
+
}
|
|
53
82
|
}
|
|
54
83
|
}
|
|
55
84
|
```
|
|
56
85
|
|
|
86
|
+
**参数规则(与 NestJS 官方一致)**:
|
|
87
|
+
- **最后一个字符串参数**:自动识别为 `context`
|
|
88
|
+
- **Error/Fatal 方法的第一个参数**:如果是 stack trace 格式,自动识别为 `stack`
|
|
89
|
+
- **多个参数**:会用空格连接成一个字符串
|
|
90
|
+
- **不支持格式化占位符**:不支持 `%s`, `%d`, `%o` 等占位符,请使用模板字符串
|
|
91
|
+
|
|
92
|
+
### 3. 使用 logStructured 记录结构化日志(扩展功能)
|
|
93
|
+
|
|
94
|
+
除了标准的 Logger API,本库还提供了 `logStructured()` 方法用于记录结构化日志:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
98
|
+
import { AppLogger } from '@lark-apaas/nestjs-logger';
|
|
99
|
+
|
|
100
|
+
@Injectable()
|
|
101
|
+
export class MyService {
|
|
102
|
+
constructor(
|
|
103
|
+
@Inject(AppLogger) private readonly logger: AppLogger,
|
|
104
|
+
) {}
|
|
105
|
+
|
|
106
|
+
doSomething() {
|
|
107
|
+
// 使用 logStructured 记录结构化日志
|
|
108
|
+
this.logger.logStructured(
|
|
109
|
+
'log', // 日志级别
|
|
110
|
+
'User action completed', // 消息
|
|
111
|
+
{ // 元数据对象(会合并到日志字段中)
|
|
112
|
+
action: 'create_order',
|
|
113
|
+
order_id: '123',
|
|
114
|
+
amount: 100,
|
|
115
|
+
},
|
|
116
|
+
'MyService', // context(可选)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**两种方式对比**:
|
|
123
|
+
|
|
124
|
+
| 特性 | 标准 Logger API | logStructured API |
|
|
125
|
+
|------|----------------|-------------------|
|
|
126
|
+
| **用途** | 常规日志,兼容 NestJS 官方 | 结构化日志,将 meta 合并到字段 |
|
|
127
|
+
| **Context** | 最后一个参数自动识别 | 显式传递第4个参数 |
|
|
128
|
+
| **消息格式** | 支持格式化占位符 | 纯文本消息 |
|
|
129
|
+
| **元数据** | 需要手动拼接到消息中 | 作为独立字段存储,便于查询 |
|
|
130
|
+
| **使用场景** | 日常日志、错误日志 | 需要结构化查询的业务日志 |
|
|
131
|
+
|
|
57
132
|
## 环境变量配置
|
|
58
133
|
|
|
59
134
|
### 基础配置
|
|
@@ -266,6 +341,14 @@ NestJS LoggerService 级别到 Pino 级别的映射:
|
|
|
266
341
|
- **延迟记录**:不在 Interceptor 的 `tap()` 或 `catchError()` 中记录日志,而是在 `finish` 事件中统一记录
|
|
267
342
|
- **完整信息**:此时可以获取 Exception Filter 处理后的最终状态码和响应体,确保日志准确性
|
|
268
343
|
|
|
344
|
+
4. **Logger API 兼容性**:
|
|
345
|
+
- **完全兼容 NestJS 官方**:实现与 `@nestjs/common` 的 Logger 完全一致的 API
|
|
346
|
+
- **参数解析规则**:
|
|
347
|
+
- 最后一个字符串参数自动识别为 `context`
|
|
348
|
+
- Error/Fatal 方法的第一个参数如果是 stack trace 格式,自动识别为 `stack`
|
|
349
|
+
- **无缝替换**:可以直接替换项目中的官方 Logger,无需修改业务代码
|
|
350
|
+
- **扩展功能**:提供 `logStructured()` 方法用于结构化日志场景
|
|
351
|
+
|
|
269
352
|
### 安全性
|
|
270
353
|
|
|
271
354
|
1. **生产环境默认不打印 HTTP 追踪日志**:由于使用 verbose 级别,生产环境(info 级别)默认不会输出详细日志
|
package/dist/index.cjs
CHANGED
|
@@ -14382,7 +14382,6 @@ module.exports = __toCommonJS(index_exports);
|
|
|
14382
14382
|
|
|
14383
14383
|
// src/service/app-logger.service.ts
|
|
14384
14384
|
var import_common2 = require("@nestjs/common");
|
|
14385
|
-
var import_util = require("util");
|
|
14386
14385
|
|
|
14387
14386
|
// src/helper/constants.ts
|
|
14388
14387
|
var PINO_ROOT_LOGGER = Symbol("PINO_ROOT_LOGGER");
|
|
@@ -14678,8 +14677,12 @@ var BasePinoLogger = class _BasePinoLogger {
|
|
|
14678
14677
|
messageText: message
|
|
14679
14678
|
};
|
|
14680
14679
|
}
|
|
14680
|
+
const allMessages = [
|
|
14681
|
+
message,
|
|
14682
|
+
...extras.map((e) => String(e))
|
|
14683
|
+
].join(" ");
|
|
14681
14684
|
return {
|
|
14682
|
-
messageText:
|
|
14685
|
+
messageText: allMessages
|
|
14683
14686
|
};
|
|
14684
14687
|
}
|
|
14685
14688
|
if (typeof message === "object" && message !== null) {
|
|
@@ -14784,7 +14787,7 @@ function normalizeLevel(level) {
|
|
|
14784
14787
|
}
|
|
14785
14788
|
__name(normalizeLevel, "normalizeLevel");
|
|
14786
14789
|
var logger_config_default = (0, import_config.registerAs)("logger", () => {
|
|
14787
|
-
const level = normalizeLevel(process.env.LOGGER_LEVEL || (process.env.NODE_ENV === "production" ? "
|
|
14790
|
+
const level = normalizeLevel(process.env.LOGGER_LEVEL || (process.env.NODE_ENV === "production" ? "trace" : "trace"));
|
|
14788
14791
|
const maxBodyLengthEnv = process.env.LOG_MAX_BODY_LENGTH;
|
|
14789
14792
|
const maxBodyLength = maxBodyLengthEnv ? Number(maxBodyLengthEnv) : null;
|
|
14790
14793
|
return {
|
|
@@ -14874,7 +14877,8 @@ var LoggingInterceptor = class {
|
|
|
14874
14877
|
if (this.config.logRequestBody && Object.keys(req.query || {}).length > 0) {
|
|
14875
14878
|
requestMeta["query_params"] = this.sanitizeAndTruncate(req.query);
|
|
14876
14879
|
}
|
|
14877
|
-
this.appLogger.log(
|
|
14880
|
+
this.appLogger.log(`HTTP request started
|
|
14881
|
+
url=${req.url}`, "HTTPTraceInterceptor");
|
|
14878
14882
|
this.traceLogger.logStructured("verbose", "HTTP request started", requestMeta, "HTTPTraceInterceptor");
|
|
14879
14883
|
let logged = false;
|
|
14880
14884
|
res.on("finish", () => {
|
|
@@ -14901,15 +14905,29 @@ var LoggingInterceptor = class {
|
|
|
14901
14905
|
const shouldLogBody = this.config.logResponseBody && isJsonResponse && finalResponseBody !== void 0;
|
|
14902
14906
|
if (isError) {
|
|
14903
14907
|
if (shouldLogBody) {
|
|
14904
|
-
appLog(
|
|
14908
|
+
appLog(`HTTP request failed
|
|
14909
|
+
url=${req.url}
|
|
14910
|
+
status_code=${statusCode}
|
|
14911
|
+
duration_ms=${durationMs}
|
|
14912
|
+
response_body=${JSON.stringify(finalResponseBody ?? {})}`, "HTTPTraceInterceptor");
|
|
14905
14913
|
} else {
|
|
14906
|
-
appLog(
|
|
14914
|
+
appLog(`HTTP request failed
|
|
14915
|
+
url=${req.url}
|
|
14916
|
+
status_code=${statusCode}
|
|
14917
|
+
duration_ms=${durationMs}`, "HTTPTraceInterceptor");
|
|
14907
14918
|
}
|
|
14908
14919
|
} else {
|
|
14909
14920
|
if (shouldLogBody) {
|
|
14910
|
-
appLog(
|
|
14921
|
+
appLog(`HTTP request completed
|
|
14922
|
+
url=${req.url}
|
|
14923
|
+
status_code=${statusCode}
|
|
14924
|
+
duration_ms=${durationMs}
|
|
14925
|
+
response_body=${JSON.stringify(finalResponseBody ?? {})}`, "HTTPTraceInterceptor");
|
|
14911
14926
|
} else {
|
|
14912
|
-
appLog(
|
|
14927
|
+
appLog(`HTTP request completed
|
|
14928
|
+
url=${req.url}
|
|
14929
|
+
status_code=${statusCode}
|
|
14930
|
+
duration_ms=${durationMs}`, "HTTPTraceInterceptor");
|
|
14913
14931
|
}
|
|
14914
14932
|
}
|
|
14915
14933
|
this.traceLogger.logStructured(traceLevel, isError ? "HTTP request failed" : "HTTP request completed", responseMeta, "HTTPTraceInterceptor");
|