[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger":2674,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger":2700},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":2670,"stem":2671,"id":2672,"extension":2673},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","内置 Logger 可替换为 Pino 等实现。","技能小册",[12,13],"nestjs","logger","2022-10-10",false,{"type":17,"value":18,"toc":2660},"minimark",[19,22,31,42,47,57,62,378,382,475,482,511,515,521,749,757,766,1046,1049,1076,1080,1084,1099,1102,1121,1124,1344,1347,1493,1497,1502,1504,1521,1524,1760,1774,1941,1945,1948,2382,2385,2467,2478,2482,2530,2533,2596,2599,2603,2606,2656],[20,21,8],"h1",{"id":8},[23,24,25,26,30],"p",{},"内置 ",[27,28,29],"code",{},"Logger"," 可替换为 Pino 等实现。",[23,32,33,34,37,38,41],{},"日志是监控和调试应用的重要手段。NestJS 内置了轻量级日志器，同时也支持与 ",[27,35,36],{},"pino","、",[27,39,40],{},"winston"," 等专业日志库集成，满足生产环境需求。",[43,44,46],"h3",{"id":45},"一内置-logger","一、内置 Logger",[23,48,49,50,53,54,56],{},"NestJS 在 ",[27,51,52],{},"@nestjs\u002Fcommon"," 中提供了 ",[27,55,29],{}," 类，支持多种日志级别，开箱即用。",[58,59,61],"h4",{"id":60},"_1-基本使用","1. 基本使用",[63,64,69],"pre",{"className":65,"code":66,"language":67,"meta":68,"style":68},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Logger } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class AppService {\n  private readonly logger = new Logger(AppService.name);\n\n  getHello(): string {\n    this.logger.log(\"Returning hello\");\n    this.logger.debug(\"Debug info\");\n    this.logger.warn(\"Warning message\");\n    this.logger.error(\"Error occurred\", \"stack trace\");\n    this.logger.verbose(\"Verbose output\");\n    return \"Hello World!\";\n  }\n}\n","ts","",[27,70,71,107,114,127,144,178,183,201,233,260,287,324,351,366,372],{"__ignoreMap":68},[72,73,76,80,84,88,91,94,98,101,104],"span",{"class":74,"line":75},"line",1,[72,77,79],{"class":78},"sVHd0","import",[72,81,83],{"class":82},"sP7_E"," {",[72,85,87],{"class":86},"su5hD"," Logger",[72,89,90],{"class":82}," }",[72,92,93],{"class":78}," from",[72,95,97],{"class":96},"sjJ54"," \"",[72,99,52],{"class":100},"s_sjI",[72,102,103],{"class":96},"\"",[72,105,106],{"class":82},";\n",[72,108,110],{"class":74,"line":109},2,[72,111,113],{"emptyLinePlaceholder":112},true,"\n",[72,115,117,120,124],{"class":74,"line":116},3,[72,118,119],{"class":82},"@",[72,121,123],{"class":122},"sGLFI","Injectable",[72,125,126],{"class":86},"()\n",[72,128,130,133,137,141],{"class":74,"line":129},4,[72,131,132],{"class":78},"export",[72,134,136],{"class":135},"sbsja"," class",[72,138,140],{"class":139},"sbgvK"," AppService",[72,142,143],{"class":82}," {\n",[72,145,147,150,153,157,161,164,167,170,173,176],{"class":74,"line":146},5,[72,148,149],{"class":135},"  private",[72,151,152],{"class":135}," readonly",[72,154,156],{"class":155},"sucvu"," logger",[72,158,160],{"class":159},"smGrS"," =",[72,162,163],{"class":159}," new",[72,165,87],{"class":166},"sVXei",[72,168,169],{"class":86},"(AppService",[72,171,172],{"class":82},".",[72,174,175],{"class":86},"name)",[72,177,106],{"class":82},[72,179,181],{"class":74,"line":180},6,[72,182,113],{"emptyLinePlaceholder":112},[72,184,186,189,192,195,199],{"class":74,"line":185},7,[72,187,188],{"class":166},"  getHello",[72,190,191],{"class":82},"()",[72,193,194],{"class":159},":",[72,196,198],{"class":197},"sZMiF"," string",[72,200,143],{"class":82},[72,202,204,208,210,212,214,217,221,223,226,228,231],{"class":74,"line":203},8,[72,205,207],{"class":206},"s39Yj","    this",[72,209,172],{"class":82},[72,211,13],{"class":86},[72,213,172],{"class":82},[72,215,216],{"class":122},"log",[72,218,220],{"class":219},"skxfh","(",[72,222,103],{"class":96},[72,224,225],{"class":100},"Returning hello",[72,227,103],{"class":96},[72,229,230],{"class":219},")",[72,232,106],{"class":82},[72,234,236,238,240,242,244,247,249,251,254,256,258],{"class":74,"line":235},9,[72,237,207],{"class":206},[72,239,172],{"class":82},[72,241,13],{"class":86},[72,243,172],{"class":82},[72,245,246],{"class":122},"debug",[72,248,220],{"class":219},[72,250,103],{"class":96},[72,252,253],{"class":100},"Debug info",[72,255,103],{"class":96},[72,257,230],{"class":219},[72,259,106],{"class":82},[72,261,263,265,267,269,271,274,276,278,281,283,285],{"class":74,"line":262},10,[72,264,207],{"class":206},[72,266,172],{"class":82},[72,268,13],{"class":86},[72,270,172],{"class":82},[72,272,273],{"class":122},"warn",[72,275,220],{"class":219},[72,277,103],{"class":96},[72,279,280],{"class":100},"Warning message",[72,282,103],{"class":96},[72,284,230],{"class":219},[72,286,106],{"class":82},[72,288,290,292,294,296,298,301,303,305,308,310,313,315,318,320,322],{"class":74,"line":289},11,[72,291,207],{"class":206},[72,293,172],{"class":82},[72,295,13],{"class":86},[72,297,172],{"class":82},[72,299,300],{"class":122},"error",[72,302,220],{"class":219},[72,304,103],{"class":96},[72,306,307],{"class":100},"Error occurred",[72,309,103],{"class":96},[72,311,312],{"class":82},",",[72,314,97],{"class":96},[72,316,317],{"class":100},"stack trace",[72,319,103],{"class":96},[72,321,230],{"class":219},[72,323,106],{"class":82},[72,325,327,329,331,333,335,338,340,342,345,347,349],{"class":74,"line":326},12,[72,328,207],{"class":206},[72,330,172],{"class":82},[72,332,13],{"class":86},[72,334,172],{"class":82},[72,336,337],{"class":122},"verbose",[72,339,220],{"class":219},[72,341,103],{"class":96},[72,343,344],{"class":100},"Verbose output",[72,346,103],{"class":96},[72,348,230],{"class":219},[72,350,106],{"class":82},[72,352,354,357,359,362,364],{"class":74,"line":353},13,[72,355,356],{"class":78},"    return",[72,358,97],{"class":96},[72,360,361],{"class":100},"Hello World!",[72,363,103],{"class":96},[72,365,106],{"class":82},[72,367,369],{"class":74,"line":368},14,[72,370,371],{"class":82},"  }\n",[72,373,375],{"class":74,"line":374},15,[72,376,377],{"class":82},"}\n",[58,379,381],{"id":380},"_2-日志级别","2. 日志级别",[383,384,385,401],"table",{},[386,387,388],"thead",{},[389,390,391,395,398],"tr",{},[392,393,394],"th",{},"方法",[392,396,397],{},"级别",[392,399,400],{},"说明",[402,403,404,419,433,447,461],"tbody",{},[389,405,406,412,416],{},[407,408,409],"td",{},[27,410,411],{},"log()",[407,413,414],{},[27,415,216],{},[407,417,418],{},"一般信息",[389,420,421,426,430],{},[407,422,423],{},[27,424,425],{},"error()",[407,427,428],{},[27,429,300],{},[407,431,432],{},"错误信息，可传堆栈",[389,434,435,440,444],{},[407,436,437],{},[27,438,439],{},"warn()",[407,441,442],{},[27,443,273],{},[407,445,446],{},"警告信息",[389,448,449,454,458],{},[407,450,451],{},[27,452,453],{},"debug()",[407,455,456],{},[27,457,246],{},[407,459,460],{},"调试信息",[389,462,463,468,472],{},[407,464,465],{},[27,466,467],{},"verbose()",[407,469,470],{},[27,471,337],{},[407,473,474],{},"详细输出",[23,476,477,478,481],{},"可通过设置 ",[27,479,480],{},"LOG_LEVELS"," 环境变量或启动参数控制哪些级别输出：",[63,483,487],{"className":484,"code":485,"language":486,"meta":68,"style":68},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","# 只输出 error 和 warn\nLOG_LEVELS=error,warn node dist\u002Fmain\n","bash",[27,488,489,495],{"__ignoreMap":68},[72,490,491],{"class":74,"line":75},[72,492,494],{"class":493},"sutJx","# 只输出 error 和 warn\n",[72,496,497,499,502,505,508],{"class":74,"line":109},[72,498,480],{"class":86},[72,500,501],{"class":159},"=",[72,503,504],{"class":100},"error,warn",[72,506,507],{"class":139}," node",[72,509,510],{"class":100}," dist\u002Fmain\n",[58,512,514],{"id":513},"_3-全局替换日志器","3. 全局替换日志器",[23,516,517,518,520],{},"你可以创建自定义日志器替换内置的 ",[27,519,29],{},"。例如，将日志输出到文件：",[63,522,524],{"className":65,"code":523,"language":67,"meta":68,"style":68},"\u002F\u002F main.ts\nimport { Logger } from \"@nestjs\u002Fcommon\";\n\nclass MyLogger extends Logger {\n  error(message: any, trace?: string, context?: string) {\n    \u002F\u002F 自定义逻辑（保存到文件、发送到外部服务）\n    super.error(message, trace, context);\n  }\n}\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule, {\n    logger: new MyLogger(),\n  });\n  await app.listen(3000);\n}\n",[27,525,526,531,551,555,570,609,614,640,644,648,652,667,697,713,722,744],{"__ignoreMap":68},[72,527,528],{"class":74,"line":75},[72,529,530],{"class":493},"\u002F\u002F main.ts\n",[72,532,533,535,537,539,541,543,545,547,549],{"class":74,"line":109},[72,534,79],{"class":78},[72,536,83],{"class":82},[72,538,87],{"class":86},[72,540,90],{"class":82},[72,542,93],{"class":78},[72,544,97],{"class":96},[72,546,52],{"class":100},[72,548,103],{"class":96},[72,550,106],{"class":82},[72,552,553],{"class":74,"line":116},[72,554,113],{"emptyLinePlaceholder":112},[72,556,557,560,563,566,568],{"class":74,"line":129},[72,558,559],{"class":135},"class",[72,561,562],{"class":139}," MyLogger",[72,564,565],{"class":135}," extends",[72,567,87],{"class":139},[72,569,143],{"class":82},[72,571,572,575,577,581,583,586,588,591,594,596,598,601,603,605,607],{"class":74,"line":146},[72,573,574],{"class":166},"  error",[72,576,220],{"class":82},[72,578,580],{"class":579},"s99_P","message",[72,582,194],{"class":159},[72,584,585],{"class":197}," any",[72,587,312],{"class":82},[72,589,590],{"class":579}," trace",[72,592,593],{"class":159},"?:",[72,595,198],{"class":197},[72,597,312],{"class":82},[72,599,600],{"class":579}," context",[72,602,593],{"class":159},[72,604,198],{"class":197},[72,606,230],{"class":82},[72,608,143],{"class":82},[72,610,611],{"class":74,"line":180},[72,612,613],{"class":493},"    \u002F\u002F 自定义逻辑（保存到文件、发送到外部服务）\n",[72,615,616,620,622,624,626,628,630,632,634,636,638],{"class":74,"line":185},[72,617,619],{"class":618},"s_hVV","    super",[72,621,172],{"class":82},[72,623,300],{"class":122},[72,625,220],{"class":219},[72,627,580],{"class":86},[72,629,312],{"class":82},[72,631,590],{"class":86},[72,633,312],{"class":82},[72,635,600],{"class":86},[72,637,230],{"class":219},[72,639,106],{"class":82},[72,641,642],{"class":74,"line":203},[72,643,371],{"class":82},[72,645,646],{"class":74,"line":235},[72,647,377],{"class":82},[72,649,650],{"class":74,"line":262},[72,651,113],{"emptyLinePlaceholder":112},[72,653,654,657,660,663,665],{"class":74,"line":289},[72,655,656],{"class":135},"async",[72,658,659],{"class":135}," function",[72,661,662],{"class":122}," bootstrap",[72,664,191],{"class":82},[72,666,143],{"class":82},[72,668,669,672,675,677,680,683,685,688,690,693,695],{"class":74,"line":326},[72,670,671],{"class":135},"  const",[72,673,674],{"class":618}," app",[72,676,160],{"class":159},[72,678,679],{"class":78}," await",[72,681,682],{"class":86}," NestFactory",[72,684,172],{"class":82},[72,686,687],{"class":122},"create",[72,689,220],{"class":219},[72,691,692],{"class":86},"AppModule",[72,694,312],{"class":82},[72,696,143],{"class":82},[72,698,699,702,704,706,708,710],{"class":74,"line":353},[72,700,701],{"class":219},"    logger",[72,703,194],{"class":82},[72,705,163],{"class":159},[72,707,562],{"class":122},[72,709,191],{"class":219},[72,711,712],{"class":82},",\n",[72,714,715,718,720],{"class":74,"line":368},[72,716,717],{"class":82},"  }",[72,719,230],{"class":219},[72,721,106],{"class":82},[72,723,724,727,729,731,734,736,740,742],{"class":74,"line":374},[72,725,726],{"class":78},"  await",[72,728,674],{"class":86},[72,730,172],{"class":82},[72,732,733],{"class":122},"listen",[72,735,220],{"class":219},[72,737,739],{"class":738},"srdBf","3000",[72,741,230],{"class":219},[72,743,106],{"class":82},[72,745,747],{"class":74,"line":746},16,[72,748,377],{"class":82},[43,750,752,753,756],{"id":751},"二自定义日志器实现-loggerservice-接口","二、自定义日志器：实现 ",[27,754,755],{},"LoggerService"," 接口",[23,758,759,760,762,763,765],{},"如果你需要完全控制日志行为，可以实现 ",[27,761,755],{}," 接口（来自 ",[27,764,52],{},"）。",[63,767,769],{"className":65,"code":768,"language":67,"meta":68,"style":68},"import { LoggerService } from \"@nestjs\u002Fcommon\";\n\nexport class MyCustomLogger implements LoggerService {\n  log(message: any, ...optionalParams: any[]) {\n    \u002F* 实现 *\u002F\n  }\n  error(message: any, ...optionalParams: any[]) {\n    \u002F* 实现 *\u002F\n  }\n  warn(message: any, ...optionalParams: any[]) {\n    \u002F* 实现 *\u002F\n  }\n  debug?(message: any, ...optionalParams: any[]) {\n    \u002F* 实现 *\u002F\n  }\n  verbose?(message: any, ...optionalParams: any[]) {\n    \u002F* 实现 *\u002F\n  }\n  setLogLevels?(levels: string[]) {\n    \u002F* 可选 *\u002F\n  }\n}\n",[27,770,771,792,796,812,844,849,853,881,885,889,918,922,926,958,962,966,997,1002,1007,1030,1036,1041],{"__ignoreMap":68},[72,772,773,775,777,780,782,784,786,788,790],{"class":74,"line":75},[72,774,79],{"class":78},[72,776,83],{"class":82},[72,778,779],{"class":86}," LoggerService",[72,781,90],{"class":82},[72,783,93],{"class":78},[72,785,97],{"class":96},[72,787,52],{"class":100},[72,789,103],{"class":96},[72,791,106],{"class":82},[72,793,794],{"class":74,"line":109},[72,795,113],{"emptyLinePlaceholder":112},[72,797,798,800,802,805,808,810],{"class":74,"line":116},[72,799,132],{"class":78},[72,801,136],{"class":135},[72,803,804],{"class":139}," MyCustomLogger",[72,806,807],{"class":135}," implements",[72,809,779],{"class":139},[72,811,143],{"class":82},[72,813,814,817,819,821,823,825,827,830,833,835,837,840,842],{"class":74,"line":129},[72,815,816],{"class":166},"  log",[72,818,220],{"class":82},[72,820,580],{"class":579},[72,822,194],{"class":159},[72,824,585],{"class":197},[72,826,312],{"class":82},[72,828,829],{"class":159}," ...",[72,831,832],{"class":579},"optionalParams",[72,834,194],{"class":159},[72,836,585],{"class":197},[72,838,839],{"class":86},"[]",[72,841,230],{"class":82},[72,843,143],{"class":82},[72,845,846],{"class":74,"line":146},[72,847,848],{"class":493},"    \u002F* 实现 *\u002F\n",[72,850,851],{"class":74,"line":180},[72,852,371],{"class":82},[72,854,855,857,859,861,863,865,867,869,871,873,875,877,879],{"class":74,"line":185},[72,856,574],{"class":166},[72,858,220],{"class":82},[72,860,580],{"class":579},[72,862,194],{"class":159},[72,864,585],{"class":197},[72,866,312],{"class":82},[72,868,829],{"class":159},[72,870,832],{"class":579},[72,872,194],{"class":159},[72,874,585],{"class":197},[72,876,839],{"class":86},[72,878,230],{"class":82},[72,880,143],{"class":82},[72,882,883],{"class":74,"line":203},[72,884,848],{"class":493},[72,886,887],{"class":74,"line":235},[72,888,371],{"class":82},[72,890,891,894,896,898,900,902,904,906,908,910,912,914,916],{"class":74,"line":262},[72,892,893],{"class":166},"  warn",[72,895,220],{"class":82},[72,897,580],{"class":579},[72,899,194],{"class":159},[72,901,585],{"class":197},[72,903,312],{"class":82},[72,905,829],{"class":159},[72,907,832],{"class":579},[72,909,194],{"class":159},[72,911,585],{"class":197},[72,913,839],{"class":86},[72,915,230],{"class":82},[72,917,143],{"class":82},[72,919,920],{"class":74,"line":289},[72,921,848],{"class":493},[72,923,924],{"class":74,"line":326},[72,925,371],{"class":82},[72,927,928,931,934,936,938,940,942,944,946,948,950,952,954,956],{"class":74,"line":353},[72,929,930],{"class":166},"  debug",[72,932,933],{"class":159},"?",[72,935,220],{"class":82},[72,937,580],{"class":579},[72,939,194],{"class":159},[72,941,585],{"class":197},[72,943,312],{"class":82},[72,945,829],{"class":159},[72,947,832],{"class":579},[72,949,194],{"class":159},[72,951,585],{"class":197},[72,953,839],{"class":86},[72,955,230],{"class":82},[72,957,143],{"class":82},[72,959,960],{"class":74,"line":368},[72,961,848],{"class":493},[72,963,964],{"class":74,"line":374},[72,965,371],{"class":82},[72,967,968,971,973,975,977,979,981,983,985,987,989,991,993,995],{"class":74,"line":746},[72,969,970],{"class":166},"  verbose",[72,972,933],{"class":159},[72,974,220],{"class":82},[72,976,580],{"class":579},[72,978,194],{"class":159},[72,980,585],{"class":197},[72,982,312],{"class":82},[72,984,829],{"class":159},[72,986,832],{"class":579},[72,988,194],{"class":159},[72,990,585],{"class":197},[72,992,839],{"class":86},[72,994,230],{"class":82},[72,996,143],{"class":82},[72,998,1000],{"class":74,"line":999},17,[72,1001,848],{"class":493},[72,1003,1005],{"class":74,"line":1004},18,[72,1006,371],{"class":82},[72,1008,1010,1013,1015,1017,1020,1022,1024,1026,1028],{"class":74,"line":1009},19,[72,1011,1012],{"class":166},"  setLogLevels",[72,1014,933],{"class":159},[72,1016,220],{"class":82},[72,1018,1019],{"class":579},"levels",[72,1021,194],{"class":159},[72,1023,198],{"class":197},[72,1025,839],{"class":86},[72,1027,230],{"class":82},[72,1029,143],{"class":82},[72,1031,1033],{"class":74,"line":1032},20,[72,1034,1035],{"class":493},"    \u002F* 可选 *\u002F\n",[72,1037,1039],{"class":74,"line":1038},21,[72,1040,371],{"class":82},[72,1042,1044],{"class":74,"line":1043},22,[72,1045,377],{"class":82},[23,1047,1048],{},"然后在创建应用时传入：",[63,1050,1052],{"className":65,"code":1051,"language":67,"meta":68,"style":68},"app.useLogger(new MyCustomLogger());\n",[27,1053,1054],{"__ignoreMap":68},[72,1055,1056,1059,1061,1064,1066,1069,1071,1074],{"class":74,"line":75},[72,1057,1058],{"class":86},"app",[72,1060,172],{"class":82},[72,1062,1063],{"class":122},"useLogger",[72,1065,220],{"class":86},[72,1067,1068],{"class":159},"new",[72,1070,804],{"class":122},[72,1072,1073],{"class":86},"())",[72,1075,106],{"class":82},[43,1077,1079],{"id":1078},"三生产级日志pino-与-winston","三、生产级日志：pino 与 winston",[58,1081,1083],{"id":1082},"_1-nestjs-pino推荐用于高性能","1. nestjs-pino（推荐用于高性能）",[23,1085,1086,1088,1089,1092,1093,1095,1096,765],{},[27,1087,36],{}," 是极快的 JSON 日志库，",[27,1090,1091],{},"nestjs-pino"," 提供 NestJS 集成（注意包名是 ",[27,1094,1091],{},"，不是 ",[27,1097,1098],{},"nest-pino",[23,1100,1101],{},"安装：",[63,1103,1105],{"className":484,"code":1104,"language":486,"meta":68,"style":68},"npm install nestjs-pino pino-http\n",[27,1106,1107],{"__ignoreMap":68},[72,1108,1109,1112,1115,1118],{"class":74,"line":75},[72,1110,1111],{"class":139},"npm",[72,1113,1114],{"class":100}," install",[72,1116,1117],{"class":100}," nestjs-pino",[72,1119,1120],{"class":100}," pino-http\n",[23,1122,1123],{},"在模块中导入：",[63,1125,1127],{"className":65,"code":1126,"language":67,"meta":68,"style":68},"\u002F\u002F app.module.ts\nimport { LoggerModule } from \"nestjs-pino\";\n\n@Module({\n  imports: [\n    LoggerModule.forRoot({\n      pinoHttp: {\n        level: process.env.LOG_LEVEL || \"info\",\n        transport:\n          process.env.NODE_ENV !== \"production\"\n            ? { target: \"pino-pretty\" } \u002F\u002F 开发友好格式\n            : undefined,\n      },\n    }),\n  ],\n})\nexport class AppModule {}\n",[27,1128,1129,1134,1155,1159,1171,1181,1195,1204,1236,1244,1269,1293,1303,1308,1317,1324,1332],{"__ignoreMap":68},[72,1130,1131],{"class":74,"line":75},[72,1132,1133],{"class":493},"\u002F\u002F app.module.ts\n",[72,1135,1136,1138,1140,1143,1145,1147,1149,1151,1153],{"class":74,"line":109},[72,1137,79],{"class":78},[72,1139,83],{"class":82},[72,1141,1142],{"class":86}," LoggerModule",[72,1144,90],{"class":82},[72,1146,93],{"class":78},[72,1148,97],{"class":96},[72,1150,1091],{"class":100},[72,1152,103],{"class":96},[72,1154,106],{"class":82},[72,1156,1157],{"class":74,"line":116},[72,1158,113],{"emptyLinePlaceholder":112},[72,1160,1161,1163,1166,1168],{"class":74,"line":129},[72,1162,119],{"class":82},[72,1164,1165],{"class":122},"Module",[72,1167,220],{"class":86},[72,1169,1170],{"class":82},"{\n",[72,1172,1173,1176,1178],{"class":74,"line":146},[72,1174,1175],{"class":219},"  imports",[72,1177,194],{"class":82},[72,1179,1180],{"class":86}," [\n",[72,1182,1183,1186,1188,1191,1193],{"class":74,"line":180},[72,1184,1185],{"class":86},"    LoggerModule",[72,1187,172],{"class":82},[72,1189,1190],{"class":122},"forRoot",[72,1192,220],{"class":86},[72,1194,1170],{"class":82},[72,1196,1197,1200,1202],{"class":74,"line":185},[72,1198,1199],{"class":219},"      pinoHttp",[72,1201,194],{"class":82},[72,1203,143],{"class":82},[72,1205,1206,1209,1211,1214,1216,1219,1221,1224,1227,1229,1232,1234],{"class":74,"line":203},[72,1207,1208],{"class":219},"        level",[72,1210,194],{"class":82},[72,1212,1213],{"class":86}," process",[72,1215,172],{"class":82},[72,1217,1218],{"class":86},"env",[72,1220,172],{"class":82},[72,1222,1223],{"class":618},"LOG_LEVEL",[72,1225,1226],{"class":159}," ||",[72,1228,97],{"class":96},[72,1230,1231],{"class":100},"info",[72,1233,103],{"class":96},[72,1235,712],{"class":82},[72,1237,1238,1241],{"class":74,"line":235},[72,1239,1240],{"class":219},"        transport",[72,1242,1243],{"class":82},":\n",[72,1245,1246,1249,1251,1253,1255,1258,1261,1263,1266],{"class":74,"line":262},[72,1247,1248],{"class":86},"          process",[72,1250,172],{"class":82},[72,1252,1218],{"class":86},[72,1254,172],{"class":82},[72,1256,1257],{"class":618},"NODE_ENV",[72,1259,1260],{"class":159}," !==",[72,1262,97],{"class":96},[72,1264,1265],{"class":100},"production",[72,1267,1268],{"class":96},"\"\n",[72,1270,1271,1274,1276,1279,1281,1283,1286,1288,1290],{"class":74,"line":289},[72,1272,1273],{"class":159},"            ?",[72,1275,83],{"class":82},[72,1277,1278],{"class":219}," target",[72,1280,194],{"class":82},[72,1282,97],{"class":96},[72,1284,1285],{"class":100},"pino-pretty",[72,1287,103],{"class":96},[72,1289,90],{"class":82},[72,1291,1292],{"class":493}," \u002F\u002F 开发友好格式\n",[72,1294,1295,1298,1301],{"class":74,"line":326},[72,1296,1297],{"class":159},"            :",[72,1299,1300],{"class":206}," undefined",[72,1302,712],{"class":82},[72,1304,1305],{"class":74,"line":353},[72,1306,1307],{"class":82},"      },\n",[72,1309,1310,1313,1315],{"class":74,"line":368},[72,1311,1312],{"class":82},"    }",[72,1314,230],{"class":86},[72,1316,712],{"class":82},[72,1318,1319,1322],{"class":74,"line":374},[72,1320,1321],{"class":86},"  ]",[72,1323,712],{"class":82},[72,1325,1326,1329],{"class":74,"line":746},[72,1327,1328],{"class":82},"}",[72,1330,1331],{"class":86},")\n",[72,1333,1334,1336,1338,1341],{"class":74,"line":999},[72,1335,132],{"class":78},[72,1337,136],{"class":135},[72,1339,1340],{"class":139}," AppModule",[72,1342,1343],{"class":82}," {}\n",[23,1345,1346],{},"在服务中注入 Pino 日志器：",[63,1348,1350],{"className":65,"code":1349,"language":67,"meta":68,"style":68},"import { PinoLogger, InjectPinoLogger } from \"nestjs-pino\";\n\n@Injectable()\nexport class MyService {\n  constructor(@InjectPinoLogger(MyService.name) private logger: PinoLogger) {}\n\n  doSomething() {\n    this.logger.info({ data: 123 }, \"Info log\");\n  }\n}\n",[27,1351,1352,1378,1382,1390,1401,1433,1437,1446,1485,1489],{"__ignoreMap":68},[72,1353,1354,1356,1358,1361,1363,1366,1368,1370,1372,1374,1376],{"class":74,"line":75},[72,1355,79],{"class":78},[72,1357,83],{"class":82},[72,1359,1360],{"class":86}," PinoLogger",[72,1362,312],{"class":82},[72,1364,1365],{"class":86}," InjectPinoLogger",[72,1367,90],{"class":82},[72,1369,93],{"class":78},[72,1371,97],{"class":96},[72,1373,1091],{"class":100},[72,1375,103],{"class":96},[72,1377,106],{"class":82},[72,1379,1380],{"class":74,"line":109},[72,1381,113],{"emptyLinePlaceholder":112},[72,1383,1384,1386,1388],{"class":74,"line":116},[72,1385,119],{"class":82},[72,1387,123],{"class":122},[72,1389,126],{"class":86},[72,1391,1392,1394,1396,1399],{"class":74,"line":129},[72,1393,132],{"class":78},[72,1395,136],{"class":135},[72,1397,1398],{"class":139}," MyService",[72,1400,143],{"class":82},[72,1402,1403,1406,1409,1412,1415,1417,1420,1423,1425,1427,1429,1431],{"class":74,"line":146},[72,1404,1405],{"class":135},"  constructor",[72,1407,1408],{"class":82},"(@",[72,1410,1411],{"class":122},"InjectPinoLogger",[72,1413,1414],{"class":86},"(MyService",[72,1416,172],{"class":82},[72,1418,1419],{"class":86},"name) ",[72,1421,1422],{"class":135},"private",[72,1424,156],{"class":579},[72,1426,194],{"class":159},[72,1428,1360],{"class":139},[72,1430,230],{"class":82},[72,1432,1343],{"class":82},[72,1434,1435],{"class":74,"line":180},[72,1436,113],{"emptyLinePlaceholder":112},[72,1438,1439,1442,1444],{"class":74,"line":185},[72,1440,1441],{"class":166},"  doSomething",[72,1443,191],{"class":82},[72,1445,143],{"class":82},[72,1447,1448,1450,1452,1454,1456,1458,1460,1463,1466,1468,1471,1474,1476,1479,1481,1483],{"class":74,"line":203},[72,1449,207],{"class":206},[72,1451,172],{"class":82},[72,1453,13],{"class":86},[72,1455,172],{"class":82},[72,1457,1231],{"class":122},[72,1459,220],{"class":219},[72,1461,1462],{"class":82},"{",[72,1464,1465],{"class":219}," data",[72,1467,194],{"class":82},[72,1469,1470],{"class":738}," 123",[72,1472,1473],{"class":82}," },",[72,1475,97],{"class":96},[72,1477,1478],{"class":100},"Info log",[72,1480,103],{"class":96},[72,1482,230],{"class":219},[72,1484,106],{"class":82},[72,1486,1487],{"class":74,"line":235},[72,1488,371],{"class":82},[72,1490,1491],{"class":74,"line":262},[72,1492,377],{"class":82},[58,1494,1496],{"id":1495},"_2-nest-winston","2. nest-winston",[23,1498,1499,1501],{},[27,1500,40],{}," 功能丰富，支持多运输渠道（控制台、文件、远程服务）。",[23,1503,1101],{},[63,1505,1507],{"className":484,"code":1506,"language":486,"meta":68,"style":68},"npm install nest-winston winston\n",[27,1508,1509],{"__ignoreMap":68},[72,1510,1511,1513,1515,1518],{"class":74,"line":75},[72,1512,1111],{"class":139},[72,1514,1114],{"class":100},[72,1516,1517],{"class":100}," nest-winston",[72,1519,1520],{"class":100}," winston\n",[23,1522,1523],{},"配置：",[63,1525,1527],{"className":65,"code":1526,"language":67,"meta":68,"style":68},"import { WinstonModule } from \"nest-winston\";\nimport * as winston from \"winston\";\n\n@Module({\n  imports: [\n    WinstonModule.forRoot({\n      transports: [\n        new winston.transports.Console({\n          format: winston.format.simple(),\n        }),\n        new winston.transports.File({ filename: \"logs\u002Ferror.log\", level: \"error\" }),\n      ],\n    }),\n  ],\n})\nexport class AppModule {}\n",[27,1528,1529,1551,1575,1579,1589,1597,1610,1619,1641,1664,1673,1723,1730,1738,1744,1750],{"__ignoreMap":68},[72,1530,1531,1533,1535,1538,1540,1542,1544,1547,1549],{"class":74,"line":75},[72,1532,79],{"class":78},[72,1534,83],{"class":82},[72,1536,1537],{"class":86}," WinstonModule",[72,1539,90],{"class":82},[72,1541,93],{"class":78},[72,1543,97],{"class":96},[72,1545,1546],{"class":100},"nest-winston",[72,1548,103],{"class":96},[72,1550,106],{"class":82},[72,1552,1553,1555,1558,1561,1564,1567,1569,1571,1573],{"class":74,"line":109},[72,1554,79],{"class":78},[72,1556,1557],{"class":206}," *",[72,1559,1560],{"class":78}," as",[72,1562,1563],{"class":86}," winston ",[72,1565,1566],{"class":78},"from",[72,1568,97],{"class":96},[72,1570,40],{"class":100},[72,1572,103],{"class":96},[72,1574,106],{"class":82},[72,1576,1577],{"class":74,"line":116},[72,1578,113],{"emptyLinePlaceholder":112},[72,1580,1581,1583,1585,1587],{"class":74,"line":129},[72,1582,119],{"class":82},[72,1584,1165],{"class":122},[72,1586,220],{"class":86},[72,1588,1170],{"class":82},[72,1590,1591,1593,1595],{"class":74,"line":146},[72,1592,1175],{"class":219},[72,1594,194],{"class":82},[72,1596,1180],{"class":86},[72,1598,1599,1602,1604,1606,1608],{"class":74,"line":180},[72,1600,1601],{"class":86},"    WinstonModule",[72,1603,172],{"class":82},[72,1605,1190],{"class":122},[72,1607,220],{"class":86},[72,1609,1170],{"class":82},[72,1611,1612,1615,1617],{"class":74,"line":185},[72,1613,1614],{"class":219},"      transports",[72,1616,194],{"class":82},[72,1618,1180],{"class":86},[72,1620,1621,1624,1627,1629,1632,1634,1637,1639],{"class":74,"line":203},[72,1622,1623],{"class":159},"        new",[72,1625,1626],{"class":86}," winston",[72,1628,172],{"class":82},[72,1630,1631],{"class":86},"transports",[72,1633,172],{"class":82},[72,1635,1636],{"class":122},"Console",[72,1638,220],{"class":86},[72,1640,1170],{"class":82},[72,1642,1643,1646,1648,1650,1652,1655,1657,1660,1662],{"class":74,"line":235},[72,1644,1645],{"class":219},"          format",[72,1647,194],{"class":82},[72,1649,1626],{"class":86},[72,1651,172],{"class":82},[72,1653,1654],{"class":86},"format",[72,1656,172],{"class":82},[72,1658,1659],{"class":122},"simple",[72,1661,191],{"class":86},[72,1663,712],{"class":82},[72,1665,1666,1669,1671],{"class":74,"line":262},[72,1667,1668],{"class":82},"        }",[72,1670,230],{"class":86},[72,1672,712],{"class":82},[72,1674,1675,1677,1679,1681,1683,1685,1688,1690,1692,1695,1697,1699,1702,1704,1706,1709,1711,1713,1715,1717,1719,1721],{"class":74,"line":289},[72,1676,1623],{"class":159},[72,1678,1626],{"class":86},[72,1680,172],{"class":82},[72,1682,1631],{"class":86},[72,1684,172],{"class":82},[72,1686,1687],{"class":122},"File",[72,1689,220],{"class":86},[72,1691,1462],{"class":82},[72,1693,1694],{"class":219}," filename",[72,1696,194],{"class":82},[72,1698,97],{"class":96},[72,1700,1701],{"class":100},"logs\u002Ferror.log",[72,1703,103],{"class":96},[72,1705,312],{"class":82},[72,1707,1708],{"class":219}," level",[72,1710,194],{"class":82},[72,1712,97],{"class":96},[72,1714,300],{"class":100},[72,1716,103],{"class":96},[72,1718,90],{"class":82},[72,1720,230],{"class":86},[72,1722,712],{"class":82},[72,1724,1725,1728],{"class":74,"line":326},[72,1726,1727],{"class":86},"      ]",[72,1729,712],{"class":82},[72,1731,1732,1734,1736],{"class":74,"line":353},[72,1733,1312],{"class":82},[72,1735,230],{"class":86},[72,1737,712],{"class":82},[72,1739,1740,1742],{"class":74,"line":368},[72,1741,1321],{"class":86},[72,1743,712],{"class":82},[72,1745,1746,1748],{"class":74,"line":374},[72,1747,1328],{"class":82},[72,1749,1331],{"class":86},[72,1751,1752,1754,1756,1758],{"class":74,"line":746},[72,1753,132],{"class":78},[72,1755,136],{"class":135},[72,1757,1340],{"class":139},[72,1759,1343],{"class":82},[23,1761,1762,1763,1765,1766,1769,1770,1773],{},"在服务中注入（",[27,1764,1546],{}," 没有 ",[27,1767,1768],{},"InjectLogger"," 装饰器，需通过 ",[27,1771,1772],{},"WINSTON_MODULE_PROVIDER"," 令牌注入）：",[63,1775,1777],{"className":65,"code":1776,"language":67,"meta":68,"style":68},"import { Inject, Injectable } from \"@nestjs\u002Fcommon\";\nimport { WINSTON_MODULE_PROVIDER } from \"nest-winston\";\nimport { Logger } from \"winston\";\n\n@Injectable()\nexport class MyService {\n  constructor(@Inject(WINSTON_MODULE_PROVIDER) private logger: Logger) {}\n\n  test() {\n    this.logger.info(\"message\");\n  }\n}\n",[27,1778,1779,1805,1826,1846,1850,1858,1868,1896,1900,1909,1933,1937],{"__ignoreMap":68},[72,1780,1781,1783,1785,1788,1790,1793,1795,1797,1799,1801,1803],{"class":74,"line":75},[72,1782,79],{"class":78},[72,1784,83],{"class":82},[72,1786,1787],{"class":86}," Inject",[72,1789,312],{"class":82},[72,1791,1792],{"class":86}," Injectable",[72,1794,90],{"class":82},[72,1796,93],{"class":78},[72,1798,97],{"class":96},[72,1800,52],{"class":100},[72,1802,103],{"class":96},[72,1804,106],{"class":82},[72,1806,1807,1809,1811,1814,1816,1818,1820,1822,1824],{"class":74,"line":109},[72,1808,79],{"class":78},[72,1810,83],{"class":82},[72,1812,1813],{"class":86}," WINSTON_MODULE_PROVIDER",[72,1815,90],{"class":82},[72,1817,93],{"class":78},[72,1819,97],{"class":96},[72,1821,1546],{"class":100},[72,1823,103],{"class":96},[72,1825,106],{"class":82},[72,1827,1828,1830,1832,1834,1836,1838,1840,1842,1844],{"class":74,"line":116},[72,1829,79],{"class":78},[72,1831,83],{"class":82},[72,1833,87],{"class":86},[72,1835,90],{"class":82},[72,1837,93],{"class":78},[72,1839,97],{"class":96},[72,1841,40],{"class":100},[72,1843,103],{"class":96},[72,1845,106],{"class":82},[72,1847,1848],{"class":74,"line":129},[72,1849,113],{"emptyLinePlaceholder":112},[72,1851,1852,1854,1856],{"class":74,"line":146},[72,1853,119],{"class":82},[72,1855,123],{"class":122},[72,1857,126],{"class":86},[72,1859,1860,1862,1864,1866],{"class":74,"line":180},[72,1861,132],{"class":78},[72,1863,136],{"class":135},[72,1865,1398],{"class":139},[72,1867,143],{"class":82},[72,1869,1870,1872,1874,1877,1879,1881,1884,1886,1888,1890,1892,1894],{"class":74,"line":185},[72,1871,1405],{"class":135},[72,1873,1408],{"class":82},[72,1875,1876],{"class":122},"Inject",[72,1878,220],{"class":86},[72,1880,1772],{"class":618},[72,1882,1883],{"class":86},") ",[72,1885,1422],{"class":135},[72,1887,156],{"class":579},[72,1889,194],{"class":159},[72,1891,87],{"class":139},[72,1893,230],{"class":82},[72,1895,1343],{"class":82},[72,1897,1898],{"class":74,"line":203},[72,1899,113],{"emptyLinePlaceholder":112},[72,1901,1902,1905,1907],{"class":74,"line":235},[72,1903,1904],{"class":166},"  test",[72,1906,191],{"class":82},[72,1908,143],{"class":82},[72,1910,1911,1913,1915,1917,1919,1921,1923,1925,1927,1929,1931],{"class":74,"line":262},[72,1912,207],{"class":206},[72,1914,172],{"class":82},[72,1916,13],{"class":86},[72,1918,172],{"class":82},[72,1920,1231],{"class":122},[72,1922,220],{"class":219},[72,1924,103],{"class":96},[72,1926,580],{"class":100},[72,1928,103],{"class":96},[72,1930,230],{"class":219},[72,1932,106],{"class":82},[72,1934,1935],{"class":74,"line":289},[72,1936,371],{"class":82},[72,1938,1939],{"class":74,"line":326},[72,1940,377],{"class":82},[43,1942,1944],{"id":1943},"四请求日志中间件","四、请求日志中间件",[23,1946,1947],{},"记录每个 HTTP 请求的详细信息（方法、URL、参数、响应状态、耗时等）对问题排查很有帮助。可以用中间件实现。",[63,1949,1951],{"className":65,"code":1950,"language":67,"meta":68,"style":68},"\u002F\u002F logger.middleware.ts\nimport { Injectable, NestMiddleware, Logger } from \"@nestjs\u002Fcommon\";\nimport { Request, Response, NextFunction } from \"express\";\n\n@Injectable()\nexport class RequestLoggerMiddleware implements NestMiddleware {\n  private logger = new Logger(\"HTTP\");\n\n  use(req: Request, res: Response, next: NextFunction) {\n    const { method, originalUrl, ip, body, query } = req;\n    const userAgent = req.get(\"user-agent\") || \"\";\n    const start = Date.now();\n\n    res.on(\"finish\", () => {\n      const duration = Date.now() - start;\n      this.logger.log(\n        `${method} ${originalUrl} ${res.statusCode} ${duration}ms - ${userAgent} ${ip}`,\n      );\n      \u002F\u002F 可选：记录 body、query（注意敏感信息脱敏）\n    });\n\n    next();\n  }\n}\n",[27,1952,1953,1958,1987,2019,2023,2031,2046,2071,2075,2111,2150,2185,2206,2210,2239,2265,2281,2339,2346,2351,2359,2363,2372,2377],{"__ignoreMap":68},[72,1954,1955],{"class":74,"line":75},[72,1956,1957],{"class":493},"\u002F\u002F logger.middleware.ts\n",[72,1959,1960,1962,1964,1966,1968,1971,1973,1975,1977,1979,1981,1983,1985],{"class":74,"line":109},[72,1961,79],{"class":78},[72,1963,83],{"class":82},[72,1965,1792],{"class":86},[72,1967,312],{"class":82},[72,1969,1970],{"class":86}," NestMiddleware",[72,1972,312],{"class":82},[72,1974,87],{"class":86},[72,1976,90],{"class":82},[72,1978,93],{"class":78},[72,1980,97],{"class":96},[72,1982,52],{"class":100},[72,1984,103],{"class":96},[72,1986,106],{"class":82},[72,1988,1989,1991,1993,1996,1998,2001,2003,2006,2008,2010,2012,2015,2017],{"class":74,"line":116},[72,1990,79],{"class":78},[72,1992,83],{"class":82},[72,1994,1995],{"class":86}," Request",[72,1997,312],{"class":82},[72,1999,2000],{"class":86}," Response",[72,2002,312],{"class":82},[72,2004,2005],{"class":86}," NextFunction",[72,2007,90],{"class":82},[72,2009,93],{"class":78},[72,2011,97],{"class":96},[72,2013,2014],{"class":100},"express",[72,2016,103],{"class":96},[72,2018,106],{"class":82},[72,2020,2021],{"class":74,"line":129},[72,2022,113],{"emptyLinePlaceholder":112},[72,2024,2025,2027,2029],{"class":74,"line":146},[72,2026,119],{"class":82},[72,2028,123],{"class":122},[72,2030,126],{"class":86},[72,2032,2033,2035,2037,2040,2042,2044],{"class":74,"line":180},[72,2034,132],{"class":78},[72,2036,136],{"class":135},[72,2038,2039],{"class":139}," RequestLoggerMiddleware",[72,2041,807],{"class":135},[72,2043,1970],{"class":139},[72,2045,143],{"class":82},[72,2047,2048,2050,2052,2054,2056,2058,2060,2062,2065,2067,2069],{"class":74,"line":185},[72,2049,149],{"class":135},[72,2051,156],{"class":155},[72,2053,160],{"class":159},[72,2055,163],{"class":159},[72,2057,87],{"class":166},[72,2059,220],{"class":86},[72,2061,103],{"class":96},[72,2063,2064],{"class":100},"HTTP",[72,2066,103],{"class":96},[72,2068,230],{"class":86},[72,2070,106],{"class":82},[72,2072,2073],{"class":74,"line":203},[72,2074,113],{"emptyLinePlaceholder":112},[72,2076,2077,2080,2082,2085,2087,2089,2091,2094,2096,2098,2100,2103,2105,2107,2109],{"class":74,"line":235},[72,2078,2079],{"class":166},"  use",[72,2081,220],{"class":82},[72,2083,2084],{"class":579},"req",[72,2086,194],{"class":159},[72,2088,1995],{"class":139},[72,2090,312],{"class":82},[72,2092,2093],{"class":579}," res",[72,2095,194],{"class":159},[72,2097,2000],{"class":139},[72,2099,312],{"class":82},[72,2101,2102],{"class":579}," next",[72,2104,194],{"class":159},[72,2106,2005],{"class":139},[72,2108,230],{"class":82},[72,2110,143],{"class":82},[72,2112,2113,2116,2118,2121,2123,2126,2128,2131,2133,2136,2138,2141,2143,2145,2148],{"class":74,"line":262},[72,2114,2115],{"class":135},"    const",[72,2117,83],{"class":82},[72,2119,2120],{"class":618}," method",[72,2122,312],{"class":82},[72,2124,2125],{"class":618}," originalUrl",[72,2127,312],{"class":82},[72,2129,2130],{"class":618}," ip",[72,2132,312],{"class":82},[72,2134,2135],{"class":618}," body",[72,2137,312],{"class":82},[72,2139,2140],{"class":618}," query",[72,2142,90],{"class":82},[72,2144,160],{"class":159},[72,2146,2147],{"class":86}," req",[72,2149,106],{"class":82},[72,2151,2152,2154,2157,2159,2161,2163,2166,2168,2170,2173,2175,2177,2180,2183],{"class":74,"line":289},[72,2153,2115],{"class":135},[72,2155,2156],{"class":618}," userAgent",[72,2158,160],{"class":159},[72,2160,2147],{"class":86},[72,2162,172],{"class":82},[72,2164,2165],{"class":122},"get",[72,2167,220],{"class":219},[72,2169,103],{"class":96},[72,2171,2172],{"class":100},"user-agent",[72,2174,103],{"class":96},[72,2176,1883],{"class":219},[72,2178,2179],{"class":159},"||",[72,2181,2182],{"class":96}," \"\"",[72,2184,106],{"class":82},[72,2186,2187,2189,2192,2194,2197,2199,2202,2204],{"class":74,"line":326},[72,2188,2115],{"class":135},[72,2190,2191],{"class":618}," start",[72,2193,160],{"class":159},[72,2195,2196],{"class":86}," Date",[72,2198,172],{"class":82},[72,2200,2201],{"class":122},"now",[72,2203,191],{"class":219},[72,2205,106],{"class":82},[72,2207,2208],{"class":74,"line":353},[72,2209,113],{"emptyLinePlaceholder":112},[72,2211,2212,2215,2217,2220,2222,2224,2227,2229,2231,2234,2237],{"class":74,"line":368},[72,2213,2214],{"class":86},"    res",[72,2216,172],{"class":82},[72,2218,2219],{"class":122},"on",[72,2221,220],{"class":219},[72,2223,103],{"class":96},[72,2225,2226],{"class":100},"finish",[72,2228,103],{"class":96},[72,2230,312],{"class":82},[72,2232,2233],{"class":82}," ()",[72,2235,2236],{"class":135}," =>",[72,2238,143],{"class":82},[72,2240,2241,2244,2247,2249,2251,2253,2255,2258,2261,2263],{"class":74,"line":374},[72,2242,2243],{"class":135},"      const",[72,2245,2246],{"class":618}," duration",[72,2248,160],{"class":159},[72,2250,2196],{"class":86},[72,2252,172],{"class":82},[72,2254,2201],{"class":122},[72,2256,2257],{"class":219},"() ",[72,2259,2260],{"class":159},"-",[72,2262,2191],{"class":86},[72,2264,106],{"class":82},[72,2266,2267,2270,2272,2274,2276,2278],{"class":74,"line":746},[72,2268,2269],{"class":206},"      this",[72,2271,172],{"class":82},[72,2273,13],{"class":86},[72,2275,172],{"class":82},[72,2277,216],{"class":122},[72,2279,2280],{"class":219},"(\n",[72,2282,2283,2286,2289,2291,2294,2297,2299,2301,2304,2306,2309,2311,2313,2316,2318,2321,2324,2327,2329,2331,2334,2337],{"class":74,"line":999},[72,2284,2285],{"class":96},"        `${",[72,2287,2288],{"class":86},"method",[72,2290,1328],{"class":96},[72,2292,2293],{"class":96}," ${",[72,2295,2296],{"class":86},"originalUrl",[72,2298,1328],{"class":96},[72,2300,2293],{"class":96},[72,2302,2303],{"class":86},"res",[72,2305,172],{"class":96},[72,2307,2308],{"class":86},"statusCode",[72,2310,1328],{"class":96},[72,2312,2293],{"class":96},[72,2314,2315],{"class":86},"duration",[72,2317,1328],{"class":96},[72,2319,2320],{"class":100},"ms - ",[72,2322,2323],{"class":96},"${",[72,2325,2326],{"class":86},"userAgent",[72,2328,1328],{"class":96},[72,2330,2293],{"class":96},[72,2332,2333],{"class":86},"ip",[72,2335,2336],{"class":96},"}`",[72,2338,712],{"class":82},[72,2340,2341,2344],{"class":74,"line":1004},[72,2342,2343],{"class":219},"      )",[72,2345,106],{"class":82},[72,2347,2348],{"class":74,"line":1009},[72,2349,2350],{"class":493},"      \u002F\u002F 可选：记录 body、query（注意敏感信息脱敏）\n",[72,2352,2353,2355,2357],{"class":74,"line":1032},[72,2354,1312],{"class":82},[72,2356,230],{"class":219},[72,2358,106],{"class":82},[72,2360,2361],{"class":74,"line":1038},[72,2362,113],{"emptyLinePlaceholder":112},[72,2364,2365,2368,2370],{"class":74,"line":1043},[72,2366,2367],{"class":122},"    next",[72,2369,191],{"class":219},[72,2371,106],{"class":82},[72,2373,2375],{"class":74,"line":2374},23,[72,2376,371],{"class":82},[72,2378,2380],{"class":74,"line":2379},24,[72,2381,377],{"class":82},[23,2383,2384],{},"注册中间件（例如在 AppModule 中全局使用）：",[63,2386,2388],{"className":65,"code":2387,"language":67,"meta":68,"style":68},"export class AppModule implements NestModule {\n  configure(consumer: MiddlewareConsumer) {\n    consumer.apply(RequestLoggerMiddleware).forRoutes(\"*\");\n  }\n}\n",[27,2389,2390,2405,2424,2459,2463],{"__ignoreMap":68},[72,2391,2392,2394,2396,2398,2400,2403],{"class":74,"line":75},[72,2393,132],{"class":78},[72,2395,136],{"class":135},[72,2397,1340],{"class":139},[72,2399,807],{"class":135},[72,2401,2402],{"class":139}," NestModule",[72,2404,143],{"class":82},[72,2406,2407,2410,2412,2415,2417,2420,2422],{"class":74,"line":109},[72,2408,2409],{"class":166},"  configure",[72,2411,220],{"class":82},[72,2413,2414],{"class":579},"consumer",[72,2416,194],{"class":159},[72,2418,2419],{"class":139}," MiddlewareConsumer",[72,2421,230],{"class":82},[72,2423,143],{"class":82},[72,2425,2426,2429,2431,2434,2436,2439,2441,2443,2446,2448,2450,2453,2455,2457],{"class":74,"line":116},[72,2427,2428],{"class":86},"    consumer",[72,2430,172],{"class":82},[72,2432,2433],{"class":122},"apply",[72,2435,220],{"class":219},[72,2437,2438],{"class":86},"RequestLoggerMiddleware",[72,2440,230],{"class":219},[72,2442,172],{"class":82},[72,2444,2445],{"class":122},"forRoutes",[72,2447,220],{"class":219},[72,2449,103],{"class":96},[72,2451,2452],{"class":100},"*",[72,2454,103],{"class":96},[72,2456,230],{"class":219},[72,2458,106],{"class":82},[72,2460,2461],{"class":74,"line":129},[72,2462,371],{"class":82},[72,2464,2465],{"class":74,"line":146},[72,2466,377],{"class":82},[23,2468,2469,2470,2473,2474,2477],{},"对于更高级的请求追踪（如关联请求 ID），可以使用 ",[27,2471,2472],{},"cls-hooked"," 或 ",[27,2475,2476],{},"nestjs-cls","。",[43,2479,2481],{"id":2480},"五日志最佳实践","五、日志最佳实践",[2483,2484,2485,2500,2506,2512,2518,2524],"ol",{},[2486,2487,2488,2492,2493,2496,2497,2477],"li",{},[2489,2490,2491],"strong",{},"分级输出","：开发环境使用 ",[27,2494,2495],{},"debug\u002Fverbose","，生产环境使用 ",[27,2498,2499],{},"info\u002Fwarn\u002Ferror",[2486,2501,2502,2505],{},[2489,2503,2504],{},"结构化日志","：使用 JSON 格式（pino\u002Fwinston 默认），便于日志聚合工具分析。",[2486,2507,2508,2511],{},[2489,2509,2510],{},"敏感信息脱敏","：在记录请求体或参数时，滤除密码、Token 等。",[2486,2513,2514,2517],{},[2489,2515,2516],{},"请求 ID 关联","：为每个请求生成唯一 ID，贯穿所有日志，方便定位链路。",[2486,2519,2520,2523],{},[2489,2521,2522],{},"异步日志","：使用非阻塞日志库（pino 自带低开销），避免日志影响性能。",[2486,2525,2526,2529],{},[2489,2527,2528],{},"集中收集","：生产环境将日志输出到 stdout\u002Fstderr，由容器或进程管理器（如 PM2）转发到 ELK、Splunk 等。",[43,2531,2532],{"id":2532},"总结",[383,2534,2535,2545],{},[386,2536,2537],{},[389,2538,2539,2542],{},[392,2540,2541],{},"需求",[392,2543,2544],{},"推荐方案",[402,2546,2547,2557,2567,2577,2585],{},[389,2548,2549,2552],{},[407,2550,2551],{},"简单调试",[407,2553,25,2554,2556],{},[27,2555,29],{},"，轻量且够用",[389,2558,2559,2562],{},[407,2560,2561],{},"高性能生产",[407,2563,2564,2566],{},[27,2565,1091],{},"（JSON 日志、低开销）",[389,2568,2569,2572],{},[407,2570,2571],{},"丰富运输渠道",[407,2573,2574,2576],{},[27,2575,1546],{},"（文件、远程、多格式）",[389,2578,2579,2582],{},[407,2580,2581],{},"请求日志",[407,2583,2584],{},"自定义中间件记录入参、耗时、状态码",[389,2586,2587,2590],{},[407,2588,2589],{},"多级别控制",[407,2591,2592,2593,2595],{},"环境变量 ",[27,2594,480],{}," 或日志库的 level 配置",[23,2597,2598],{},"根据项目规模和性能要求，选择合适的日志方案，并在开发初期就引入规范的日志记录，便于后期维护和故障排查。",[2600,2601,2602],"h2",{"id":2602},"参考文献",[23,2604,2605],{},"以下链接在编写时均可正常访问：",[383,2607,2608,2617],{},[386,2609,2610],{},[389,2611,2612,2615],{},[392,2613,2614],{},"资料",[392,2616,400],{},[402,2618,2619,2633,2644],{},[389,2620,2621,2630],{},[407,2622,2623],{},[2624,2625,2629],"a",{"href":2626,"rel":2627},"https:\u002F\u002Fdocs.nestjs.com\u002F",[2628],"nofollow","NestJS 文档",[407,2631,2632],{},"官方",[389,2634,2635,2641],{},[407,2636,2637],{},[2624,2638,29],{"href":2639,"rel":2640},"https:\u002F\u002Fdocs.nestjs.com\u002Ftechniques\u002Flogger",[2628],[407,2642,2643],{},"本章主题",[389,2645,2646,2653],{},[407,2647,2648],{},[2624,2649,2652],{"href":2650,"rel":2651},"https:\u002F\u002Fdocs.nestjs.com\u002Ffaq\u002Frequest-lifecycle",[2628],"Request lifecycle",[407,2654,2655],{},"执行顺序",[2657,2658,2659],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":68,"searchDepth":109,"depth":109,"links":2661},[2662,2663,2665,2666,2667,2668,2669],{"id":45,"depth":116,"text":46},{"id":751,"depth":116,"text":2664},"二、自定义日志器：实现 LoggerService 接口",{"id":1078,"depth":116,"text":1079},{"id":1943,"depth":116,"text":1944},{"id":2480,"depth":116,"text":2481},{"id":2532,"depth":116,"text":2532},{"id":2602,"depth":109,"text":2602},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Flogger","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Flogger.md","md",{"items":2675},[2676,2680,2684,2688,2692,2696],{"path":2677,"title":2678,"description":2679,"category":10,"score":180},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","认证（Authentication）：确认「你是谁」（如 JWT、Session）。 - 授权（Authorization）：确认「你能做什么」（如 RBAC、策略检查）。",{"path":2681,"title":2682,"description":2683,"category":10,"score":180},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","@nestjs\u002Fcache-manager 统一缓存 API，存储实现可插拔。",{"path":2685,"title":2686,"description":2687,"category":10,"score":180},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","Service 是最常见的 Provider，封装业务逻辑。见 module。",{"path":2689,"title":2690,"description":2691,"category":10,"score":180},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","守卫 (Guards) 与授权","守卫决定是否放行请求，常用于认证与授权。见 auth。",{"path":2693,"title":2694,"description":2695,"category":10,"score":180},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","@nestjs\u002Fconfig 加载 .env 并提供 ConfigService。见 工程化 env。",{"path":2697,"title":2698,"description":2699,"category":10,"score":180},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","Nest 通过 @nestjs\u002Ftypeorm 等包集成 ORM；生产环境用 migration，慎用 synchronize。亦可选用 Prisma、MikroORM 等（见 官方 Database）。",{"series":2701,"title":1068,"items":2702,"index":326,"prev":2763,"next":2764},"booklet\u002Fend\u002Fnestjs\u002Fnew",[2703,2705,2709,2711,2713,2717,2721,2725,2727,2731,2735,2737,2741,2742,2746,2750,2753,2757,2759],{"path":2677,"title":2678,"date":2704,"pinned":15},"2025-12-23",{"path":2706,"title":2707,"date":2708,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","NestJS 基础","2021-03-09",{"path":2681,"title":2682,"date":2710,"pinned":15},"2025-07-04",{"path":2693,"title":2694,"date":2712,"pinned":15},"2023-08-26",{"path":2714,"title":2715,"date":2716,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":2718,"title":2719,"date":2720,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","2023-04-12",{"path":2722,"title":2723,"date":2724,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","自定义装饰器","2021-09-19",{"path":2697,"title":2698,"date":2726,"pinned":15},"2023-05-26",{"path":2728,"title":2729,"date":2730,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":2732,"title":2733,"date":2734,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":2689,"title":2690,"date":2736,"pinned":15},"2023-09-09",{"path":2738,"title":2739,"date":2740,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","2021-04-26",{"path":7,"title":8,"date":14,"pinned":15},{"path":2743,"title":2744,"date":2745,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":2747,"title":2748,"date":2749,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","模块系统与依赖注入","2022-06-15",{"path":2751,"title":2752,"date":2716,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":2754,"title":2755,"date":2756,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":2685,"title":2686,"date":2758,"pinned":15},"2024-12-02",{"path":2760,"title":2761,"date":2762,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",{"path":2738,"title":2739,"date":2740,"pinned":15},{"path":2743,"title":2744,"date":2745,"pinned":15}]