@lark-apaas/nestjs-logger 0.1.0-alpha.2 → 0.1.0-alpha.3

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/dist/index.js CHANGED
@@ -14669,7 +14669,7 @@ function sanitizeValue(value) {
14669
14669
  __name(sanitizeValue, "sanitizeValue");
14670
14670
 
14671
14671
  // src/module.ts
14672
- var import_config2 = __toESM(require_config2(), 1);
14672
+ var import_config3 = __toESM(require_config2(), 1);
14673
14673
  import { Global, Module } from "@nestjs/common";
14674
14674
  import { APP_INTERCEPTOR } from "@nestjs/core";
14675
14675
 
@@ -14693,13 +14693,20 @@ function normalizeLevel(level) {
14693
14693
  __name(normalizeLevel, "normalizeLevel");
14694
14694
  var logger_config_default = (0, import_config.registerAs)("logger", () => {
14695
14695
  const level = normalizeLevel(process.env.LOGGER_LEVEL || (process.env.NODE_ENV === "production" ? "info" : "debug"));
14696
+ const maxBodyLengthEnv = process.env.LOG_MAX_BODY_LENGTH;
14697
+ const maxBodyLength = maxBodyLengthEnv ? Number(maxBodyLengthEnv) : null;
14696
14698
  return {
14697
14699
  level,
14698
- logDir: process.env.LOG_DIR || "logs"
14700
+ logDir: process.env.LOG_DIR || "logs",
14701
+ logRequestBody: process.env.LOG_REQUEST_BODY === "true",
14702
+ logResponseBody: process.env.LOG_RESPONSE_BODY === "true",
14703
+ maxBodyLength,
14704
+ sensitiveFields: (process.env.LOG_SENSITIVE_FIELDS || "password,token,secret,authorization,cookie,apiKey,accessToken,refreshToken").split(",").map((f) => f.trim())
14699
14705
  };
14700
14706
  });
14701
14707
 
14702
14708
  // src/interceptor/logging.interceptor.ts
14709
+ var import_config2 = __toESM(require_config2(), 1);
14703
14710
  var import_operators = __toESM(require_operators(), 1);
14704
14711
  import { Inject as Inject2, Injectable as Injectable3, LoggerService } from "@nestjs/common";
14705
14712
  function _ts_decorate3(decorators, target, key, desc) {
@@ -14725,9 +14732,11 @@ var LoggingInterceptor = class {
14725
14732
  }
14726
14733
  traceLogger;
14727
14734
  requestContext;
14728
- constructor(traceLogger, requestContext) {
14735
+ config;
14736
+ constructor(traceLogger, requestContext, config) {
14729
14737
  this.traceLogger = traceLogger;
14730
14738
  this.requestContext = requestContext;
14739
+ this.config = config;
14731
14740
  }
14732
14741
  intercept(context, next) {
14733
14742
  if (context.getType() !== "http") {
@@ -14746,7 +14755,6 @@ var LoggingInterceptor = class {
14746
14755
  const baseMeta = {
14747
14756
  method,
14748
14757
  path: url,
14749
- requestId: req.requestId ?? req.id,
14750
14758
  trace_id: req.requestId ?? req.id,
14751
14759
  user_id: req.userContext?.userId ?? null,
14752
14760
  tenant_id: req.userContext?.tenantId ?? null,
@@ -14754,15 +14762,32 @@ var LoggingInterceptor = class {
14754
14762
  ip: req.ip ?? null,
14755
14763
  pid: process.pid
14756
14764
  };
14757
- this.traceLogger.log("HTTP request started", baseMeta, "HTTP");
14758
- return next.handle().pipe((0, import_operators.tap)(() => {
14765
+ const requestMeta = {
14766
+ ...baseMeta
14767
+ };
14768
+ if (this.config.logRequestBody && req.body) {
14769
+ requestMeta["requestBody"] = this.sanitizeAndTruncate(req.body);
14770
+ }
14771
+ if (this.config.logRequestBody && Object.keys(req.query || {}).length > 0) {
14772
+ requestMeta["queryParams"] = this.sanitizeAndTruncate(req.query);
14773
+ }
14774
+ this.traceLogger.verbose?.("HTTP request started", requestMeta, "HTTP");
14775
+ return next.handle().pipe((0, import_operators.tap)((responseData) => {
14759
14776
  const durationMs = Date.now() - startedAt;
14760
14777
  const statusCode = res.statusCode;
14761
- this.traceLogger.log("HTTP request completed", {
14778
+ const responseMeta = {
14762
14779
  ...baseMeta,
14763
14780
  statusCode,
14764
14781
  durationMs
14765
- }, "HTTP");
14782
+ };
14783
+ if (this.config.logResponseBody && responseData !== void 0) {
14784
+ const contentType = res.getHeader("content-type");
14785
+ const isJsonResponse = this.isJsonContentType(contentType);
14786
+ if (isJsonResponse) {
14787
+ responseMeta["responseBody"] = this.sanitizeAndTruncate(responseData);
14788
+ }
14789
+ }
14790
+ this.traceLogger.verbose?.("HTTP request completed", responseMeta, "HTTP");
14766
14791
  }), (0, import_operators.catchError)((error) => {
14767
14792
  const durationMs = Date.now() - startedAt;
14768
14793
  const statusCode = res.statusCode >= 400 ? res.statusCode : 500;
@@ -14779,14 +14804,78 @@ var LoggingInterceptor = class {
14779
14804
  throw error;
14780
14805
  }));
14781
14806
  }
14807
+ /**
14808
+ * 对数据进行脱敏和截断处理
14809
+ */
14810
+ sanitizeAndTruncate(data) {
14811
+ try {
14812
+ const sanitized = this.maskSensitiveFields(data);
14813
+ if (this.config.maxBodyLength === null) {
14814
+ return sanitized;
14815
+ }
14816
+ const jsonStr = JSON.stringify(sanitized);
14817
+ if (jsonStr.length > this.config.maxBodyLength) {
14818
+ return {
14819
+ _truncated: true,
14820
+ _originalLength: jsonStr.length,
14821
+ _data: jsonStr.substring(0, this.config.maxBodyLength) + "..."
14822
+ };
14823
+ }
14824
+ return sanitized;
14825
+ } catch (error) {
14826
+ return {
14827
+ _error: "Failed to serialize data",
14828
+ _message: error instanceof Error ? error.message : String(error)
14829
+ };
14830
+ }
14831
+ }
14832
+ /**
14833
+ * 判断是否是 JSON 响应类型
14834
+ */
14835
+ isJsonContentType(contentType) {
14836
+ if (typeof contentType !== "string") {
14837
+ return false;
14838
+ }
14839
+ const contentTypeLower = contentType.toLowerCase();
14840
+ return contentTypeLower.includes("application/json") || contentTypeLower.includes("application/vnd.api+json") || contentTypeLower.includes("+json");
14841
+ }
14842
+ /**
14843
+ * 脱敏敏感字段
14844
+ */
14845
+ maskSensitiveFields(data) {
14846
+ if (data === null || data === void 0) {
14847
+ return data;
14848
+ }
14849
+ if (Array.isArray(data)) {
14850
+ return data.map((item) => this.maskSensitiveFields(item));
14851
+ }
14852
+ if (typeof data === "object") {
14853
+ const result = {};
14854
+ for (const [key, value] of Object.entries(data)) {
14855
+ const lowerKey = key.toLowerCase();
14856
+ const isSensitive = this.config.sensitiveFields.some((field) => lowerKey.includes(field.toLowerCase()));
14857
+ if (isSensitive) {
14858
+ result[key] = "***MASKED***";
14859
+ } else if (typeof value === "object" && value !== null) {
14860
+ result[key] = this.maskSensitiveFields(value);
14861
+ } else {
14862
+ result[key] = value;
14863
+ }
14864
+ }
14865
+ return result;
14866
+ }
14867
+ return data;
14868
+ }
14782
14869
  };
14783
14870
  LoggingInterceptor = _ts_decorate3([
14784
14871
  Injectable3(),
14785
14872
  _ts_param2(0, Inject2(TRACE_LOGGER)),
14873
+ _ts_param2(2, Inject2(logger_config_default.KEY)),
14786
14874
  _ts_metadata2("design:type", Function),
14787
14875
  _ts_metadata2("design:paramtypes", [
14788
14876
  typeof LoggerService === "undefined" ? Object : LoggerService,
14789
- typeof RequestContextService === "undefined" ? Object : RequestContextService
14877
+ typeof RequestContextService === "undefined" ? Object : RequestContextService,
14878
+ typeof import_config2.ConfigType === "undefined" ? Object : import_config2.ConfigType
14790
14879
  ])
14791
14880
  ], LoggingInterceptor);
14792
14881
 
@@ -14904,7 +14993,7 @@ LoggerModule = _ts_decorate5([
14904
14993
  Global(),
14905
14994
  Module({
14906
14995
  imports: [
14907
- import_config2.ConfigModule.forFeature(logger_config_default)
14996
+ import_config3.ConfigModule.forFeature(logger_config_default)
14908
14997
  ],
14909
14998
  providers: [
14910
14999
  RequestContextService,