From 376f6bcc74377817a8bad4891139eea50c5e1a83 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Sat, 16 Nov 2024 04:07:45 -0300 Subject: [PATCH 01/14] CHORE: added pinojs package --- package-lock.json | 206 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 5 +- 2 files changed, 203 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16c413cb..eea23165 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,8 @@ "lucide-react": "^0.453.0", "next": "^14.1.3", "next-auth": "^4.24.7", + "pino": "^9.5.0", + "pino-pretty": "^13.0.0", "react": "^18.3.1", "react-chartjs-2": "^5.2.0", "react-color": "^2.19.3", @@ -76,6 +78,7 @@ "@types/jsonwebtoken": "^9.0.7", "@types/node": "^22", "@types/node-fetch": "^2.6.11", + "@types/pino": "^7.0.5", "@types/react": "^18", "@types/react-color": "^3.0.12", "@types/react-dom": "^18", @@ -7206,6 +7209,16 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "dev": true }, + "node_modules/@types/pino": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/pino/-/pino-7.0.5.tgz", + "integrity": "sha512-wKoab31pknvILkxAF8ss+v9iNyhw5Iu/0jLtRkUD74cNfOOLJNnqfFKAv0r7wVaTQxRZtWrMpGfShwwBjOcgcg==", + "deprecated": "This is a stub types definition. pino provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "pino": "*" + } + }, "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", @@ -8327,6 +8340,14 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -9876,8 +9897,7 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/colorjs.io": { "version": "0.5.2", @@ -10395,6 +10415,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "engines": { + "node": "*" + } + }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -10834,6 +10862,14 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/endent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", @@ -11914,6 +11950,11 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -11970,6 +12011,19 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, "node_modules/fast-uri": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", @@ -12790,6 +12844,11 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -14918,6 +14977,14 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -15695,7 +15762,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16181,6 +16247,14 @@ "node": "^10.13.0 || >=12.0.0" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -16197,7 +16271,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -16558,6 +16631,63 @@ "node": ">=0.10.0" } }, + "node_modules/pino": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.5.0.tgz", + "integrity": "sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -17098,6 +17228,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/process-warning": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", + "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==" + }, "node_modules/promise-polyfill": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", @@ -17167,6 +17302,15 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -17247,6 +17391,11 @@ } ] }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -17621,6 +17770,14 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/recast": { "version": "0.23.6", "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz", @@ -18134,6 +18291,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -18215,6 +18380,11 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -18538,6 +18708,14 @@ "node": ">=8" } }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -18585,6 +18763,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -18945,7 +19131,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -19333,6 +19518,14 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/timers-browserify": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", @@ -20913,8 +21106,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.18.0", diff --git a/package.json b/package.json index ad1950e6..eaad2c93 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev -p 8081", + "dev": "NODE_ENV=development next dev -p 8081", "build": "next build", "start": "next start -p 8081", "lint": "next lint --fix", @@ -52,6 +52,8 @@ "lucide-react": "^0.453.0", "next": "^14.1.3", "next-auth": "^4.24.7", + "pino": "^9.5.0", + "pino-pretty": "^13.0.0", "react": "^18.3.1", "react-chartjs-2": "^5.2.0", "react-color": "^2.19.3", @@ -87,6 +89,7 @@ "@types/jsonwebtoken": "^9.0.7", "@types/node": "^22", "@types/node-fetch": "^2.6.11", + "@types/pino": "^7.0.5", "@types/react": "^18", "@types/react-color": "^3.0.12", "@types/react-dom": "^18", From cfb8def693038426ced1ba50a6e4cf6b44deca7e Mon Sep 17 00:00:00 2001 From: paulolerian Date: Sat, 16 Nov 2024 04:10:20 -0300 Subject: [PATCH 02/14] CHORE: added nextjs pino config --- next.config.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/next.config.mjs b/next.config.mjs index e925d8ae..ce49ea6c 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -45,6 +45,18 @@ const nextConfig = { process.env.NODE_ENV === 'production' ? { properties: ['^data-testid$'] } : false + }, + webpack: (config, { isServer }) => { + config.resolve.fallback = { + ...config.resolve.fallback, + worker_threads: false, + pino: false + } + + return config + }, + experimental: { + serverComponentsExternalPackages: ['pino'] } } From 1f3f1a6e51fb603b1d229599e8736c6b0680c2cc Mon Sep 17 00:00:00 2001 From: paulolerian Date: Sat, 16 Nov 2024 04:13:32 -0300 Subject: [PATCH 03/14] FEATURE: added logs inicial structure --- .../portfolios/[portfolioId]/route.ts | 9 ++- .../ledgers/[ledgerId]/portfolios/route.ts | 61 ++++++++++++++---- src/app/api/utils/api-error-handler.ts | 21 ++++--- src/core/domain/logger/logger.interface.ts | 7 +++ .../container-registry/container-registry.ts | 5 ++ src/core/types.ts | 3 + src/lib/logger/pino-logger.ts | 62 +++++++++++++++++++ src/middleware/api-logger.middleware.ts | 54 ++++++++++++++++ src/middleware/middleware.ts | 17 +++++ 9 files changed, 218 insertions(+), 21 deletions(-) create mode 100644 src/core/domain/logger/logger.interface.ts create mode 100644 src/core/types.ts create mode 100644 src/lib/logger/pino-logger.ts create mode 100644 src/middleware/api-logger.middleware.ts create mode 100644 src/middleware/middleware.ts diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index e4911b9b..c6220b7c 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -13,6 +13,7 @@ import { UpdatePortfolioUseCase } from '@/core/application/use-cases/portfolios/update-portfolio-use-case' import { NextResponse } from 'next/server' +import { PinoLogger } from '@/lib/logger/pino-logger' const updatePortfolioUseCase: UpdatePortfolio = container.get( UpdatePortfolioUseCase @@ -23,7 +24,7 @@ const deletePortfolioUseCase: DeletePortfolio = container.get( ) const getPortfolioByIdUseCase: FetchPortfolioById = container.get(FetchPortfolioByIdUseCase) - +const logger = new PinoLogger() export async function DELETE( request: Request, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } @@ -34,7 +35,11 @@ export async function DELETE( const portfolioId = params.portfolioId await deletePortfolioUseCase.execute(organizationId, ledgerId, portfolioId) - + logger.audit('Portfolio deleted', { + organizationId, + ledgerId, + portfolioId + }) return NextResponse.json({}, { status: 200 }) } catch (error: any) { console.error('Error deleting portfolio', error) diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts index 8fca2af7..081392c3 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts @@ -10,6 +10,7 @@ import { } from '@/core/application/use-cases/portfolios/fetch-all-portfolio-use-case' import { NextResponse } from 'next/server' +import { PinoLogger } from '@/lib/logger/pino-logger' const createPortfolioUseCase: CreatePortfolio = container.get( CreatePortfolioUseCase @@ -18,17 +19,27 @@ const createPortfolioUseCase: CreatePortfolio = container.get( const fetchAllPortfoliosUseCase: FetchAllPortfolios = container.get(FetchAllPortfoliosUseCase) +const logger = new PinoLogger() + export async function GET( request: Request, { params }: { params: { id: string; ledgerId: string } } ) { - try { - const { searchParams } = new URL(request.url) - const limit = Number(searchParams.get('limit')) || 100 - const page = Number(searchParams.get('page')) || 1 - const organizationId = params.id - const ledgerId = params.ledgerId + const { searchParams } = new URL(request.url) + const limit = Number(searchParams.get('limit')) || 100 + const page = Number(searchParams.get('page')) || 1 + const organizationId = params.id + const ledgerId = params.ledgerId + logger.info('Fetching portfolios', { + organizationId, + ledgerId, + page, + limit, + method: 'GET' + }) + + try { const portfolios = await fetchAllPortfoliosUseCase.execute( organizationId, ledgerId, @@ -36,9 +47,21 @@ export async function GET( limit ) + logger.info('Successfully fetched portfolios', { + organizationId, + ledgerId, + count: portfolios.items.length, + method: 'GET' + // data: portfolios + }) + return NextResponse.json(portfolios) } catch (error: any) { - console.error('Error fetching all portfolios', error) + logger.error('Failed to fetch portfolios', { + message: error.message, + name: error.name, + stack: error.stack + }) const { message, status } = await apiErrorHandler(error) return NextResponse.json({ message }, { status }) @@ -49,20 +72,36 @@ export async function POST( request: Request, { params }: { params: { id: string; ledgerId: string } } ) { + const organizationId = params.id + const ledgerId = params.ledgerId + + logger.info('Creating portfolio', { + organizationId, + ledgerId, + method: 'POST' + }) + try { const body = await request.json() - const organizationId = params.id - const ledgerId = params.ledgerId - const portfolio = await createPortfolioUseCase.execute( organizationId, ledgerId, body ) + logger.info('Successfully created portfolio', { + organizationId, + ledgerId, + portfolioId: portfolio.id + }) + return NextResponse.json(portfolio) } catch (error: any) { - console.error('Error creating portfolio', error) + logger.error('Failed to create portfolio', { + message: error.message, + name: error.name, + stack: error.stack + }) const { message, status } = await apiErrorHandler(error) return NextResponse.json({ message }, { status }) diff --git a/src/app/api/utils/api-error-handler.ts b/src/app/api/utils/api-error-handler.ts index 7cc91225..dc6ca375 100644 --- a/src/app/api/utils/api-error-handler.ts +++ b/src/app/api/utils/api-error-handler.ts @@ -1,36 +1,41 @@ import { UnauthorizedException } from '@/core/infrastructure/errors/http-exceptions' import { MidazError } from '@/core/infrastructure/errors/midaz-error' import { getIntl } from '@/lib/intl' -import { signOut } from 'next-auth/react' +import { PinoLogger } from '@/lib/logger/pino-logger' + +const logger = new PinoLogger() export interface ErrorResponse { message: string status: number } + export async function apiErrorHandler(error: any): Promise { const intl = await getIntl() let errorResponse: ErrorResponse + const errorMetadata = { + errorType: error.constructor.name, + originalMessage: error.message + } + switch (error.constructor) { case MidazError: - console.log('apiErrorHandler - MidazError', error.message) + logger.error('Business logic error occurred', error, errorMetadata) errorResponse = { message: error.message, status: 400 } break case UnauthorizedException: - console.log( - '[ERROR] - apiErrorHandler - UnauthorizedException', - error.message - ) + logger.error('Authentication error occurred', error, errorMetadata) errorResponse = { message: error.message, status: 401 } break default: - console.log('apiErrorHandler - Default') + logger.error('Unexpected error occurred', error, errorMetadata) errorResponse = { message: intl.formatMessage({ id: 'error.midaz.unknowError', defaultMessage: 'Error on Midaz.' }), - status: 400 + status: 500 } } diff --git a/src/core/domain/logger/logger.interface.ts b/src/core/domain/logger/logger.interface.ts new file mode 100644 index 00000000..00d04205 --- /dev/null +++ b/src/core/domain/logger/logger.interface.ts @@ -0,0 +1,7 @@ +export interface ILogger { + debug(message: string, metadata?: Record): void + info(message: string, metadata?: Record): void + warn(message: string, metadata?: Record): void + error(message: string, error?: Error, metadata?: Record): void + audit(message: string, metadata?: Record): void +} diff --git a/src/core/infrastructure/container-registry/container-registry.ts b/src/core/infrastructure/container-registry/container-registry.ts index 1d63c95e..0ac78f4a 100644 --- a/src/core/infrastructure/container-registry/container-registry.ts +++ b/src/core/infrastructure/container-registry/container-registry.ts @@ -10,6 +10,9 @@ import { AssetUseCaseModule } from './use-cases/asset-module' import { ProductUseCaseModule } from './use-cases/product-module' import { CasdoorModule } from '../casdoor/module/casdoor-module' import { AuthUseCaseModule } from './use-cases/auth-module' +import { ILogger } from '@/core/domain/logger/logger.interface' +import { PinoLogger } from '@/lib/logger/pino-logger' +import { TYPES } from '@/core/types' export const container = new Container() @@ -23,3 +26,5 @@ container.load(PortfolioUseCaseModule) container.load(AccountUseCaseModule) container.load(AssetUseCaseModule) container.load(ProductUseCaseModule) + +container.bind(TYPES.ILogger).to(PinoLogger).inSingletonScope() diff --git a/src/core/types.ts b/src/core/types.ts new file mode 100644 index 00000000..7dd714c8 --- /dev/null +++ b/src/core/types.ts @@ -0,0 +1,3 @@ +export const TYPES = { + ILogger: Symbol.for('ILogger') +} diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts new file mode 100644 index 00000000..19e5b8dc --- /dev/null +++ b/src/lib/logger/pino-logger.ts @@ -0,0 +1,62 @@ +import pino from 'pino' +import { ILogger } from '@/core/domain/logger/logger.interface' + +export class PinoLogger implements ILogger { + private logger: pino.Logger + + constructor() { + this.logger = pino({ + level: process.env.LOG_LEVEL || 'info', + transport: { + target: 'pino-pretty', + options: { + colorize: true, + translateTime: 'UTC:yyyy-mm-dd HH:MM:ss.l o', + ignore: 'pid,hostname' + } + }, + base: { + env: process.env.NODE_ENV, + version: process.env.APP_VERSION || '1.0.0' + } + }) + } + + private enrichMetadata(metadata?: Record): Record { + return { + timestamp: new Date().toISOString(), + ...metadata + } + } + + debug(message: string, metadata?: Record): void { + this.logger.debug(this.enrichMetadata(metadata), message) + } + + info(message: string, metadata?: Record): void { + this.logger.info(this.enrichMetadata(metadata), message) + } + + warn(message: string, metadata?: Record): void { + this.logger.warn(this.enrichMetadata(metadata), message) + } + + error(message: string, error?: Error, metadata?: Record): void { + this.logger.error( + this.enrichMetadata({ + ...metadata, + error: error + ? { message: error.message, stack: error.stack } + : undefined + }), + message + ) + } + + audit(message: string, metadata?: Record): void { + this.logger.info( + this.enrichMetadata({ ...metadata, type: 'AUDIT' }), + message + ) + } +} diff --git a/src/middleware/api-logger.middleware.ts b/src/middleware/api-logger.middleware.ts new file mode 100644 index 00000000..3d35ba34 --- /dev/null +++ b/src/middleware/api-logger.middleware.ts @@ -0,0 +1,54 @@ +import { NextResponse } from 'next/server' +import type { NextRequest } from 'next/server' +import { PinoLogger } from '@/lib/logger/pino-logger' + +const logger = new PinoLogger() + +export async function apiLoggerMiddleware( + request: NextRequest, + next: () => Promise +) { + const requestId = crypto.randomUUID() + const startTime = Date.now() + + const requestMetadata = { + requestId, + method: request.method, + url: request.url, + userAgent: request.headers.get('user-agent'), + ip: request.ip || request.headers.get('x-forwarded-for'), + referer: request.headers.get('referer') + } + + // logger.info('Incoming API request', requestMetadata) + + try { + const response = await next() + const duration = Date.now() - startTime + + // logger.info('API request completed', { + // ...requestMetadata, + // status: response.status, + // duration + // }) + + response.headers.set('X-Request-Id', requestId) + return response + } catch (error) { + const duration = Date.now() - startTime + + logger.error( + 'API request failed', + error instanceof Error ? error : new Error('Unknown error'), + { + ...requestMetadata, + duration + } + ) + + return NextResponse.json( + { error: 'Internal Server Error' }, + { status: 500 } + ) + } +} diff --git a/src/middleware/middleware.ts b/src/middleware/middleware.ts new file mode 100644 index 00000000..bcecf6ae --- /dev/null +++ b/src/middleware/middleware.ts @@ -0,0 +1,17 @@ +import { apiLoggerMiddleware } from './api-logger.middleware' +import { NextResponse } from 'next/server' +import type { NextRequest } from 'next/server' + +export async function middleware(request: NextRequest) { + if (request.nextUrl.pathname.startsWith('/api')) { + return apiLoggerMiddleware(request, () => + Promise.resolve(NextResponse.next()) + ) + } + + return NextResponse.next() +} + +export const config = { + matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] +} From d01d7a3570b4f5737a1942de39a0aa1091f5ff96 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Wed, 20 Nov 2024 17:26:00 -0300 Subject: [PATCH 04/14] feature loggers improvement --- .../portfolios/[portfolioId]/route.ts | 22 +++++-- src/lib/logger/pino-logger.ts | 65 ++++++++++--------- src/lib/logger/types.ts | 20 ++++++ 3 files changed, 73 insertions(+), 34 deletions(-) create mode 100644 src/lib/logger/types.ts diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index c6220b7c..36ed6d3e 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -35,11 +35,23 @@ export async function DELETE( const portfolioId = params.portfolioId await deletePortfolioUseCase.execute(organizationId, ledgerId, portfolioId) - logger.audit('Portfolio deleted', { - organizationId, - ledgerId, - portfolioId - }) + + logger.audit( + 'Portfolio deleted', + { + organizationId, + ledgerId + }, + { + layer: 'api', + operation: 'delete_portfolio', + params: { + ledgerId, + portfolioId + } + } + ) + return NextResponse.json({}, { status: 200 }) } catch (error: any) { console.error('Error deleting portfolio', error) diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts index 19e5b8dc..a864c424 100644 --- a/src/lib/logger/pino-logger.ts +++ b/src/lib/logger/pino-logger.ts @@ -1,18 +1,22 @@ import pino from 'pino' -import { ILogger } from '@/core/domain/logger/logger.interface' +import { LogContext, LogEntry, LogMetadata } from './types' +import { randomUUID } from 'crypto' -export class PinoLogger implements ILogger { +export class PinoLogger { private logger: pino.Logger constructor() { this.logger = pino({ - level: process.env.LOG_LEVEL || 'info', + formatters: { + level: (label) => ({ level: label.toUpperCase() }) + }, + timestamp: () => `,"timestamp":${Date.now()}`, transport: { target: 'pino-pretty', options: { colorize: true, - translateTime: 'UTC:yyyy-mm-dd HH:MM:ss.l o', - ignore: 'pid,hostname' + ignore: 'pid,hostname', + translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l' } }, base: { @@ -22,41 +26,44 @@ export class PinoLogger implements ILogger { }) } - private enrichMetadata(metadata?: Record): Record { + private createLogEntry( + level: LogEntry['level'], + message: string, + metadata: LogMetadata, + context: LogContext + ): LogEntry { return { - timestamp: new Date().toISOString(), - ...metadata + level, + message, + timestamp: Date.now(), + traceId: randomUUID(), + metadata, + context } } - debug(message: string, metadata?: Record): void { - this.logger.debug(this.enrichMetadata(metadata), message) + info(message: string, metadata: LogMetadata, context: LogContext) { + const logEntry = this.createLogEntry('INFO', message, metadata, context) + this.logger.info(logEntry) } - info(message: string, metadata?: Record): void { - this.logger.info(this.enrichMetadata(metadata), message) + error(message: string, metadata: LogMetadata, context: LogContext) { + const logEntry = this.createLogEntry('ERROR', message, metadata, context) + this.logger.error(logEntry) } - warn(message: string, metadata?: Record): void { - this.logger.warn(this.enrichMetadata(metadata), message) + warn(message: string, metadata: LogMetadata, context: LogContext) { + const logEntry = this.createLogEntry('WARN', message, metadata, context) + this.logger.warn(logEntry) } - error(message: string, error?: Error, metadata?: Record): void { - this.logger.error( - this.enrichMetadata({ - ...metadata, - error: error - ? { message: error.message, stack: error.stack } - : undefined - }), - message - ) + debug(message: string, metadata: LogMetadata, context: LogContext) { + const logEntry = this.createLogEntry('DEBUG', message, metadata, context) + this.logger.debug(logEntry) } - audit(message: string, metadata?: Record): void { - this.logger.info( - this.enrichMetadata({ ...metadata, type: 'AUDIT' }), - message - ) + audit(message: string, metadata: LogMetadata, context: LogContext) { + const logEntry = this.createLogEntry('AUDIT', message, metadata, context) + this.logger.info(logEntry) } } diff --git a/src/lib/logger/types.ts b/src/lib/logger/types.ts new file mode 100644 index 00000000..1413cb8c --- /dev/null +++ b/src/lib/logger/types.ts @@ -0,0 +1,20 @@ +export interface LogMetadata { + userId?: string + organizationId?: string + [key: string]: any +} + +export interface LogContext { + layer: 'api' | 'application' | 'infrastructure' | 'domain' + operation: string + params?: Record +} + +export interface LogEntry { + level: 'INFO' | 'ERROR' | 'WARN' | 'DEBUG' | 'AUDIT' + message: string + timestamp: number + traceId: string + metadata: LogMetadata + context: LogContext +} From c16ea0585be903e5809f7a2e66e0e66119827686 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Wed, 20 Nov 2024 19:19:14 -0300 Subject: [PATCH 05/14] feature loggers improvement --- .../ledgers/[ledgerId]/portfolios/route.ts | 126 +++++++++++++----- src/lib/logger/types.ts | 1 + src/middleware/api-logger.middleware.ts | 25 +++- 3 files changed, 115 insertions(+), 37 deletions(-) diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts index 081392c3..24bf4110 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts @@ -31,13 +31,26 @@ export async function GET( const organizationId = params.id const ledgerId = params.ledgerId - logger.info('Fetching portfolios', { - organizationId, - ledgerId, - page, - limit, - method: 'GET' - }) + const context = { + component: 'PortfoliosAPI', + action: 'fetchPortfolios', + layer: 'api' as const, + operation: 'GET' + } + + logger.info( + 'Fetching portfolios', + { + organizationId, + ledgerId, + page, + limit, + method: 'GET' + }, + { + ...context + } + ) try { const portfolios = await fetchAllPortfoliosUseCase.execute( @@ -47,23 +60,35 @@ export async function GET( limit ) - logger.info('Successfully fetched portfolios', { - organizationId, - ledgerId, - count: portfolios.items.length, - method: 'GET' - // data: portfolios - }) + logger.info( + 'Successfully fetched portfolios', + { + organizationId, + ledgerId, + count: portfolios.items.length, + method: 'GET' + }, + context + ) return NextResponse.json(portfolios) } catch (error: any) { - logger.error('Failed to fetch portfolios', { - message: error.message, - name: error.name, - stack: error.stack - }) + logger.error( + 'Failed to fetch portfolios', + { + organizationId, + ledgerId, + error: { + message: error.message, + name: error.name, + stack: error.stack + } + }, + { + ...context + } + ) const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) } } @@ -75,11 +100,24 @@ export async function POST( const organizationId = params.id const ledgerId = params.ledgerId - logger.info('Creating portfolio', { - organizationId, - ledgerId, - method: 'POST' - }) + const context = { + component: 'PortfoliosAPI', + action: 'createPortfolio', + layer: 'api' as const, + operation: 'POST' + } + + logger.info( + 'Creating portfolio', + { + organizationId, + ledgerId, + method: 'POST' + }, + { + ...context + } + ) try { const body = await request.json() @@ -89,21 +127,37 @@ export async function POST( body ) - logger.info('Successfully created portfolio', { - organizationId, - ledgerId, - portfolioId: portfolio.id - }) + logger.info( + 'Successfully created portfolio', + { + organizationId, + ledgerId, + portfolioId: portfolio.id, + method: 'POST' + }, + { + ...context + } + ) return NextResponse.json(portfolio) } catch (error: any) { - logger.error('Failed to create portfolio', { - message: error.message, - name: error.name, - stack: error.stack - }) + logger.error( + 'Failed to create portfolio', + { + organizationId, + ledgerId, + error: { + message: error.message, + name: error.name, + stack: error.stack + } + }, + { + ...context + } + ) const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) } } diff --git a/src/lib/logger/types.ts b/src/lib/logger/types.ts index 1413cb8c..f56ef8ee 100644 --- a/src/lib/logger/types.ts +++ b/src/lib/logger/types.ts @@ -8,6 +8,7 @@ export interface LogContext { layer: 'api' | 'application' | 'infrastructure' | 'domain' operation: string params?: Record + component?: string } export interface LogEntry { diff --git a/src/middleware/api-logger.middleware.ts b/src/middleware/api-logger.middleware.ts index 3d35ba34..31ee4fa1 100644 --- a/src/middleware/api-logger.middleware.ts +++ b/src/middleware/api-logger.middleware.ts @@ -32,6 +32,18 @@ export async function apiLoggerMiddleware( // duration // }) + logger.info( + 'API request completed', + { + duration, + status: response.status + }, + { + layer: 'api', + operation: 'request_end' + } + ) + response.headers.set('X-Request-Id', requestId) return response } catch (error) { @@ -39,10 +51,21 @@ export async function apiLoggerMiddleware( logger.error( 'API request failed', - error instanceof Error ? error : new Error('Unknown error'), { + error: + error instanceof Error + ? { + message: error.message, + name: error.name, + stack: error.stack + } + : error, ...requestMetadata, duration + }, + { + layer: 'api', + operation: 'request_error' } ) From fffa55176fade005f43514b8aa83f9ecb42f3fab Mon Sep 17 00:00:00 2001 From: paulolerian Date: Fri, 29 Nov 2024 01:42:13 -0300 Subject: [PATCH 06/14] feature loggers improvement --- .../portfolios/[portfolioId]/route.ts | 61 +++---- .../ledgers/[ledgerId]/portfolios/route.ts | 87 +++------ .../application/decorators/log-operation.ts | 49 +++++ .../application/mappers/portfolio-mapper.ts | 8 + .../portfolios/create-portfolio-use-case.ts | 7 +- .../portfolios/delete-portfolio-use-case.ts | 6 +- src/lib/logger/pino-logger.ts | 56 ++++-- src/lib/logger/request-context.ts | 171 ++++++++++++++++++ src/lib/logger/types.ts | 2 +- src/middleware/api-logger.middleware.ts | 58 ++---- 10 files changed, 350 insertions(+), 155 deletions(-) create mode 100644 src/core/application/decorators/log-operation.ts create mode 100644 src/lib/logger/request-context.ts diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index 36ed6d3e..f186e9f6 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -12,8 +12,9 @@ import { UpdatePortfolio, UpdatePortfolioUseCase } from '@/core/application/use-cases/portfolios/update-portfolio-use-case' -import { NextResponse } from 'next/server' +import { NextRequest, NextResponse } from 'next/server' import { PinoLogger } from '@/lib/logger/pino-logger' +import { RequestContextManager } from '@/lib/logger/request-context' const updatePortfolioUseCase: UpdatePortfolio = container.get( UpdatePortfolioUseCase @@ -24,45 +25,43 @@ const deletePortfolioUseCase: DeletePortfolio = container.get( ) const getPortfolioByIdUseCase: FetchPortfolioById = container.get(FetchPortfolioByIdUseCase) -const logger = new PinoLogger() + +const logger = PinoLogger.getInstance() + export async function DELETE( - request: Request, + request: NextRequest, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { - try { - const organizationId = params.id - const ledgerId = params.ledgerId - const portfolioId = params.portfolioId - - await deletePortfolioUseCase.execute(organizationId, ledgerId, portfolioId) - - logger.audit( - 'Portfolio deleted', - { - organizationId, - ledgerId - }, - { - layer: 'api', - operation: 'delete_portfolio', - params: { + const { id: organizationId, ledgerId, portfolioId } = params + return RequestContextManager.runWithContext( + request.url, + request.method, + { + organizationId, + ledgerId, + portfolioId, + deletedAt: new Date().toISOString() + }, + async () => { + try { + await deletePortfolioUseCase.execute( + organizationId, ledgerId, portfolioId - } - } - ) - - return NextResponse.json({}, { status: 200 }) - } catch (error: any) { - console.error('Error deleting portfolio', error) - const { message, status } = await apiErrorHandler(error) + ) + return NextResponse.json({}, { status: 200 }) + } catch (error: any) { + console.error('Error deleting portfolio', error) + const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) - } + return NextResponse.json({ message }, { status }) + } + } + ) } export async function PATCH( - request: Request, + request: NextRequest, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { try { diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts index 24bf4110..5450d312 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts @@ -9,8 +9,9 @@ import { FetchAllPortfoliosUseCase } from '@/core/application/use-cases/portfolios/fetch-all-portfolio-use-case' -import { NextResponse } from 'next/server' +import { NextRequest, NextResponse } from 'next/server' import { PinoLogger } from '@/lib/logger/pino-logger' +import { RequestContextManager } from '@/lib/logger/request-context' const createPortfolioUseCase: CreatePortfolio = container.get( CreatePortfolioUseCase @@ -19,7 +20,7 @@ const createPortfolioUseCase: CreatePortfolio = container.get( const fetchAllPortfoliosUseCase: FetchAllPortfolios = container.get(FetchAllPortfoliosUseCase) -const logger = new PinoLogger() +const logger = PinoLogger.getInstance() export async function GET( request: Request, @@ -94,70 +95,28 @@ export async function GET( } export async function POST( - request: Request, + request: NextRequest, { params }: { params: { id: string; ledgerId: string } } ) { - const organizationId = params.id - const ledgerId = params.ledgerId - - const context = { - component: 'PortfoliosAPI', - action: 'createPortfolio', - layer: 'api' as const, - operation: 'POST' - } - - logger.info( - 'Creating portfolio', - { - organizationId, - ledgerId, - method: 'POST' - }, - { - ...context + const { id: organizationId, ledgerId } = params + + return RequestContextManager.runWithContext( + request.url, + request.method, + { organizationId, ledgerId }, + async () => { + try { + const body = await request.json() + const portfolio = await createPortfolioUseCase.execute( + organizationId, + ledgerId, + body + ) + return NextResponse.json(portfolio) + } catch (error) { + const { message, status } = await apiErrorHandler(error) + return NextResponse.json({ message }, { status }) + } } ) - - try { - const body = await request.json() - const portfolio = await createPortfolioUseCase.execute( - organizationId, - ledgerId, - body - ) - - logger.info( - 'Successfully created portfolio', - { - organizationId, - ledgerId, - portfolioId: portfolio.id, - method: 'POST' - }, - { - ...context - } - ) - - return NextResponse.json(portfolio) - } catch (error: any) { - logger.error( - 'Failed to create portfolio', - { - organizationId, - ledgerId, - error: { - message: error.message, - name: error.name, - stack: error.stack - } - }, - { - ...context - } - ) - const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) - } } diff --git a/src/core/application/decorators/log-operation.ts b/src/core/application/decorators/log-operation.ts new file mode 100644 index 00000000..500fd49c --- /dev/null +++ b/src/core/application/decorators/log-operation.ts @@ -0,0 +1,49 @@ +import { RequestContextManager } from '@/lib/logger/request-context' + +export function LogOperation(options: { + layer: 'application' | 'infrastructure' | 'domain' + operation: string +}) { + return function ( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor + ) { + const originalMethod = descriptor.value + + descriptor.value = async function (...args: any[]) { + try { + RequestContextManager.addEvent({ + layer: options.layer, + operation: `${options.operation}_start`, + level: 'info', + message: `Starting ${options.operation}`, + metadata: { args } + }) + + const result = await originalMethod.apply(this, args) + + RequestContextManager.addEvent({ + layer: options.layer, + operation: `${options.operation}_success`, + level: 'info', + message: `${options.operation} completed successfully`, + metadata: { result } + }) + + return result + } catch (error) { + RequestContextManager.addEvent({ + layer: options.layer, + operation: `${options.operation}_error`, + level: 'error', + message: `${options.operation} failed`, + error: error as Error + }) + throw error + } + } + + return descriptor + } +} diff --git a/src/core/application/mappers/portfolio-mapper.ts b/src/core/application/mappers/portfolio-mapper.ts index e6b8f98e..051f3bd7 100644 --- a/src/core/application/mappers/portfolio-mapper.ts +++ b/src/core/application/mappers/portfolio-mapper.ts @@ -4,6 +4,7 @@ import { PortfolioResponseDto, UpdatePortfolioDto } from '../dto/portfolios-dto' +import { RequestContextManager } from '@/lib/logger/request-context' export function portfolioEntityToDto( portfolio: PortfolioEntity @@ -26,6 +27,13 @@ export function portfolioEntityToDto( } export function portfolioDtoToEntity(dto: CreatePortfolioDto): PortfolioEntity { + RequestContextManager.addEvent({ + layer: 'application', + operation: 'portfolio_dto_to_entity', + level: 'debug', + message: 'Mapping portfolio dto to entity', + metadata: { dto } + }) return { entityId: dto.entityId, name: dto.name, diff --git a/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts index 531065b0..aad9c94c 100644 --- a/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts @@ -3,12 +3,13 @@ import { portfolioDtoToEntity, portfolioEntityToDto } from '../../mappers/portfolio-mapper' -import { +import type { CreatePortfolioDto, PortfolioResponseDto } from '../../dto/portfolios-dto' import { PortfolioEntity } from '@/core/domain/entities/portfolios-entity' import { inject, injectable } from 'inversify' +import { LogOperation } from '../../decorators/log-operation' export interface CreatePortfolio { execute: ( @@ -25,6 +26,10 @@ export class CreatePortfolioUseCase implements CreatePortfolio { private readonly createPortfolioRepository: CreatePortfolioRepository ) {} + @LogOperation({ + layer: 'application', + operation: 'create_portfolio' + }) async execute( organizationId: string, ledgerId: string, diff --git a/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts index 7c339b50..12469d32 100644 --- a/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts @@ -1,5 +1,6 @@ import { DeletePortfolioRepository } from '@/core/domain/repositories/portfolios/delete-portfolio-repository' import { inject, injectable } from 'inversify' +import { LogOperation } from '../../decorators/log-operation' export interface DeletePortfolio { execute: ( @@ -15,7 +16,10 @@ export class DeletePortfolioUseCase implements DeletePortfolio { @inject(DeletePortfolioRepository) private readonly deletePortfolioRepository: DeletePortfolioRepository ) {} - + @LogOperation({ + layer: 'application', + operation: 'delete_portfolio' + }) async execute( organizationId: string, ledgerId: string, diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts index a864c424..77f70edc 100644 --- a/src/lib/logger/pino-logger.ts +++ b/src/lib/logger/pino-logger.ts @@ -1,29 +1,47 @@ -import pino from 'pino' -import { LogContext, LogEntry, LogMetadata } from './types' +// PinoLogger.ts + +import pino, { Logger, LoggerOptions } from 'pino' import { randomUUID } from 'crypto' +import { LogContext, LogEntry, LogMetadata } from './types' export class PinoLogger { - private logger: pino.Logger + private static instance: PinoLogger + private logger: Logger - constructor() { - this.logger = pino({ + private constructor() { + const isDebugEnabled = process.env.ENABLE_DEBUG === 'true' + + const loggerOptions: LoggerOptions = { + level: isDebugEnabled ? 'debug' : 'info', formatters: { level: (label) => ({ level: label.toUpperCase() }) }, - timestamp: () => `,"timestamp":${Date.now()}`, - transport: { + timestamp: pino.stdTimeFunctions.isoTime, + base: { + env: process.env.NODE_ENV || 'production', + version: process.env.APP_VERSION || '1.0.0' + } + } + + if (process.env.NODE_ENV === 'development') { + loggerOptions.transport = { target: 'pino-pretty', options: { colorize: true, ignore: 'pid,hostname', translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l' } - }, - base: { - env: process.env.NODE_ENV, - version: process.env.APP_VERSION || '1.0.0' } - }) + } + + this.logger = pino(loggerOptions) + } + + static getInstance(): PinoLogger { + if (!PinoLogger.instance) { + PinoLogger.instance = new PinoLogger() + } + return PinoLogger.instance } private createLogEntry( @@ -35,34 +53,34 @@ export class PinoLogger { return { level, message, - timestamp: Date.now(), - traceId: randomUUID(), + timestamp: new Date().toISOString(), + traceId: metadata.traceId || randomUUID(), metadata, context } } - info(message: string, metadata: LogMetadata, context: LogContext) { + info(message: string, metadata: LogMetadata = {}, context: LogContext) { const logEntry = this.createLogEntry('INFO', message, metadata, context) this.logger.info(logEntry) } - error(message: string, metadata: LogMetadata, context: LogContext) { + error(message: string, metadata: LogMetadata = {}, context: LogContext) { const logEntry = this.createLogEntry('ERROR', message, metadata, context) this.logger.error(logEntry) } - warn(message: string, metadata: LogMetadata, context: LogContext) { + warn(message: string, metadata: LogMetadata = {}, context: LogContext) { const logEntry = this.createLogEntry('WARN', message, metadata, context) this.logger.warn(logEntry) } - debug(message: string, metadata: LogMetadata, context: LogContext) { + debug(message: string, metadata: LogMetadata = {}, context: LogContext) { const logEntry = this.createLogEntry('DEBUG', message, metadata, context) this.logger.debug(logEntry) } - audit(message: string, metadata: LogMetadata, context: LogContext) { + audit(message: string, metadata: LogMetadata = {}, context: LogContext) { const logEntry = this.createLogEntry('AUDIT', message, metadata, context) this.logger.info(logEntry) } diff --git a/src/lib/logger/request-context.ts b/src/lib/logger/request-context.ts new file mode 100644 index 00000000..5fd3431f --- /dev/null +++ b/src/lib/logger/request-context.ts @@ -0,0 +1,171 @@ +import { AsyncLocalStorage } from 'async_hooks' +import * as crypto from 'crypto' +import { PinoLogger } from './pino-logger' + +type Layer = 'api' | 'application' | 'infrastructure' | 'domain' +type Level = 'info' | 'error' | 'warn' | 'debug' | 'audit' + +interface Event { + timestamp: number + layer: Layer + operation: string + level: Level + message: string + metadata?: Record + error?: Error +} + +interface RequestContext { + requestId: string + startTime: number + path: string + method: string + metadata: Record + events: Event[] +} + +export class RequestContextManager { + private static storage = new AsyncLocalStorage() + private static logger = PinoLogger.getInstance() + + private static shouldLogDebug(): boolean { + return process.env.ENABLE_DEBUG === 'true' + } + + static async runWithContext( + path: string, + method: string, + initialMetadata: Record, + fn: () => Promise + ): Promise { + const context: RequestContext = { + requestId: crypto.randomUUID(), + startTime: Date.now(), + path, + method, + metadata: initialMetadata, + events: [] + } + + return this.storage.run(context, async () => { + try { + const result = await fn() + this.finalizeContext() + return result + } catch (error) { + this.addEvent({ + layer: 'api', + operation: 'request_error', + level: 'error', + message: 'Request failed', + error: error instanceof Error ? error : new Error(String(error)) + }) + this.finalizeContext() + throw error + } + }) + } + + private static finalizeContext() { + const context = this.getContext() + if (context) { + const duration = Date.now() - context.startTime + console.log( + 'ENABLE_REQUEST_TIMELINE', + process.env.ENABLE_REQUEST_TIMELINE + ) + if (process.env.ENABLE_REQUEST_TIMELINE === 'true') { + this.logger.info( + 'Request Timeline', + { + requestId: context.requestId, + path: context.path, + method: context.method, + duration, + metadata: context.metadata, + events: context.events.map((event) => ({ + ...event, + timestamp: new Date(event.timestamp).toISOString() + })) + }, + { + layer: 'api', + operation: 'request_timeline' + } + ) + } + } + } + + static getContext(): RequestContext | undefined { + return this.storage.getStore() + } + + static addEvent(event: Omit) { + const context = this.getContext() + if (context) { + if (event.level === 'debug' && !this.shouldLogDebug()) { + return + } + + const fullEvent: Event = { + timestamp: Date.now(), + ...event + } + + switch (event.level) { + case 'debug': + this.logger.debug( + event.message, + { eventData: fullEvent, requestId: context.requestId }, + { layer: event.layer, operation: event.operation } + ) + break + case 'info': + this.logger.info( + event.message, + { eventData: fullEvent, requestId: context.requestId }, + { layer: event.layer, operation: event.operation } + ) + break + case 'error': + this.logger.error( + event.message, + { + eventData: fullEvent, + requestId: context.requestId, + error: event.error + }, + { layer: event.layer, operation: event.operation } + ) + break + case 'warn': + this.logger.warn( + event.message, + { eventData: fullEvent, requestId: context.requestId }, + { layer: event.layer, operation: event.operation } + ) + break + case 'audit': + this.logger.audit( + event.message, + { eventData: fullEvent, requestId: context.requestId }, + { layer: event.layer, operation: event.operation } + ) + break + } + + context.events.push(fullEvent) + } + } + + static updateMetadata(metadata: Partial) { + const context = this.getContext() + if (context) { + context.metadata = { + ...context.metadata, + ...metadata + } + } + } +} diff --git a/src/lib/logger/types.ts b/src/lib/logger/types.ts index f56ef8ee..d67fb42b 100644 --- a/src/lib/logger/types.ts +++ b/src/lib/logger/types.ts @@ -14,7 +14,7 @@ export interface LogContext { export interface LogEntry { level: 'INFO' | 'ERROR' | 'WARN' | 'DEBUG' | 'AUDIT' message: string - timestamp: number + timestamp: string traceId: string metadata: LogMetadata context: LogContext diff --git a/src/middleware/api-logger.middleware.ts b/src/middleware/api-logger.middleware.ts index 31ee4fa1..c573df1b 100644 --- a/src/middleware/api-logger.middleware.ts +++ b/src/middleware/api-logger.middleware.ts @@ -1,8 +1,6 @@ +import { RequestContextManager } from '@/lib/logger/request-context' import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' -import { PinoLogger } from '@/lib/logger/pino-logger' - -const logger = new PinoLogger() export async function apiLoggerMiddleware( request: NextRequest, @@ -20,54 +18,38 @@ export async function apiLoggerMiddleware( referer: request.headers.get('referer') } - // logger.info('Incoming API request', requestMetadata) - try { const response = await next() const duration = Date.now() - startTime - // logger.info('API request completed', { - // ...requestMetadata, - // status: response.status, - // duration - // }) - - logger.info( - 'API request completed', - { + RequestContextManager.addEvent({ + level: 'info', + message: 'API request completed', + layer: 'api', + operation: 'request_end', + metadata: { duration, - status: response.status - }, - { - layer: 'api', - operation: 'request_end' + status: response.status, + ...requestMetadata } - ) + }) response.headers.set('X-Request-Id', requestId) return response } catch (error) { const duration = Date.now() - startTime - logger.error( - 'API request failed', - { - error: - error instanceof Error - ? { - message: error.message, - name: error.name, - stack: error.stack - } - : error, - ...requestMetadata, - duration - }, - { - layer: 'api', - operation: 'request_error' + RequestContextManager.addEvent({ + layer: 'api', + operation: 'request_error', + level: 'error', + message: 'Request failed', + error: error as Error, + metadata: { + duration, + ...requestMetadata } - ) + }) return NextResponse.json( { error: 'Internal Server Error' }, From 5b27d4006eb40dc1c438843eeff93d681bd9182f Mon Sep 17 00:00:00 2001 From: paulolerian Date: Wed, 4 Dec 2024 19:55:53 -0300 Subject: [PATCH 07/14] middleware and midaz-id implementation --- next.config.mjs | 2 +- .../portfolios/[portfolioId]/route.ts | 6 +- .../ledgers/[ledgerId]/portfolios/route.ts | 6 +- src/lib/logger/pino-logger.ts | 80 ++++++++++++++++--- src/lib/logger/request-context.ts | 1 + src/lib/logger/types.ts | 2 +- src/{middleware => }/middleware.ts | 8 +- src/middleware/api-logger.middleware.ts | 4 +- 8 files changed, 87 insertions(+), 22 deletions(-) rename src/{middleware => }/middleware.ts (67%) diff --git a/next.config.mjs b/next.config.mjs index 2d9a3381..1e08402a 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -56,7 +56,7 @@ const nextConfig = { return config }, experimental: { - serverComponentsExternalPackages: ['pino'] + serverComponentsExternalPackages: ['pino', 'pino-pretty'] } } diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index f186e9f6..56c2756b 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -33,6 +33,7 @@ export async function DELETE( { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { const { id: organizationId, ledgerId, portfolioId } = params + const midazId = request.headers.get('X-Midaz-Id') return RequestContextManager.runWithContext( request.url, request.method, @@ -40,9 +41,12 @@ export async function DELETE( organizationId, ledgerId, portfolioId, - deletedAt: new Date().toISOString() + deletedAt: new Date().toISOString(), + midazId }, async () => { + console.log('midazId delete', midazId) + try { await deletePortfolioUseCase.execute( organizationId, diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts index 5450d312..9c73b03d 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts @@ -99,13 +99,15 @@ export async function POST( { params }: { params: { id: string; ledgerId: string } } ) { const { id: organizationId, ledgerId } = params - + const midazId = request.headers.get('X-Midaz-Id') return RequestContextManager.runWithContext( request.url, request.method, - { organizationId, ledgerId }, + { organizationId, ledgerId, midazId }, async () => { try { + console.log('midazId post', midazId) + console.log('request readers', request.headers) const body = await request.json() const portfolio = await createPortfolioUseCase.execute( organizationId, diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts index 77f70edc..bad6e648 100644 --- a/src/lib/logger/pino-logger.ts +++ b/src/lib/logger/pino-logger.ts @@ -3,6 +3,7 @@ import pino, { Logger, LoggerOptions } from 'pino' import { randomUUID } from 'crypto' import { LogContext, LogEntry, LogMetadata } from './types' +import { NextRequest } from 'next/server' export class PinoLogger { private static instance: PinoLogger @@ -48,40 +49,95 @@ export class PinoLogger { level: LogEntry['level'], message: string, metadata: LogMetadata, - context: LogContext + context: LogContext, + request?: NextRequest ): LogEntry { return { level, message, timestamp: new Date().toISOString(), - traceId: metadata.traceId || randomUUID(), metadata, context } } - info(message: string, metadata: LogMetadata = {}, context: LogContext) { - const logEntry = this.createLogEntry('INFO', message, metadata, context) + info( + message: string, + metadata: LogMetadata = {}, + context: LogContext, + request?: NextRequest + ) { + const logEntry = this.createLogEntry( + 'INFO', + message, + metadata, + context, + request + ) this.logger.info(logEntry) } - error(message: string, metadata: LogMetadata = {}, context: LogContext) { - const logEntry = this.createLogEntry('ERROR', message, metadata, context) + error( + message: string, + metadata: LogMetadata = {}, + context: LogContext, + request?: NextRequest + ) { + const logEntry = this.createLogEntry( + 'ERROR', + message, + metadata, + context, + request + ) this.logger.error(logEntry) } - warn(message: string, metadata: LogMetadata = {}, context: LogContext) { - const logEntry = this.createLogEntry('WARN', message, metadata, context) + warn( + message: string, + metadata: LogMetadata = {}, + context: LogContext, + request?: NextRequest + ) { + const logEntry = this.createLogEntry( + 'WARN', + message, + metadata, + context, + request + ) this.logger.warn(logEntry) } - debug(message: string, metadata: LogMetadata = {}, context: LogContext) { - const logEntry = this.createLogEntry('DEBUG', message, metadata, context) + debug( + message: string, + metadata: LogMetadata = {}, + context: LogContext, + request?: NextRequest + ) { + const logEntry = this.createLogEntry( + 'DEBUG', + message, + metadata, + context, + request + ) this.logger.debug(logEntry) } - audit(message: string, metadata: LogMetadata = {}, context: LogContext) { - const logEntry = this.createLogEntry('AUDIT', message, metadata, context) + audit( + message: string, + metadata: LogMetadata = {}, + context: LogContext, + request?: NextRequest + ) { + const logEntry = this.createLogEntry( + 'AUDIT', + message, + metadata, + context, + request + ) this.logger.info(logEntry) } } diff --git a/src/lib/logger/request-context.ts b/src/lib/logger/request-context.ts index 5fd3431f..394c33a1 100644 --- a/src/lib/logger/request-context.ts +++ b/src/lib/logger/request-context.ts @@ -38,6 +38,7 @@ export class RequestContextManager { initialMetadata: Record, fn: () => Promise ): Promise { + console.log('initialMetadata', initialMetadata) const context: RequestContext = { requestId: crypto.randomUUID(), startTime: Date.now(), diff --git a/src/lib/logger/types.ts b/src/lib/logger/types.ts index d67fb42b..9c7b2ede 100644 --- a/src/lib/logger/types.ts +++ b/src/lib/logger/types.ts @@ -15,7 +15,7 @@ export interface LogEntry { level: 'INFO' | 'ERROR' | 'WARN' | 'DEBUG' | 'AUDIT' message: string timestamp: string - traceId: string + midazId?: string metadata: LogMetadata context: LogContext } diff --git a/src/middleware/middleware.ts b/src/middleware.ts similarity index 67% rename from src/middleware/middleware.ts rename to src/middleware.ts index bcecf6ae..3b2ae73a 100644 --- a/src/middleware/middleware.ts +++ b/src/middleware.ts @@ -1,7 +1,6 @@ -import { apiLoggerMiddleware } from './api-logger.middleware' import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' - +import { apiLoggerMiddleware } from './middleware/api-logger.middleware' export async function middleware(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/api')) { return apiLoggerMiddleware(request, () => @@ -13,5 +12,8 @@ export async function middleware(request: NextRequest) { } export const config = { - matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] + matcher: [ + '/api/:path*', + '/((?!_next/static|_next/image|favicon.ico|public/.*).*)' + ] } diff --git a/src/middleware/api-logger.middleware.ts b/src/middleware/api-logger.middleware.ts index c573df1b..0483b34c 100644 --- a/src/middleware/api-logger.middleware.ts +++ b/src/middleware/api-logger.middleware.ts @@ -33,8 +33,8 @@ export async function apiLoggerMiddleware( ...requestMetadata } }) - - response.headers.set('X-Request-Id', requestId) + console.log('reponse api-logger middleware', response) + response.headers.set('X-Midaz-Id', requestId) return response } catch (error) { const duration = Date.now() - startTime From 3ec3c46ad781afc16bf05336e56ee5b512392a36 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Thu, 5 Dec 2024 21:28:26 -0300 Subject: [PATCH 08/14] feature loggers improvement --- .../portfolios/[portfolioId]/route.ts | 13 +++++++-- .../ledgers/[ledgerId]/portfolios/route.ts | 17 ++---------- src/app/api/utils/api-error-handler.ts | 27 ++++++++++++++++--- src/core/application/dto/portfolios-dto.ts | 1 + .../portfolios/create-portfolio-use-case.ts | 3 +++ src/core/domain/entities/portfolios-entity.ts | 1 + .../portfolios/create-portfolio-repository.ts | 1 + .../midaz-create-portfolio-repository.ts | 5 +++- src/lib/logger/pino-logger.ts | 6 ++--- src/middleware/api-logger.middleware.ts | 1 - 10 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index 56c2756b..cd306ffd 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -27,7 +27,6 @@ const getPortfolioByIdUseCase: FetchPortfolioById = container.get(FetchPortfolioByIdUseCase) const logger = PinoLogger.getInstance() - export async function DELETE( request: NextRequest, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } @@ -45,7 +44,17 @@ export async function DELETE( midazId }, async () => { - console.log('midazId delete', midazId) + RequestContextManager.addEvent({ + layer: 'application', + operation: 'delete_portfolio', + level: 'audit', + message: 'Deleting portfolio', + metadata: { + organizationId, + ledgerId, + portfolioId + } + }) try { await deletePortfolioUseCase.execute( diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts index 9c73b03d..1773fcd1 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts @@ -39,20 +39,6 @@ export async function GET( operation: 'GET' } - logger.info( - 'Fetching portfolios', - { - organizationId, - ledgerId, - page, - limit, - method: 'GET' - }, - { - ...context - } - ) - try { const portfolios = await fetchAllPortfoliosUseCase.execute( organizationId, @@ -99,7 +85,7 @@ export async function POST( { params }: { params: { id: string; ledgerId: string } } ) { const { id: organizationId, ledgerId } = params - const midazId = request.headers.get('X-Midaz-Id') + const midazId: any = request.headers.get('X-Midaz-Id') return RequestContextManager.runWithContext( request.url, request.method, @@ -112,6 +98,7 @@ export async function POST( const portfolio = await createPortfolioUseCase.execute( organizationId, ledgerId, + midazId, body ) return NextResponse.json(portfolio) diff --git a/src/app/api/utils/api-error-handler.ts b/src/app/api/utils/api-error-handler.ts index dc6ca375..5bd5675b 100644 --- a/src/app/api/utils/api-error-handler.ts +++ b/src/app/api/utils/api-error-handler.ts @@ -2,8 +2,9 @@ import { UnauthorizedException } from '@/core/infrastructure/errors/http-excepti import { MidazError } from '@/core/infrastructure/errors/midaz-error' import { getIntl } from '@/lib/intl' import { PinoLogger } from '@/lib/logger/pino-logger' +import { RequestContextManager } from '@/lib/logger/request-context' -const logger = new PinoLogger() +const logger = PinoLogger.getInstance() export interface ErrorResponse { message: string @@ -21,15 +22,33 @@ export async function apiErrorHandler(error: any): Promise { switch (error.constructor) { case MidazError: - logger.error('Business logic error occurred', error, errorMetadata) + RequestContextManager.addEvent({ + layer: 'api', + operation: 'api_error_handler', + level: 'error', + message: error.message, + metadata: errorMetadata + }) errorResponse = { message: error.message, status: 400 } break case UnauthorizedException: - logger.error('Authentication error occurred', error, errorMetadata) + RequestContextManager.addEvent({ + layer: 'api', + operation: 'api_error_handler', + level: 'error', + message: error.message, + metadata: errorMetadata + }) errorResponse = { message: error.message, status: 401 } break default: - logger.error('Unexpected error occurred', error, errorMetadata) + RequestContextManager.addEvent({ + layer: 'api', + operation: 'api_error_handler', + level: 'error', + message: error.message, + metadata: errorMetadata + }) errorResponse = { message: intl.formatMessage({ id: 'error.midaz.unknowError', diff --git a/src/core/application/dto/portfolios-dto.ts b/src/core/application/dto/portfolios-dto.ts index e333250a..0beb4e6b 100644 --- a/src/core/application/dto/portfolios-dto.ts +++ b/src/core/application/dto/portfolios-dto.ts @@ -13,6 +13,7 @@ export interface CreatePortfolioDto { export interface PortfolioResponseDto { id: string ledgerId: string + midazId: string organizationId: string entityId: string name: string diff --git a/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts index c020f5be..5a5f68b6 100644 --- a/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/create-portfolio-use-case.ts @@ -12,6 +12,7 @@ export interface CreatePortfolio { execute: ( organizationId: string, ledgerId: string, + midazId: string, portfolio: CreatePortfolioDto ) => Promise } @@ -30,6 +31,7 @@ export class CreatePortfolioUseCase implements CreatePortfolio { async execute( organizationId: string, ledgerId: string, + midazId: string, portfolio: CreatePortfolioDto ): Promise { portfolio.status = { @@ -40,6 +42,7 @@ export class CreatePortfolioUseCase implements CreatePortfolio { const portfolioCreated = await this.createPortfolioRepository.create( organizationId, ledgerId, + midazId, portfolioEntity ) diff --git a/src/core/domain/entities/portfolios-entity.ts b/src/core/domain/entities/portfolios-entity.ts index edaf82a4..fbb71d6c 100644 --- a/src/core/domain/entities/portfolios-entity.ts +++ b/src/core/domain/entities/portfolios-entity.ts @@ -4,6 +4,7 @@ export type PortfolioEntity = { id?: string ledgerId?: string organizationId?: string + midazId?: string name: string entityId: string status: StatusEntity diff --git a/src/core/domain/repositories/portfolios/create-portfolio-repository.ts b/src/core/domain/repositories/portfolios/create-portfolio-repository.ts index 437418dd..6717c6bf 100644 --- a/src/core/domain/repositories/portfolios/create-portfolio-repository.ts +++ b/src/core/domain/repositories/portfolios/create-portfolio-repository.ts @@ -4,6 +4,7 @@ export abstract class CreatePortfolioRepository { abstract create: ( organizationId: string, ledgerId: string, + midazId: string, product: PortfolioEntity ) => Promise } diff --git a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts index 8c9fa974..ae0fd653 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts @@ -11,10 +11,13 @@ export class MidazCreatePortfolioRepository async create( organizationId: string, ledgerId: string, + midazId: string, portfolio: PortfolioEntity ): Promise { + console.log('midazId midazCreatePortfolioRepository', midazId) + console.log('portfolio midazCreatePortfolioRepository', portfolio) const url = `${this.baseUrl}/organizations/${organizationId}/ledgers/${ledgerId}/portfolios` - + portfolio.midazId = midazId const response = await httpMidazAuthFetch({ url, method: HTTP_METHODS.POST, diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts index bad6e648..5cce5c8b 100644 --- a/src/lib/logger/pino-logger.ts +++ b/src/lib/logger/pino-logger.ts @@ -1,9 +1,9 @@ // PinoLogger.ts -import pino, { Logger, LoggerOptions } from 'pino' -import { randomUUID } from 'crypto' +import pino, { DestinationStream, Logger, LoggerOptions } from 'pino' import { LogContext, LogEntry, LogMetadata } from './types' import { NextRequest } from 'next/server' +import { EventEmitter } from 'events' export class PinoLogger { private static instance: PinoLogger @@ -11,7 +11,7 @@ export class PinoLogger { private constructor() { const isDebugEnabled = process.env.ENABLE_DEBUG === 'true' - + EventEmitter.defaultMaxListeners = 20 const loggerOptions: LoggerOptions = { level: isDebugEnabled ? 'debug' : 'info', formatters: { diff --git a/src/middleware/api-logger.middleware.ts b/src/middleware/api-logger.middleware.ts index 0483b34c..6b1aa420 100644 --- a/src/middleware/api-logger.middleware.ts +++ b/src/middleware/api-logger.middleware.ts @@ -33,7 +33,6 @@ export async function apiLoggerMiddleware( ...requestMetadata } }) - console.log('reponse api-logger middleware', response) response.headers.set('X-Midaz-Id', requestId) return response } catch (error) { From ff00791abd72347538bf027f2061658adb6c7377 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Mon, 9 Dec 2024 20:16:55 -0300 Subject: [PATCH 09/14] implement log on portfolio --- .../[id]/ledgers/[ledgerId]/accounts/route.ts | 1 - .../portfolios/[portfolioId]/route.ts | 93 +++++++----- .../ledgers/[ledgerId]/portfolios/route.ts | 77 ++++------ src/core/application/dto/portfolios-dto.ts | 2 +- .../portfolios/delete-portfolio-use-case.ts | 3 + .../fetch-all-portfolio-use-case.ts | 5 + .../fetch-portfolio-by-id-use-case.ts | 5 + .../portfolios/update-portfolio-use-case.ts | 5 + .../portfolios/delete-portfolio-repository.ts | 1 + .../midaz-create-portfolio-repository.ts | 5 +- .../midaz-delete-portfolio-repository.ts | 12 +- src/lib/logger/pino-logger.ts | 86 ++--------- src/lib/logger/request-context.ts | 135 +++++++++--------- 13 files changed, 192 insertions(+), 238 deletions(-) diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/accounts/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/accounts/route.ts index d040fdf0..38fdcc70 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/accounts/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/accounts/route.ts @@ -64,7 +64,6 @@ export async function POST( ) { try { const body = await request.json() - console.log(body) const organizationId = params.id const ledgerId = params.ledgerId diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index cd306ffd..2b559723 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -13,7 +13,6 @@ import { UpdatePortfolioUseCase } from '@/core/application/use-cases/portfolios/update-portfolio-use-case' import { NextRequest, NextResponse } from 'next/server' -import { PinoLogger } from '@/lib/logger/pino-logger' import { RequestContextManager } from '@/lib/logger/request-context' const updatePortfolioUseCase: UpdatePortfolio = container.get( @@ -26,13 +25,18 @@ const deletePortfolioUseCase: DeletePortfolio = container.get( const getPortfolioByIdUseCase: FetchPortfolioById = container.get(FetchPortfolioByIdUseCase) -const logger = PinoLogger.getInstance() export async function DELETE( request: NextRequest, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { const { id: organizationId, ledgerId, portfolioId } = params const midazId = request.headers.get('X-Midaz-Id') + if (!midazId) { + return NextResponse.json( + { message: 'X-Midaz-Id header is required' }, + { status: 400 } + ) + } return RequestContextManager.runWithContext( request.url, request.method, @@ -45,7 +49,7 @@ export async function DELETE( }, async () => { RequestContextManager.addEvent({ - layer: 'application', + layer: 'api', operation: 'delete_portfolio', level: 'audit', message: 'Deleting portfolio', @@ -60,6 +64,7 @@ export async function DELETE( await deletePortfolioUseCase.execute( organizationId, ledgerId, + midazId, portfolioId ) return NextResponse.json({}, { status: 200 }) @@ -77,48 +82,64 @@ export async function PATCH( request: NextRequest, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { - try { - const body = await request.json() - const organizationId = params.id - const ledgerId = params.ledgerId - const portfolioId = params.portfolioId + const { id: organizationId, ledgerId, portfolioId } = params + return RequestContextManager.runWithContext( + request.url, + request.method, + { organizationId, ledgerId, portfolioId }, + async () => { + try { + const body = await request.json() + const organizationId = params.id + const ledgerId = params.ledgerId + const portfolioId = params.portfolioId - const portfolioUpdated = await updatePortfolioUseCase.execute( - organizationId, - ledgerId, - portfolioId, - body - ) + const portfolioUpdated = await updatePortfolioUseCase.execute( + organizationId, + ledgerId, + portfolioId, + body + ) - return NextResponse.json(portfolioUpdated) - } catch (error: any) { - console.error('Error updating portfolio', error) - const { message, status } = await apiErrorHandler(error) + return NextResponse.json(portfolioUpdated) + } catch (error: any) { + console.error('Error updating portfolio', error) + const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) - } + return NextResponse.json({ message }, { status }) + } + } + ) } export async function GET( - request: Request, + request: NextRequest, { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { - try { - const organizationId = params.id - const ledgerId = params.ledgerId - const portfolioId = params.portfolioId + const { id: organizationId, ledgerId, portfolioId } = params + return RequestContextManager.runWithContext( + request.url, + request.method, + { organizationId, ledgerId, portfolioId }, + async () => { + try { + const organizationId = params.id + const ledgerId = params.ledgerId + const portfolioId = params.portfolioId - const portfolio = await getPortfolioByIdUseCase.execute( - organizationId, - ledgerId, - portfolioId - ) + const portfolio = await getPortfolioByIdUseCase.execute( + organizationId, + ledgerId, + portfolioId + ) - return NextResponse.json(portfolio) - } catch (error: any) { - console.error('Error getting portfolio', error) - const { message, status } = await apiErrorHandler(error) + return NextResponse.json(portfolio) + } catch (error: any) { + console.error('Error getting portfolio', error) + const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) - } + return NextResponse.json({ message }, { status }) + } + } + ) } diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts index 1773fcd1..0d2e7eae 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/route.ts @@ -8,9 +8,7 @@ import { FetchAllPortfolios, FetchAllPortfoliosUseCase } from '@/core/application/use-cases/portfolios/fetch-all-portfolio-use-case' - import { NextRequest, NextResponse } from 'next/server' -import { PinoLogger } from '@/lib/logger/pino-logger' import { RequestContextManager } from '@/lib/logger/request-context' const createPortfolioUseCase: CreatePortfolio = container.get( @@ -20,8 +18,6 @@ const createPortfolioUseCase: CreatePortfolio = container.get( const fetchAllPortfoliosUseCase: FetchAllPortfolios = container.get(FetchAllPortfoliosUseCase) -const logger = PinoLogger.getInstance() - export async function GET( request: Request, { params }: { params: { id: string; ledgerId: string } } @@ -31,53 +27,26 @@ export async function GET( const page = Number(searchParams.get('page')) || 1 const organizationId = params.id const ledgerId = params.ledgerId + return RequestContextManager.runWithContext( + request.url, + request.method, + { organizationId, ledgerId }, + async () => { + try { + const portfolios = await fetchAllPortfoliosUseCase.execute( + organizationId, + ledgerId, + page, + limit + ) - const context = { - component: 'PortfoliosAPI', - action: 'fetchPortfolios', - layer: 'api' as const, - operation: 'GET' - } - - try { - const portfolios = await fetchAllPortfoliosUseCase.execute( - organizationId, - ledgerId, - page, - limit - ) - - logger.info( - 'Successfully fetched portfolios', - { - organizationId, - ledgerId, - count: portfolios.items.length, - method: 'GET' - }, - context - ) - - return NextResponse.json(portfolios) - } catch (error: any) { - logger.error( - 'Failed to fetch portfolios', - { - organizationId, - ledgerId, - error: { - message: error.message, - name: error.name, - stack: error.stack - } - }, - { - ...context + return NextResponse.json(portfolios) + } catch (error: any) { + const { message, status } = await apiErrorHandler(error) + return NextResponse.json({ message }, { status }) } - ) - const { message, status } = await apiErrorHandler(error) - return NextResponse.json({ message }, { status }) - } + } + ) } export async function POST( @@ -85,15 +54,19 @@ export async function POST( { params }: { params: { id: string; ledgerId: string } } ) { const { id: organizationId, ledgerId } = params - const midazId: any = request.headers.get('X-Midaz-Id') + const midazId = request.headers.get('X-Midaz-Id') return RequestContextManager.runWithContext( request.url, request.method, { organizationId, ledgerId, midazId }, async () => { try { - console.log('midazId post', midazId) - console.log('request readers', request.headers) + if (!midazId) { + return NextResponse.json( + { message: 'X-Midaz-Id header is required' }, + { status: 400 } + ) + } const body = await request.json() const portfolio = await createPortfolioUseCase.execute( organizationId, diff --git a/src/core/application/dto/portfolios-dto.ts b/src/core/application/dto/portfolios-dto.ts index 0beb4e6b..15639a2a 100644 --- a/src/core/application/dto/portfolios-dto.ts +++ b/src/core/application/dto/portfolios-dto.ts @@ -13,7 +13,7 @@ export interface CreatePortfolioDto { export interface PortfolioResponseDto { id: string ledgerId: string - midazId: string + midazId?: string organizationId: string entityId: string name: string diff --git a/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts index 12469d32..1e056543 100644 --- a/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/delete-portfolio-use-case.ts @@ -6,6 +6,7 @@ export interface DeletePortfolio { execute: ( organizationId: string, ledgerId: string, + midazId: string, portfolioId: string ) => Promise } @@ -23,11 +24,13 @@ export class DeletePortfolioUseCase implements DeletePortfolio { async execute( organizationId: string, ledgerId: string, + midazId: string, portfolioId: string ): Promise { await this.deletePortfolioRepository.delete( organizationId, ledgerId, + midazId, portfolioId ) } diff --git a/src/core/application/use-cases/portfolios/fetch-all-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/fetch-all-portfolio-use-case.ts index a9b1f744..e96b13cb 100644 --- a/src/core/application/use-cases/portfolios/fetch-all-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/fetch-all-portfolio-use-case.ts @@ -5,6 +5,7 @@ import { PortfolioResponseDto } from '../../dto/portfolios-dto' import { FetchAllPortfoliosRepository } from '@/core/domain/repositories/portfolios/fetch-all-portfolio-repository' import { PortfolioEntity } from '@/core/domain/entities/portfolios-entity' import { inject, injectable } from 'inversify' +import { LogOperation } from '../../decorators/log-operation' export interface FetchAllPortfolios { execute: ( @@ -22,6 +23,10 @@ export class FetchAllPortfoliosUseCase implements FetchAllPortfolios { private readonly fetchAllPortfoliosRepository: FetchAllPortfoliosRepository ) {} + @LogOperation({ + layer: 'application', + operation: 'fetch_all_portfolios' + }) async execute( organizationId: string, ledgerId: string, diff --git a/src/core/application/use-cases/portfolios/fetch-portfolio-by-id-use-case.ts b/src/core/application/use-cases/portfolios/fetch-portfolio-by-id-use-case.ts index 3635fe80..e6d2d7a7 100644 --- a/src/core/application/use-cases/portfolios/fetch-portfolio-by-id-use-case.ts +++ b/src/core/application/use-cases/portfolios/fetch-portfolio-by-id-use-case.ts @@ -2,6 +2,7 @@ import { FetchPortfolioByIdRepository } from '@/core/domain/repositories/portfol import { PortfolioMapper } from '../../mappers/portfolio-mapper' import { PortfolioResponseDto } from '../../dto/portfolios-dto' import { inject, injectable } from 'inversify' +import { LogOperation } from '../../decorators/log-operation' export interface FetchPortfolioById { execute: ( @@ -18,6 +19,10 @@ export class FetchPortfolioByIdUseCase implements FetchPortfolioById { private readonly fetchPortfolioByIdRepository: FetchPortfolioByIdRepository ) {} + @LogOperation({ + layer: 'application', + operation: 'fetch_portfolio_by_id' + }) async execute( organizationId: string, ledgerId: string, diff --git a/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts index 79d196fb..8ca42e0e 100644 --- a/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts @@ -7,6 +7,7 @@ import { } from '../../dto/portfolios-dto' import { PortfolioEntity } from '@/core/domain/entities/portfolios-entity' import { inject, injectable } from 'inversify' +import { LogOperation } from '../../decorators/log-operation' export interface UpdatePortfolio { execute: ( @@ -24,6 +25,10 @@ export class UpdatePortfolioUseCase implements UpdatePortfolio { private readonly updatePortfolioRepository: UpdatePortfolioRepository ) {} + @LogOperation({ + layer: 'application', + operation: 'update_portfolio' + }) async execute( organizationId: string, ledgerId: string, diff --git a/src/core/domain/repositories/portfolios/delete-portfolio-repository.ts b/src/core/domain/repositories/portfolios/delete-portfolio-repository.ts index a80dc525..97660913 100644 --- a/src/core/domain/repositories/portfolios/delete-portfolio-repository.ts +++ b/src/core/domain/repositories/portfolios/delete-portfolio-repository.ts @@ -2,6 +2,7 @@ export abstract class DeletePortfolioRepository { abstract delete: ( organizationId: string, ledgerId: string, + midazId: string, portfolioId: string ) => Promise } diff --git a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts index ae0fd653..c406ef6d 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts @@ -14,10 +14,9 @@ export class MidazCreatePortfolioRepository midazId: string, portfolio: PortfolioEntity ): Promise { - console.log('midazId midazCreatePortfolioRepository', midazId) - console.log('portfolio midazCreatePortfolioRepository', portfolio) const url = `${this.baseUrl}/organizations/${organizationId}/ledgers/${ledgerId}/portfolios` - portfolio.midazId = midazId + + console.log('midazId', midazId) const response = await httpMidazAuthFetch({ url, method: HTTP_METHODS.POST, diff --git a/src/core/infrastructure/midaz/portfolios/midaz-delete-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-delete-portfolio-repository.ts index 096d19c9..1d101646 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-delete-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-delete-portfolio-repository.ts @@ -1,21 +1,27 @@ -import { DeleteProductRepository } from '@/core/domain/repositories/products/delete-product-repository' import { HTTP_METHODS, httpMidazAuthFetch } from '../../utils/http-fetch-utils' import { injectable } from 'inversify' +import { DeletePortfolioRepository } from '@/core/domain/repositories/portfolios/delete-portfolio-repository' @injectable() -export class MidazDeletePortfolioRepository implements DeleteProductRepository { +export class MidazDeletePortfolioRepository + implements DeletePortfolioRepository +{ private baseUrl: string = process.env.MIDAZ_BASE_PATH as string async delete( organizationId: string, ledgerId: string, + midazId: string, portfolioId: string ): Promise { const url = `${this.baseUrl}/organizations/${organizationId}/ledgers/${ledgerId}/portfolios/${portfolioId}` await httpMidazAuthFetch({ url, - method: HTTP_METHODS.DELETE + method: HTTP_METHODS.DELETE, + headers: { + 'Midaz-Id': midazId + } }) return diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts index 5cce5c8b..4dc94319 100644 --- a/src/lib/logger/pino-logger.ts +++ b/src/lib/logger/pino-logger.ts @@ -1,9 +1,5 @@ -// PinoLogger.ts - -import pino, { DestinationStream, Logger, LoggerOptions } from 'pino' +import pino, { Logger, LoggerOptions } from 'pino' import { LogContext, LogEntry, LogMetadata } from './types' -import { NextRequest } from 'next/server' -import { EventEmitter } from 'events' export class PinoLogger { private static instance: PinoLogger @@ -11,7 +7,7 @@ export class PinoLogger { private constructor() { const isDebugEnabled = process.env.ENABLE_DEBUG === 'true' - EventEmitter.defaultMaxListeners = 20 + // EventEmitter.defaultMaxListeners = 20 const loggerOptions: LoggerOptions = { level: isDebugEnabled ? 'debug' : 'info', formatters: { @@ -49,8 +45,7 @@ export class PinoLogger { level: LogEntry['level'], message: string, metadata: LogMetadata, - context: LogContext, - request?: NextRequest + context: LogContext ): LogEntry { return { level, @@ -61,83 +56,28 @@ export class PinoLogger { } } - info( - message: string, - metadata: LogMetadata = {}, - context: LogContext, - request?: NextRequest - ) { - const logEntry = this.createLogEntry( - 'INFO', - message, - metadata, - context, - request - ) + info(message: string, metadata: LogMetadata = {}, context: LogContext) { + const logEntry = this.createLogEntry('INFO', message, metadata, context) this.logger.info(logEntry) } - error( - message: string, - metadata: LogMetadata = {}, - context: LogContext, - request?: NextRequest - ) { - const logEntry = this.createLogEntry( - 'ERROR', - message, - metadata, - context, - request - ) + error(message: string, metadata: LogMetadata = {}, context: LogContext) { + const logEntry = this.createLogEntry('ERROR', message, metadata, context) this.logger.error(logEntry) } - warn( - message: string, - metadata: LogMetadata = {}, - context: LogContext, - request?: NextRequest - ) { - const logEntry = this.createLogEntry( - 'WARN', - message, - metadata, - context, - request - ) + warn(message: string, metadata: LogMetadata = {}, context: LogContext) { + const logEntry = this.createLogEntry('WARN', message, metadata, context) this.logger.warn(logEntry) } - debug( - message: string, - metadata: LogMetadata = {}, - context: LogContext, - request?: NextRequest - ) { - const logEntry = this.createLogEntry( - 'DEBUG', - message, - metadata, - context, - request - ) + debug(message: string, metadata: LogMetadata = {}, context: LogContext) { + const logEntry = this.createLogEntry('DEBUG', message, metadata, context) this.logger.debug(logEntry) } - audit( - message: string, - metadata: LogMetadata = {}, - context: LogContext, - request?: NextRequest - ) { - const logEntry = this.createLogEntry( - 'AUDIT', - message, - metadata, - context, - request - ) + audit(message: string, metadata: LogMetadata = {}, context: LogContext) { + const logEntry = this.createLogEntry('AUDIT', message, metadata, context) this.logger.info(logEntry) } } diff --git a/src/lib/logger/request-context.ts b/src/lib/logger/request-context.ts index 394c33a1..c289246d 100644 --- a/src/lib/logger/request-context.ts +++ b/src/lib/logger/request-context.ts @@ -5,7 +5,7 @@ import { PinoLogger } from './pino-logger' type Layer = 'api' | 'application' | 'infrastructure' | 'domain' type Level = 'info' | 'error' | 'warn' | 'debug' | 'audit' -interface Event { +interface LogEvent { timestamp: number layer: Layer operation: string @@ -21,7 +21,7 @@ interface RequestContext { path: string method: string metadata: Record - events: Event[] + events: LogEvent[] } export class RequestContextManager { @@ -38,7 +38,6 @@ export class RequestContextManager { initialMetadata: Record, fn: () => Promise ): Promise { - console.log('initialMetadata', initialMetadata) const context: RequestContext = { requestId: crypto.randomUUID(), startTime: Date.now(), @@ -51,6 +50,7 @@ export class RequestContextManager { return this.storage.run(context, async () => { try { const result = await fn() + this.finalizeContext() return result } catch (error) { @@ -71,30 +71,27 @@ export class RequestContextManager { const context = this.getContext() if (context) { const duration = Date.now() - context.startTime - console.log( - 'ENABLE_REQUEST_TIMELINE', - process.env.ENABLE_REQUEST_TIMELINE + + // if (process.env.ENABLE_REQUEST_TIMELINE === 'true') { + this.logger.info( + 'Request Timeline', + { + requestId: context.requestId, + path: context.path, + method: context.method, + duration, + metadata: context.metadata, + events: context.events.map((event) => ({ + ...event, + timestamp: new Date(event.timestamp).toISOString() + })) + }, + { + layer: 'api', + operation: 'request_timeline' + } ) - if (process.env.ENABLE_REQUEST_TIMELINE === 'true') { - this.logger.info( - 'Request Timeline', - { - requestId: context.requestId, - path: context.path, - method: context.method, - duration, - metadata: context.metadata, - events: context.events.map((event) => ({ - ...event, - timestamp: new Date(event.timestamp).toISOString() - })) - }, - { - layer: 'api', - operation: 'request_timeline' - } - ) - } + // } } } @@ -102,59 +99,59 @@ export class RequestContextManager { return this.storage.getStore() } - static addEvent(event: Omit) { + static addEvent(event: Omit) { const context = this.getContext() if (context) { if (event.level === 'debug' && !this.shouldLogDebug()) { return } - const fullEvent: Event = { + const fullEvent: LogEvent = { timestamp: Date.now(), ...event } - switch (event.level) { - case 'debug': - this.logger.debug( - event.message, - { eventData: fullEvent, requestId: context.requestId }, - { layer: event.layer, operation: event.operation } - ) - break - case 'info': - this.logger.info( - event.message, - { eventData: fullEvent, requestId: context.requestId }, - { layer: event.layer, operation: event.operation } - ) - break - case 'error': - this.logger.error( - event.message, - { - eventData: fullEvent, - requestId: context.requestId, - error: event.error - }, - { layer: event.layer, operation: event.operation } - ) - break - case 'warn': - this.logger.warn( - event.message, - { eventData: fullEvent, requestId: context.requestId }, - { layer: event.layer, operation: event.operation } - ) - break - case 'audit': - this.logger.audit( - event.message, - { eventData: fullEvent, requestId: context.requestId }, - { layer: event.layer, operation: event.operation } - ) - break - } + // switch (event.level) { + // case 'debug': + // this.logger.debug( + // event.message, + // { eventData: fullEvent, requestId: context.requestId }, + // { layer: event.layer, operation: event.operation } + // ) + // break + // case 'info': + // this.logger.info( + // event.message, + // { eventData: fullEvent, requestId: context.requestId }, + // { layer: event.layer, operation: event.operation } + // ) + // break + // case 'error': + // this.logger.error( + // event.message, + // { + // eventData: fullEvent, + // requestId: context.requestId, + // error: event.error + // }, + // { layer: event.layer, operation: event.operation } + // ) + // break + // case 'warn': + // this.logger.warn( + // event.message, + // { eventData: fullEvent, requestId: context.requestId }, + // { layer: event.layer, operation: event.operation } + // ) + // break + // case 'audit': + // this.logger.audit( + // event.message, + // { eventData: fullEvent, requestId: context.requestId }, + // { layer: event.layer, operation: event.operation } + // ) + // break + // } context.events.push(fullEvent) } From c4343e939cb1bc4698d21d87a6454a95fa25bb1c Mon Sep 17 00:00:00 2001 From: paulolerian Date: Tue, 10 Dec 2024 15:32:20 -0300 Subject: [PATCH 10/14] fix: pr changes --- .../[ledgerId]/portfolios/[portfolioId]/route.ts | 15 ++++----------- src/core/application/mappers/portfolio-mapper.ts | 7 ------- .../portfolios/update-portfolio-use-case.ts | 3 +++ .../portfolios/update-portfolio-repository.ts | 1 + .../container-registry/container-registry.ts | 5 ----- .../midaz-create-portfolio-repository.ts | 1 - .../midaz-update-portfolio-repository.ts | 6 +++++- src/lib/logger/pino-logger.ts | 1 - 8 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index 2b559723..ee6e30d9 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -31,12 +31,6 @@ export async function DELETE( ) { const { id: organizationId, ledgerId, portfolioId } = params const midazId = request.headers.get('X-Midaz-Id') - if (!midazId) { - return NextResponse.json( - { message: 'X-Midaz-Id header is required' }, - { status: 400 } - ) - } return RequestContextManager.runWithContext( request.url, request.method, @@ -64,7 +58,7 @@ export async function DELETE( await deletePortfolioUseCase.execute( organizationId, ledgerId, - midazId, + midazId!, portfolioId ) return NextResponse.json({}, { status: 200 }) @@ -83,21 +77,20 @@ export async function PATCH( { params }: { params: { id: string; ledgerId: string; portfolioId: string } } ) { const { id: organizationId, ledgerId, portfolioId } = params + const midazId = request.headers.get('X-Midaz-Id') return RequestContextManager.runWithContext( request.url, request.method, - { organizationId, ledgerId, portfolioId }, + { organizationId, ledgerId, portfolioId, midazId }, async () => { try { const body = await request.json() - const organizationId = params.id - const ledgerId = params.ledgerId - const portfolioId = params.portfolioId const portfolioUpdated = await updatePortfolioUseCase.execute( organizationId, ledgerId, portfolioId, + midazId!, body ) diff --git a/src/core/application/mappers/portfolio-mapper.ts b/src/core/application/mappers/portfolio-mapper.ts index 3d0b6d8c..4ed6cf4b 100644 --- a/src/core/application/mappers/portfolio-mapper.ts +++ b/src/core/application/mappers/portfolio-mapper.ts @@ -9,13 +9,6 @@ import { AccountResponseDto } from '../dto/account-dto' export class PortfolioMapper { public static toDomain(dto: CreatePortfolioDto): PortfolioEntity { - RequestContextManager.addEvent({ - layer: 'application', - operation: 'portfolio_dto_to_entity', - level: 'debug', - message: 'Mapping portfolio dto to entity', - metadata: { dto } - }) return { entityId: dto.entityId, name: dto.name, diff --git a/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts b/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts index 8ca42e0e..7cbf8ac5 100644 --- a/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts +++ b/src/core/application/use-cases/portfolios/update-portfolio-use-case.ts @@ -14,6 +14,7 @@ export interface UpdatePortfolio { organizationId: string, ledgerId: string, portfolioId: string, + midazId: string, portfolio: Partial ) => Promise } @@ -33,6 +34,7 @@ export class UpdatePortfolioUseCase implements UpdatePortfolio { organizationId: string, ledgerId: string, portfolioId: string, + midazId: string, portfolio: Partial ): Promise { portfolio.status = { @@ -47,6 +49,7 @@ export class UpdatePortfolioUseCase implements UpdatePortfolio { organizationId, ledgerId, portfolioId, + midazId, portfolioEntity ) diff --git a/src/core/domain/repositories/portfolios/update-portfolio-repository.ts b/src/core/domain/repositories/portfolios/update-portfolio-repository.ts index d8563bdb..1bb58bdc 100644 --- a/src/core/domain/repositories/portfolios/update-portfolio-repository.ts +++ b/src/core/domain/repositories/portfolios/update-portfolio-repository.ts @@ -5,6 +5,7 @@ export abstract class UpdatePortfolioRepository { organizationId: string, ledgerId: string, portfolioId: string, + midazId: string, portfolio: Partial ) => Promise } diff --git a/src/core/infrastructure/container-registry/container-registry.ts b/src/core/infrastructure/container-registry/container-registry.ts index 0ac78f4a..1d63c95e 100644 --- a/src/core/infrastructure/container-registry/container-registry.ts +++ b/src/core/infrastructure/container-registry/container-registry.ts @@ -10,9 +10,6 @@ import { AssetUseCaseModule } from './use-cases/asset-module' import { ProductUseCaseModule } from './use-cases/product-module' import { CasdoorModule } from '../casdoor/module/casdoor-module' import { AuthUseCaseModule } from './use-cases/auth-module' -import { ILogger } from '@/core/domain/logger/logger.interface' -import { PinoLogger } from '@/lib/logger/pino-logger' -import { TYPES } from '@/core/types' export const container = new Container() @@ -26,5 +23,3 @@ container.load(PortfolioUseCaseModule) container.load(AccountUseCaseModule) container.load(AssetUseCaseModule) container.load(ProductUseCaseModule) - -container.bind(TYPES.ILogger).to(PinoLogger).inSingletonScope() diff --git a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts index c406ef6d..b25ddfdd 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts @@ -16,7 +16,6 @@ export class MidazCreatePortfolioRepository ): Promise { const url = `${this.baseUrl}/organizations/${organizationId}/ledgers/${ledgerId}/portfolios` - console.log('midazId', midazId) const response = await httpMidazAuthFetch({ url, method: HTTP_METHODS.POST, diff --git a/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts index b8d20e8b..091c0706 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts @@ -13,6 +13,7 @@ export class MidazUpdatePortfolioRepository organizationId: string, ledgerId: string, portfolioId: string, + midazId: string, portfolio: Partial ): Promise { const url = `${this.baseUrl}/organizations/${organizationId}/ledgers/${ledgerId}/portfolios/${portfolioId}` @@ -20,7 +21,10 @@ export class MidazUpdatePortfolioRepository const response = await httpMidazAuthFetch({ url, method: HTTP_METHODS.PATCH, - body: JSON.stringify(portfolio) + body: JSON.stringify(portfolio), + headers: { + 'X-Midaz-Id': midazId + } }) return response diff --git a/src/lib/logger/pino-logger.ts b/src/lib/logger/pino-logger.ts index 4dc94319..0ffa8780 100644 --- a/src/lib/logger/pino-logger.ts +++ b/src/lib/logger/pino-logger.ts @@ -7,7 +7,6 @@ export class PinoLogger { private constructor() { const isDebugEnabled = process.env.ENABLE_DEBUG === 'true' - // EventEmitter.defaultMaxListeners = 20 const loggerOptions: LoggerOptions = { level: isDebugEnabled ? 'debug' : 'info', formatters: { From 8171ac1cb1d2a8ad2c1c79662ac34d4534f17897 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Tue, 10 Dec 2024 15:37:05 -0300 Subject: [PATCH 11/14] fix: pr changes --- .env.example | 6 +++++- package.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index de7658f9..c12f6d89 100644 --- a/.env.example +++ b/.env.example @@ -18,4 +18,8 @@ MIDAZ_API_PORT=3000 MIDAZ_BASE_PATH='http://${MIDAZ_API_HOST}:${MIDAZ_API_PORT}/v1' MIDAZ_TRANSACTION_BASE_HOST='transaction' MIDAZ_TRANSACTION_BASE_PORT=3002 -MIDAZ_TRANSACTION_BASE_PATH='http://${MIDAZ_API_HOST}:${MIDAZ_TRANSACTION_BASE_PORT}/v1' \ No newline at end of file +MIDAZ_TRANSACTION_BASE_PATH='http://${MIDAZ_API_HOST}:${MIDAZ_TRANSACTION_BASE_PORT}/v1' + +ENABLE_DEBUG=true +ENABLE_REQUEST_TIMELINE=true +NODE_ENV=development \ No newline at end of file diff --git a/package.json b/package.json index a7f75b4e..bc172b82 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "NODE_ENV=development next dev -p 8081", + "dev": "next dev -p 8081", "build": "next build", "start": "next start -p 8081", "lint": "next lint --fix", From fef14e377cc2f1f690cc3b21dc3a249db99515b4 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Tue, 10 Dec 2024 18:15:18 -0300 Subject: [PATCH 12/14] remove unused type --- src/core/types.ts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 src/core/types.ts diff --git a/src/core/types.ts b/src/core/types.ts deleted file mode 100644 index 7dd714c8..00000000 --- a/src/core/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const TYPES = { - ILogger: Symbol.for('ILogger') -} From 58eb5321ba0d02ca619fb30dd5f7ed918ef6a857 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Tue, 10 Dec 2024 18:19:54 -0300 Subject: [PATCH 13/14] remove unused code --- src/core/domain/logger/logger.interface.ts | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/core/domain/logger/logger.interface.ts diff --git a/src/core/domain/logger/logger.interface.ts b/src/core/domain/logger/logger.interface.ts deleted file mode 100644 index 00d04205..00000000 --- a/src/core/domain/logger/logger.interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ILogger { - debug(message: string, metadata?: Record): void - info(message: string, metadata?: Record): void - warn(message: string, metadata?: Record): void - error(message: string, error?: Error, metadata?: Record): void - audit(message: string, metadata?: Record): void -} From 529b28e865afc59db563934b1b426c607ebb2ed7 Mon Sep 17 00:00:00 2001 From: paulolerian Date: Thu, 12 Dec 2024 00:26:22 -0300 Subject: [PATCH 14/14] fix: remove console and unused codes --- .../portfolios/[portfolioId]/route.ts | 3 -- .../application/mappers/portfolio-mapper.ts | 2 - .../midaz-create-portfolio-repository.ts | 5 ++- .../midaz-update-portfolio-repository.ts | 2 +- src/lib/logger/request-context.ts | 44 ------------------- 5 files changed, 5 insertions(+), 51 deletions(-) diff --git a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts index ee6e30d9..7ca19b9b 100644 --- a/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts +++ b/src/app/api/organizations/[id]/ledgers/[ledgerId]/portfolios/[portfolioId]/route.ts @@ -63,7 +63,6 @@ export async function DELETE( ) return NextResponse.json({}, { status: 200 }) } catch (error: any) { - console.error('Error deleting portfolio', error) const { message, status } = await apiErrorHandler(error) return NextResponse.json({ message }, { status }) @@ -96,7 +95,6 @@ export async function PATCH( return NextResponse.json(portfolioUpdated) } catch (error: any) { - console.error('Error updating portfolio', error) const { message, status } = await apiErrorHandler(error) return NextResponse.json({ message }, { status }) @@ -128,7 +126,6 @@ export async function GET( return NextResponse.json(portfolio) } catch (error: any) { - console.error('Error getting portfolio', error) const { message, status } = await apiErrorHandler(error) return NextResponse.json({ message }, { status }) diff --git a/src/core/application/mappers/portfolio-mapper.ts b/src/core/application/mappers/portfolio-mapper.ts index 4ed6cf4b..4b70c29d 100644 --- a/src/core/application/mappers/portfolio-mapper.ts +++ b/src/core/application/mappers/portfolio-mapper.ts @@ -1,7 +1,5 @@ import { PortfolioEntity } from '@/core/domain/entities/portfolios-entity' import { CreatePortfolioDto, PortfolioResponseDto } from '../dto/portfolios-dto' -import { RequestContextManager } from '@/lib/logger/request-context' - import { PaginationEntity } from '@/core/domain/entities/pagination-entity' import { PaginationMapper } from './pagination-mapper' import { AccountMapper } from './account-mapper' diff --git a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts index b25ddfdd..b874d8dc 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-create-portfolio-repository.ts @@ -19,7 +19,10 @@ export class MidazCreatePortfolioRepository const response = await httpMidazAuthFetch({ url, method: HTTP_METHODS.POST, - body: JSON.stringify(portfolio) + body: JSON.stringify(portfolio), + headers: { + 'Midaz-Id': midazId + } }) return response diff --git a/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts b/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts index 091c0706..1980a9b8 100644 --- a/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts +++ b/src/core/infrastructure/midaz/portfolios/midaz-update-portfolio-repository.ts @@ -23,7 +23,7 @@ export class MidazUpdatePortfolioRepository method: HTTP_METHODS.PATCH, body: JSON.stringify(portfolio), headers: { - 'X-Midaz-Id': midazId + 'Midaz-Id': midazId } }) diff --git a/src/lib/logger/request-context.ts b/src/lib/logger/request-context.ts index c289246d..0c22c680 100644 --- a/src/lib/logger/request-context.ts +++ b/src/lib/logger/request-context.ts @@ -72,7 +72,6 @@ export class RequestContextManager { if (context) { const duration = Date.now() - context.startTime - // if (process.env.ENABLE_REQUEST_TIMELINE === 'true') { this.logger.info( 'Request Timeline', { @@ -91,7 +90,6 @@ export class RequestContextManager { operation: 'request_timeline' } ) - // } } } @@ -111,48 +109,6 @@ export class RequestContextManager { ...event } - // switch (event.level) { - // case 'debug': - // this.logger.debug( - // event.message, - // { eventData: fullEvent, requestId: context.requestId }, - // { layer: event.layer, operation: event.operation } - // ) - // break - // case 'info': - // this.logger.info( - // event.message, - // { eventData: fullEvent, requestId: context.requestId }, - // { layer: event.layer, operation: event.operation } - // ) - // break - // case 'error': - // this.logger.error( - // event.message, - // { - // eventData: fullEvent, - // requestId: context.requestId, - // error: event.error - // }, - // { layer: event.layer, operation: event.operation } - // ) - // break - // case 'warn': - // this.logger.warn( - // event.message, - // { eventData: fullEvent, requestId: context.requestId }, - // { layer: event.layer, operation: event.operation } - // ) - // break - // case 'audit': - // this.logger.audit( - // event.message, - // { eventData: fullEvent, requestId: context.requestId }, - // { layer: event.layer, operation: event.operation } - // ) - // break - // } - context.events.push(fullEvent) } }