@lark-apaas/nestjs-logger 0.1.0-alpha.1 → 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/README.md +320 -0
- package/dist/index.cjs +112 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -82
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14520,13 +14520,11 @@ var BasePinoLogger = class _BasePinoLogger {
|
|
|
14520
14520
|
const traceId = requestState?.requestId ?? null;
|
|
14521
14521
|
const payload = {
|
|
14522
14522
|
trace_id: traceId,
|
|
14523
|
-
requestId: traceId,
|
|
14524
14523
|
path: requestState?.path,
|
|
14525
14524
|
method: requestState?.method,
|
|
14526
14525
|
user_id: requestState?.userId ?? null,
|
|
14527
14526
|
app_id: requestState?.appId ?? null,
|
|
14528
14527
|
tenant_id: requestState?.tenantId ?? null,
|
|
14529
|
-
ip: requestState?.ip ?? null,
|
|
14530
14528
|
pid: process.pid
|
|
14531
14529
|
};
|
|
14532
14530
|
if (context) {
|
|
@@ -14671,7 +14669,7 @@ function sanitizeValue(value) {
|
|
|
14671
14669
|
__name(sanitizeValue, "sanitizeValue");
|
|
14672
14670
|
|
|
14673
14671
|
// src/module.ts
|
|
14674
|
-
var
|
|
14672
|
+
var import_config3 = __toESM(require_config2(), 1);
|
|
14675
14673
|
import { Global, Module } from "@nestjs/common";
|
|
14676
14674
|
import { APP_INTERCEPTOR } from "@nestjs/core";
|
|
14677
14675
|
|
|
@@ -14693,48 +14691,22 @@ function normalizeLevel(level) {
|
|
|
14693
14691
|
}
|
|
14694
14692
|
}
|
|
14695
14693
|
__name(normalizeLevel, "normalizeLevel");
|
|
14696
|
-
function parseDestinations(raw) {
|
|
14697
|
-
if (!raw) {
|
|
14698
|
-
return [
|
|
14699
|
-
{
|
|
14700
|
-
type: "stdout"
|
|
14701
|
-
}
|
|
14702
|
-
];
|
|
14703
|
-
}
|
|
14704
|
-
return raw.split(",").map((token) => token.trim()).filter(Boolean).map((token) => {
|
|
14705
|
-
const [typeAndPath, level] = token.split("@");
|
|
14706
|
-
const [type, path] = typeAndPath.split(":");
|
|
14707
|
-
const normalizedType = (type ?? "stdout").toLowerCase();
|
|
14708
|
-
if (normalizedType === "file") {
|
|
14709
|
-
return {
|
|
14710
|
-
type: "file",
|
|
14711
|
-
path: path || "logs/app.log",
|
|
14712
|
-
level
|
|
14713
|
-
};
|
|
14714
|
-
}
|
|
14715
|
-
if (normalizedType === "stderr") {
|
|
14716
|
-
return {
|
|
14717
|
-
type: "stderr",
|
|
14718
|
-
level
|
|
14719
|
-
};
|
|
14720
|
-
}
|
|
14721
|
-
return {
|
|
14722
|
-
type: "stdout",
|
|
14723
|
-
level
|
|
14724
|
-
};
|
|
14725
|
-
});
|
|
14726
|
-
}
|
|
14727
|
-
__name(parseDestinations, "parseDestinations");
|
|
14728
14694
|
var logger_config_default = (0, import_config.registerAs)("logger", () => {
|
|
14729
14695
|
const level = normalizeLevel(process.env.LOGGER_LEVEL || (process.env.NODE_ENV === "production" ? "info" : "debug"));
|
|
14730
|
-
const
|
|
14696
|
+
const maxBodyLengthEnv = process.env.LOG_MAX_BODY_LENGTH;
|
|
14697
|
+
const maxBodyLength = maxBodyLengthEnv ? Number(maxBodyLengthEnv) : null;
|
|
14731
14698
|
return {
|
|
14732
14699
|
level,
|
|
14733
|
-
|
|
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())
|
|
14734
14705
|
};
|
|
14735
14706
|
});
|
|
14736
14707
|
|
|
14737
14708
|
// src/interceptor/logging.interceptor.ts
|
|
14709
|
+
var import_config2 = __toESM(require_config2(), 1);
|
|
14738
14710
|
var import_operators = __toESM(require_operators(), 1);
|
|
14739
14711
|
import { Inject as Inject2, Injectable as Injectable3, LoggerService } from "@nestjs/common";
|
|
14740
14712
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
@@ -14760,9 +14732,11 @@ var LoggingInterceptor = class {
|
|
|
14760
14732
|
}
|
|
14761
14733
|
traceLogger;
|
|
14762
14734
|
requestContext;
|
|
14763
|
-
|
|
14735
|
+
config;
|
|
14736
|
+
constructor(traceLogger, requestContext, config) {
|
|
14764
14737
|
this.traceLogger = traceLogger;
|
|
14765
14738
|
this.requestContext = requestContext;
|
|
14739
|
+
this.config = config;
|
|
14766
14740
|
}
|
|
14767
14741
|
intercept(context, next) {
|
|
14768
14742
|
if (context.getType() !== "http") {
|
|
@@ -14781,7 +14755,6 @@ var LoggingInterceptor = class {
|
|
|
14781
14755
|
const baseMeta = {
|
|
14782
14756
|
method,
|
|
14783
14757
|
path: url,
|
|
14784
|
-
requestId: req.requestId ?? req.id,
|
|
14785
14758
|
trace_id: req.requestId ?? req.id,
|
|
14786
14759
|
user_id: req.userContext?.userId ?? null,
|
|
14787
14760
|
tenant_id: req.userContext?.tenantId ?? null,
|
|
@@ -14789,15 +14762,32 @@ var LoggingInterceptor = class {
|
|
|
14789
14762
|
ip: req.ip ?? null,
|
|
14790
14763
|
pid: process.pid
|
|
14791
14764
|
};
|
|
14792
|
-
|
|
14793
|
-
|
|
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) => {
|
|
14794
14776
|
const durationMs = Date.now() - startedAt;
|
|
14795
14777
|
const statusCode = res.statusCode;
|
|
14796
|
-
|
|
14778
|
+
const responseMeta = {
|
|
14797
14779
|
...baseMeta,
|
|
14798
14780
|
statusCode,
|
|
14799
14781
|
durationMs
|
|
14800
|
-
}
|
|
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");
|
|
14801
14791
|
}), (0, import_operators.catchError)((error) => {
|
|
14802
14792
|
const durationMs = Date.now() - startedAt;
|
|
14803
14793
|
const statusCode = res.statusCode >= 400 ? res.statusCode : 500;
|
|
@@ -14814,14 +14804,78 @@ var LoggingInterceptor = class {
|
|
|
14814
14804
|
throw error;
|
|
14815
14805
|
}));
|
|
14816
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
|
+
}
|
|
14817
14869
|
};
|
|
14818
14870
|
LoggingInterceptor = _ts_decorate3([
|
|
14819
14871
|
Injectable3(),
|
|
14820
14872
|
_ts_param2(0, Inject2(TRACE_LOGGER)),
|
|
14873
|
+
_ts_param2(2, Inject2(logger_config_default.KEY)),
|
|
14821
14874
|
_ts_metadata2("design:type", Function),
|
|
14822
14875
|
_ts_metadata2("design:paramtypes", [
|
|
14823
14876
|
typeof LoggerService === "undefined" ? Object : LoggerService,
|
|
14824
|
-
typeof RequestContextService === "undefined" ? Object : RequestContextService
|
|
14877
|
+
typeof RequestContextService === "undefined" ? Object : RequestContextService,
|
|
14878
|
+
typeof import_config2.ConfigType === "undefined" ? Object : import_config2.ConfigType
|
|
14825
14879
|
])
|
|
14826
14880
|
], LoggingInterceptor);
|
|
14827
14881
|
|
|
@@ -14844,12 +14898,12 @@ function createPinoLogger(config) {
|
|
|
14844
14898
|
}
|
|
14845
14899
|
}
|
|
14846
14900
|
};
|
|
14847
|
-
const
|
|
14901
|
+
const streams = [
|
|
14848
14902
|
{
|
|
14849
|
-
|
|
14903
|
+
level: config.level,
|
|
14904
|
+
stream: createFileDestination(config.filePath)
|
|
14850
14905
|
}
|
|
14851
14906
|
];
|
|
14852
|
-
const streams = buildStreams(destinations, baseLevel);
|
|
14853
14907
|
if (streams.length === 0) {
|
|
14854
14908
|
return pino(options);
|
|
14855
14909
|
}
|
|
@@ -14859,30 +14913,6 @@ function createPinoLogger(config) {
|
|
|
14859
14913
|
return pino(options, pino.multistream(streams));
|
|
14860
14914
|
}
|
|
14861
14915
|
__name(createPinoLogger, "createPinoLogger");
|
|
14862
|
-
function buildStreams(destinations, fallbackLevel) {
|
|
14863
|
-
return destinations.map((destination) => {
|
|
14864
|
-
const level = normalizeLevel(destination.level ?? fallbackLevel);
|
|
14865
|
-
switch (destination.type) {
|
|
14866
|
-
case "stderr":
|
|
14867
|
-
return {
|
|
14868
|
-
level,
|
|
14869
|
-
stream: process.stderr
|
|
14870
|
-
};
|
|
14871
|
-
case "file":
|
|
14872
|
-
return {
|
|
14873
|
-
level,
|
|
14874
|
-
stream: createFileDestination(destination.path)
|
|
14875
|
-
};
|
|
14876
|
-
case "stdout":
|
|
14877
|
-
default:
|
|
14878
|
-
return {
|
|
14879
|
-
level,
|
|
14880
|
-
stream: process.stdout
|
|
14881
|
-
};
|
|
14882
|
-
}
|
|
14883
|
-
});
|
|
14884
|
-
}
|
|
14885
|
-
__name(buildStreams, "buildStreams");
|
|
14886
14916
|
function createFileDestination(pathname) {
|
|
14887
14917
|
const target = pathname && pathname.length > 0 ? pathname : "logs/app.log";
|
|
14888
14918
|
const resolved = isAbsolute(target) ? target : join(process.cwd(), target);
|
|
@@ -14963,32 +14993,32 @@ LoggerModule = _ts_decorate5([
|
|
|
14963
14993
|
Global(),
|
|
14964
14994
|
Module({
|
|
14965
14995
|
imports: [
|
|
14966
|
-
|
|
14996
|
+
import_config3.ConfigModule.forFeature(logger_config_default)
|
|
14967
14997
|
],
|
|
14968
14998
|
providers: [
|
|
14969
14999
|
RequestContextService,
|
|
14970
15000
|
LoggerContextMiddleware,
|
|
14971
15001
|
{
|
|
14972
15002
|
provide: PINO_ROOT_LOGGER,
|
|
14973
|
-
useFactory: /* @__PURE__ */ __name((config) =>
|
|
15003
|
+
useFactory: /* @__PURE__ */ __name((config) => {
|
|
15004
|
+
return createPinoLogger({
|
|
15005
|
+
level: "trace",
|
|
15006
|
+
filePath: `${config.logDir}/app.log`
|
|
15007
|
+
});
|
|
15008
|
+
}, "useFactory"),
|
|
14974
15009
|
inject: [
|
|
14975
15010
|
logger_config_default.KEY
|
|
14976
15011
|
]
|
|
14977
15012
|
},
|
|
14978
15013
|
{
|
|
14979
15014
|
provide: TRACE_LOGGER,
|
|
14980
|
-
useFactory: /* @__PURE__ */ __name((requestContext) => new PinoLoggerService(createPinoLogger({
|
|
15015
|
+
useFactory: /* @__PURE__ */ __name((requestContext, config) => new PinoLoggerService(createPinoLogger({
|
|
14981
15016
|
level: "trace",
|
|
14982
|
-
|
|
14983
|
-
{
|
|
14984
|
-
type: "file",
|
|
14985
|
-
path: "logs/trace.log",
|
|
14986
|
-
level: "trace"
|
|
14987
|
-
}
|
|
14988
|
-
]
|
|
15017
|
+
filePath: `${config.logDir}/trace.log`
|
|
14989
15018
|
}), requestContext), "useFactory"),
|
|
14990
15019
|
inject: [
|
|
14991
|
-
RequestContextService
|
|
15020
|
+
RequestContextService,
|
|
15021
|
+
logger_config_default.KEY
|
|
14992
15022
|
]
|
|
14993
15023
|
},
|
|
14994
15024
|
AppLogger,
|