@lark-apaas/nestjs-logger 1.0.1-alpha.0 → 1.0.1-alpha.1

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 CHANGED
@@ -99,6 +99,14 @@ HTTP 请求追踪日志使用 **`verbose` 级别**(对应 Pino 的 `trace` 级
99
99
  - **需要显式启用**:要查看 HTTP 请求追踪日志,需要将 `LOGGER_LEVEL` 设置为 `verbose`
100
100
  - **细粒度控制**:可以通过日志级别控制是否打印请求追踪,而无需修改 `LOG_REQUEST_BODY` 和 `LOG_RESPONSE_BODY` 配置
101
101
 
102
+ ### 响应体记录规则
103
+
104
+ **只针对 JSON 响应记录 body**:
105
+ - 自动检测 `Content-Type` 是否包含 `application/json`
106
+ - 只有 JSON 响应才会记录 `response_body` 字段
107
+ - 文件下载、HTML 页面等非 JSON 响应不会记录 body,避免日志污染
108
+ - 这样可以显著减少日志体积,同时保持日志的可读性
109
+
102
110
  ### 启用方式
103
111
 
104
112
  通过环境变量启用:
@@ -121,7 +129,11 @@ LOG_RESPONSE_BODY=true
121
129
 
122
130
  2. **默认不限制长度**:如果不设置 `LOG_MAX_BODY_LENGTH` 环境变量,日志体不会被截断。建议在生产环境设置合理的限制值。
123
131
 
124
- 3. **响应数据处理**:日志库会尝试序列化所有响应数据,对于无法序列化的数据(如 Buffer、Stream)会返回类型信息。
132
+ 3. **响应体过滤**:
133
+ - 只记录 JSON 响应的 body(检测 Content-Type)
134
+ - 文件下载、HTML、图片等非 JSON 响应不会记录 body
135
+ - 避免记录无法序列化的数据(如 Buffer、Stream)
136
+ - 显著减少日志体积,提高日志可读性
125
137
 
126
138
  ### 日志输出示例
127
139
 
@@ -250,6 +262,7 @@ NestJS LoggerService 级别到 Pino 级别的映射:
250
262
 
251
263
  3. **实现原理**:
252
264
  - **拦截响应方法**:在 Interceptor 中拦截 `res.json()` 和 `res.send()`,存储响应体到 `res.__finalResponseBody`
265
+ - **类型检测**:通过 `Content-Type` header 判断是否为 JSON 响应,只记录 JSON 类型的 body
253
266
  - **延迟记录**:不在 Interceptor 的 `tap()` 或 `catchError()` 中记录日志,而是在 `finish` 事件中统一记录
254
267
  - **完整信息**:此时可以获取 Exception Filter 处理后的最终状态码和响应体,确保日志准确性
255
268
 
package/dist/index.cjs CHANGED
@@ -14890,16 +14890,27 @@ var LoggingInterceptor = class {
14890
14890
  duration_ms: durationMs
14891
14891
  };
14892
14892
  const finalResponseBody = res.__finalResponseBody;
14893
- if (this.config.logResponseBody && finalResponseBody !== void 0) {
14893
+ const contentType = res.getHeader("content-type");
14894
+ const isJsonResponse = typeof contentType === "string" && contentType.includes("application/json");
14895
+ if (this.config.logResponseBody && finalResponseBody !== void 0 && isJsonResponse) {
14894
14896
  responseMeta["response_body"] = this.sanitizeAndTruncate(finalResponseBody);
14895
14897
  }
14896
14898
  const isError = statusCode >= 400;
14897
14899
  const appLog = this.appLogger[isError ? "error" : "log"].bind(this.appLogger);
14898
14900
  const traceLevel = isError ? "error" : "verbose";
14901
+ const shouldLogBody = this.config.logResponseBody && isJsonResponse && finalResponseBody !== void 0;
14899
14902
  if (isError) {
14900
- appLog("HTTP request failed\n url=%s \n status_code=%d \n duration_ms=%d \n response_body=%o", req.url, statusCode, durationMs, finalResponseBody ?? {});
14903
+ if (shouldLogBody) {
14904
+ appLog("HTTP request failed\n url=%s \n status_code=%d \n duration_ms=%d \n response_body=%o", req.url, statusCode, durationMs, finalResponseBody);
14905
+ } else {
14906
+ appLog("HTTP request failed\n url=%s \n status_code=%d \n duration_ms=%d", req.url, statusCode, durationMs);
14907
+ }
14901
14908
  } else {
14902
- appLog("HTTP request completed\n url=%s \n status_code=%d \n duration_ms=%d \n response_body=%o", req.url, statusCode, durationMs, finalResponseBody ?? {});
14909
+ if (shouldLogBody) {
14910
+ appLog("HTTP request completed\n url=%s \n status_code=%d \n duration_ms=%d \n response_body=%o", req.url, statusCode, durationMs, finalResponseBody);
14911
+ } else {
14912
+ appLog("HTTP request completed\n url=%s \n status_code=%d \n duration_ms=%d", req.url, statusCode, durationMs);
14913
+ }
14903
14914
  }
14904
14915
  this.traceLogger.logStructured(traceLevel, isError ? "HTTP request failed" : "HTTP request completed", responseMeta, "HTTPTraceInterceptor");
14905
14916
  });