feat: add pino structured logging (stdout + optional file via env)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
39a4e21eed
commit
bbc06ae775
@ -34,6 +34,9 @@
|
||||
"bcryptjs": "^3.0.3",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.15.1",
|
||||
"nestjs-pino": "^5.3.1",
|
||||
"pino": "^10.4.0",
|
||||
"pino-roll": "^4.0.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
|
||||
145
pnpm-lock.yaml
generated
145
pnpm-lock.yaml
generated
@ -190,6 +190,15 @@ importers:
|
||||
class-validator:
|
||||
specifier: ^0.15.1
|
||||
version: 0.15.1
|
||||
nestjs-pino:
|
||||
specifier: ^5.3.1
|
||||
version: 5.3.1(@nestjs/common@12.1.2(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.1.2)(pino-http@11.0.0)(pino@10.4.0)(rxjs@7.8.2)
|
||||
pino:
|
||||
specifier: ^10.4.0
|
||||
version: 10.4.0
|
||||
pino-roll:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
reflect-metadata:
|
||||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
@ -870,6 +879,9 @@ packages:
|
||||
'@paralleldrive/cuid2@2.3.1':
|
||||
resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==}
|
||||
|
||||
'@pinojs/redact@0.4.0':
|
||||
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
|
||||
|
||||
'@prisma/client@6.19.3':
|
||||
resolution: {integrity: sha512-mKq3jQFhjvko5LTJFHGilsuQs+W+T3Gm451NzuTDGQxwCzwXHYnIu2zGkRoW+Exq3Rob7yp2MfzSrdIiZVhrBg==}
|
||||
engines: {node: '>=18.18'}
|
||||
@ -1164,6 +1176,10 @@ packages:
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
atomic-sleep@1.0.0:
|
||||
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
balanced-match@4.0.4:
|
||||
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
||||
engines: {node: 18 || 20 || >=22}
|
||||
@ -1363,6 +1379,9 @@ packages:
|
||||
resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
date-fns@4.4.0:
|
||||
resolution: {integrity: sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==}
|
||||
|
||||
debug@4.4.3:
|
||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -1561,6 +1580,10 @@ packages:
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-east-asian-width@1.7.0:
|
||||
resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==}
|
||||
engines: {node: '>=18'}
|
||||
@ -1901,6 +1924,16 @@ packages:
|
||||
resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
nestjs-pino@5.3.1:
|
||||
resolution: {integrity: sha512-tL3fFSY38Wuv3VS4dCo+zlHVt1xU7+RSXnlgenyTvfy74GLBLgisqvG+76983ilf2C2uFkPe68qUapXCYnoSoA==}
|
||||
engines: {node: '>=22.12.0'}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^11.0.8 || ^12.0.2
|
||||
'@nestjs/core': ^11.0.8 || ^12.0.2
|
||||
pino: ^10.0.0
|
||||
pino-http: ^11.0.0
|
||||
rxjs: ^7.1.0
|
||||
|
||||
node-emoji@2.1.3:
|
||||
resolution: {integrity: sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==}
|
||||
engines: {node: '>=18'}
|
||||
@ -1932,6 +1965,10 @@ packages:
|
||||
ohash@2.0.12:
|
||||
resolution: {integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==}
|
||||
|
||||
on-exit-leak-free@2.1.2:
|
||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
on-finished@2.4.1:
|
||||
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -1996,6 +2033,22 @@ packages:
|
||||
resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
pino-abstract-transport@3.0.0:
|
||||
resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
|
||||
|
||||
pino-http@11.0.0:
|
||||
resolution: {integrity: sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g==}
|
||||
|
||||
pino-roll@4.0.0:
|
||||
resolution: {integrity: sha512-axI1aQaIxXdw1F4OFFli1EDxIrdYNGLowkw/ZoZogX8oCSLHUghzwVVXUS8U+xD/Savwa5IXpiXmsSGKFX/7Sg==}
|
||||
|
||||
pino-std-serializers@7.1.0:
|
||||
resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==}
|
||||
|
||||
pino@10.4.0:
|
||||
resolution: {integrity: sha512-bk1ZMTwG/Vymx+zPoa28MhNzucFvXJWp3csrSuxuHPSMeUettaCoQ5Jvg07mtC4JGNpcfTwz41oVCnNgBK9+vA==}
|
||||
hasBin: true
|
||||
|
||||
pkg-types@2.3.3:
|
||||
resolution: {integrity: sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==}
|
||||
|
||||
@ -2022,6 +2075,9 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
process-warning@5.1.0:
|
||||
resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==}
|
||||
|
||||
proxy-addr@2.0.8:
|
||||
resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@ -2033,6 +2089,9 @@ packages:
|
||||
resolution: {integrity: sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
quick-format-unescaped@4.0.4:
|
||||
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
|
||||
|
||||
range-parser@1.3.0:
|
||||
resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -2056,6 +2115,9 @@ packages:
|
||||
resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
|
||||
engines: {node: '>= 20.19.0'}
|
||||
|
||||
real-require@1.0.0:
|
||||
resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==}
|
||||
|
||||
reflect-metadata@0.2.2:
|
||||
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
|
||||
|
||||
@ -2090,6 +2152,10 @@ packages:
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
safe-stable-stringify@2.5.0:
|
||||
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
|
||||
@ -2139,6 +2205,9 @@ packages:
|
||||
resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
sonic-boom@4.2.1:
|
||||
resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
|
||||
|
||||
source-map-js@1.2.2:
|
||||
resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -2154,6 +2223,10 @@ packages:
|
||||
resolution: {integrity: sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
split2@4.2.0:
|
||||
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||
engines: {node: '>= 10.x'}
|
||||
|
||||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
@ -2211,6 +2284,10 @@ packages:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
thread-stream@4.2.0:
|
||||
resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
through@2.3.8:
|
||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||
|
||||
@ -2867,6 +2944,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@noble/hashes': 1.8.0
|
||||
|
||||
'@pinojs/redact@0.4.0': {}
|
||||
|
||||
'@prisma/client@6.19.3(prisma@6.19.3(typescript@6.0.3))(typescript@6.0.3)':
|
||||
optionalDependencies:
|
||||
prisma: 6.19.3(typescript@6.0.3)
|
||||
@ -3142,6 +3221,8 @@ snapshots:
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
atomic-sleep@1.0.0: {}
|
||||
|
||||
balanced-match@4.0.4: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
@ -3323,6 +3404,8 @@ snapshots:
|
||||
object-assign: 4.1.1
|
||||
vary: 1.1.2
|
||||
|
||||
date-fns@4.4.0: {}
|
||||
|
||||
debug@4.4.3(supports-color@7.2.0):
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
@ -3552,6 +3635,8 @@ snapshots:
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-east-asian-width@1.7.0: {}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
@ -3849,6 +3934,14 @@ snapshots:
|
||||
dependencies:
|
||||
content-type: 2.1.0
|
||||
|
||||
nestjs-pino@5.3.1(@nestjs/common@12.1.2(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/core@12.1.2)(pino-http@11.0.0)(pino@10.4.0)(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@nestjs/common': 12.1.2(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0)
|
||||
'@nestjs/core': 12.1.2(@nestjs/common@12.1.2(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)(supports-color@7.2.0))(@nestjs/platform-express@12.1.2)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
pino: 10.4.0
|
||||
pino-http: 11.0.0
|
||||
rxjs: 7.8.2
|
||||
|
||||
node-emoji@2.1.3:
|
||||
dependencies:
|
||||
'@sindresorhus/is': 4.6.0
|
||||
@ -3879,6 +3972,8 @@ snapshots:
|
||||
|
||||
ohash@2.0.12: {}
|
||||
|
||||
on-exit-leak-free@2.1.2: {}
|
||||
|
||||
on-finished@2.4.1:
|
||||
dependencies:
|
||||
ee-first: 1.1.1
|
||||
@ -3964,6 +4059,38 @@ snapshots:
|
||||
|
||||
picomatch@4.0.7: {}
|
||||
|
||||
pino-abstract-transport@3.0.0:
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
|
||||
pino-http@11.0.0:
|
||||
dependencies:
|
||||
get-caller-file: 2.0.5
|
||||
pino: 10.4.0
|
||||
pino-std-serializers: 7.1.0
|
||||
process-warning: 5.1.0
|
||||
|
||||
pino-roll@4.0.0:
|
||||
dependencies:
|
||||
date-fns: 4.4.0
|
||||
sonic-boom: 4.2.1
|
||||
|
||||
pino-std-serializers@7.1.0: {}
|
||||
|
||||
pino@10.4.0:
|
||||
dependencies:
|
||||
'@pinojs/redact': 0.4.0
|
||||
atomic-sleep: 1.0.0
|
||||
on-exit-leak-free: 2.1.2
|
||||
pino-abstract-transport: 3.0.0
|
||||
pino-std-serializers: 7.1.0
|
||||
process-warning: 5.1.0
|
||||
quick-format-unescaped: 4.0.4
|
||||
real-require: 1.0.0
|
||||
safe-stable-stringify: 2.5.0
|
||||
sonic-boom: 4.2.1
|
||||
thread-stream: 4.2.0
|
||||
|
||||
pkg-types@2.3.3:
|
||||
dependencies:
|
||||
confbox: 0.3.1
|
||||
@ -3989,6 +4116,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
process-warning@5.1.0: {}
|
||||
|
||||
proxy-addr@2.0.8:
|
||||
dependencies:
|
||||
forwarded: 0.2.0
|
||||
@ -4001,6 +4130,8 @@ snapshots:
|
||||
es-define-property: 1.0.1
|
||||
side-channel: 1.1.1
|
||||
|
||||
quick-format-unescaped@4.0.4: {}
|
||||
|
||||
range-parser@1.3.0: {}
|
||||
|
||||
raw-body@3.0.2:
|
||||
@ -4025,6 +4156,8 @@ snapshots:
|
||||
|
||||
readdirp@5.1.1: {}
|
||||
|
||||
real-require@1.0.0: {}
|
||||
|
||||
reflect-metadata@0.2.2: {}
|
||||
|
||||
require-from-string@2.0.2: {}
|
||||
@ -4078,6 +4211,8 @@ snapshots:
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
safe-stable-stringify@2.5.0: {}
|
||||
|
||||
safer-buffer@2.1.2: {}
|
||||
|
||||
semver@7.8.5: {}
|
||||
@ -4147,6 +4282,10 @@ snapshots:
|
||||
dependencies:
|
||||
unicode-emoji-modifier-base: 1.0.0
|
||||
|
||||
sonic-boom@4.2.1:
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
|
||||
source-map-js@1.2.2: {}
|
||||
|
||||
source-map-support@0.5.21:
|
||||
@ -4158,6 +4297,8 @@ snapshots:
|
||||
|
||||
source-map@0.8.0: {}
|
||||
|
||||
split2@4.2.0: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
statuses@2.0.2: {}
|
||||
@ -4223,6 +4364,10 @@ snapshots:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
thread-stream@4.2.0:
|
||||
dependencies:
|
||||
real-require: 1.0.0
|
||||
|
||||
through@2.3.8: {}
|
||||
|
||||
tinybench@2.9.0: {}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
|
||||
import { PrismaModule } from './prisma/prisma.module.js';
|
||||
import { createLoggerModule } from './logging/logger.config.js';
|
||||
import { AuthModule } from './auth/auth.module.js';
|
||||
import { JwtAuthGuard } from './auth/jwt-auth.guard.js';
|
||||
import { PermissionsGuard } from './auth/permissions.guard.js';
|
||||
@ -21,6 +22,7 @@ import { AppService } from './app.service.js';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
createLoggerModule(),
|
||||
PrismaModule,
|
||||
AuthModule,
|
||||
TenantsModule,
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import type { Response } from 'express';
|
||||
import { InjectPinoLogger, PinoLogger } from 'nestjs-pino';
|
||||
|
||||
/**
|
||||
* 全局异常过滤器:错误码分段与 HTTP 状态对齐(400xx/401xx/403xx/404xx/409xx/500xx)。
|
||||
* 全局异常过滤器:错误码分段与 HTTP 状态对齐(400xx/401xx/403xx/404xx/409xx/500xx),并记录日志。
|
||||
*/
|
||||
@Catch()
|
||||
export class AllExceptionsFilter implements ExceptionFilter {
|
||||
constructor(@InjectPinoLogger(AllExceptionsFilter.name) private readonly logger: PinoLogger) {}
|
||||
|
||||
catch(exception: unknown, host: ArgumentsHost): void {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<Response>();
|
||||
@ -19,6 +22,12 @@ export class AllExceptionsFilter implements ExceptionFilter {
|
||||
? ((body as { message: string[] }).message.join('; '))
|
||||
: ((body as { message?: string })?.message ?? (exception as Error).message ?? 'Internal server error');
|
||||
|
||||
if (status >= 500) {
|
||||
this.logger.error({ err: exception }, message);
|
||||
} else {
|
||||
this.logger.warn(message);
|
||||
}
|
||||
|
||||
response.status(status).json({
|
||||
code: status * 100,
|
||||
message,
|
||||
|
||||
28
src/logging/logger.config.ts
Normal file
28
src/logging/logger.config.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { DynamicModule } from '@nestjs/common';
|
||||
import { LoggerModule } from 'nestjs-pino';
|
||||
|
||||
/**
|
||||
* 日志配置:pino 结构化日志。
|
||||
* - stdout 默认开启
|
||||
* - 文件输出默认关闭,由环境变量 LOG_FILE_ENABLED=true 开启
|
||||
* - 级别 LOG_LEVEL(默认 info)、路径 LOG_FILE_PATH(默认 logs/app.log)
|
||||
*/
|
||||
export function createLoggerModule(): DynamicModule {
|
||||
const level = process.env.LOG_LEVEL ?? 'info';
|
||||
const fileEnabled = process.env.LOG_FILE_ENABLED === 'true';
|
||||
const filePath = process.env.LOG_FILE_PATH ?? 'logs/app.log';
|
||||
|
||||
const pinoHttp = fileEnabled
|
||||
? {
|
||||
level,
|
||||
transport: {
|
||||
targets: [
|
||||
{ target: 'pino/file', options: { destination: 1 } }, // stdout
|
||||
{ target: 'pino-roll', options: { file: filePath, size: '10m', limit: { count: 10 } } }, // 文件按大小轮转
|
||||
],
|
||||
},
|
||||
}
|
||||
: { level };
|
||||
|
||||
return LoggerModule.forRoot({ pinoHttp });
|
||||
}
|
||||
@ -1,13 +1,15 @@
|
||||
import 'dotenv/config';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ValidationPipe } from '@nestjs/common';
|
||||
import { Logger } from 'nestjs-pino';
|
||||
import { AppModule } from './app.module.js';
|
||||
|
||||
async function bootstrap(): Promise<void> {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const app = await NestFactory.create(AppModule, { bufferLogs: true });
|
||||
app.setGlobalPrefix('api/v1');
|
||||
app.enableCors();
|
||||
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
|
||||
app.useLogger(app.get(Logger));
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
}
|
||||
await bootstrap();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user