From 25914bfa18b1d46eeabc138407f17d7f5c7ecf0b Mon Sep 17 00:00:00 2001 From: OrdisPrime <134585663+OrdisPrime@users.noreply.github.com> Date: Sat, 6 Jan 2024 16:26:58 +0100 Subject: [PATCH] Improved logging using winston (#111) --- .env.example | 16 +- .gitignore | 3 + config.json | 2 +- package-lock.json | 278 +++++++++++++++++- package.json | 6 +- src/app.ts | 9 +- src/controllers/api/findSessionsController.ts | 11 +- src/controllers/api/getCreditsController.ts | 2 +- src/controllers/api/hostSessionController.ts | 11 +- src/controllers/api/joinSessionController.ts | 4 +- src/controllers/api/loginController.ts | 3 +- .../api/rerollRandomModController.ts | 3 +- src/controllers/api/saveLoadout.ts | 3 +- .../api/setBootLocationController.ts | 4 +- .../api/updateSessionController.ts | 1 + src/helpers/general.ts | 7 + src/index.ts | 5 +- src/managers/sessionManager.ts | 6 +- src/middleware/middleware.ts | 19 +- src/middleware/morgenMiddleware.ts | 6 + src/services/inventoryService.ts | 3 +- .../missionInventoryUpdateService .ts | 7 +- src/services/mongoService.ts | 7 +- src/services/purchaseService.ts | 40 ++- src/services/saveLoadoutService.ts | 11 +- src/types/purchaseTypes.ts | 1 - src/utils/logger.ts | 113 +++++++ 27 files changed, 504 insertions(+), 77 deletions(-) create mode 100644 src/middleware/morgenMiddleware.ts create mode 100644 src/utils/logger.ts diff --git a/.env.example b/.env.example index ed317f00e..fc389f4dd 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,15 @@ -MONGODB_URL='mongodb://127.0.0.1:27017/wf_emulator' -PORT=3001 +MONGODB_URL='mongodb://127.0.0.1:27017/openWF' -DATABASE_PORT=27017 +#DOCKER ONLY +DATABASE_PORT=27017 DATABASE_USERNAME=root -DATABASE_PASSWORD=root +DATABASE_PASSWORD=database +#DOCKER ONLY END + +# save logs to file +LOG_FILES=true +#possible log levels: { fatal: 0, error: 1, warn: 2, info: 3, http: 4, debug: 5, trace: 6 } +LOG_LEVEL=trace + + diff --git a/.gitignore b/.gitignore index 23c4cd819..7e1fa4a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ yarn.lock # JetBrains/webstorm configs .idea/ + +# logs +/logs \ No newline at end of file diff --git a/config.json b/config.json index 64ad5d3c2..205c173fa 100644 --- a/config.json +++ b/config.json @@ -8,5 +8,5 @@ "skipTutorial": true, "testMission": true, "testQuestKey": true, - "infinitePlatinum": false + "infiniteResources": true } diff --git a/package-lock.json b/package-lock.json index de59907cd..873314d5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,9 @@ "dotenv": "^16.1.3", "express": "^5.0.0-beta.1", "mongoose": "^8.0.2", - "warframe-items": "1.1260.121" + "warframe-items": "1.1260.121", + "winston": "^3.11.0", + "winston-daily-rotate-file": "^4.7.1" }, "devDependencies": { "@tsconfig/node20": "^1.0.0", @@ -42,6 +44,14 @@ "node": ">=0.10.0" } }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -54,6 +64,16 @@ "node": ">=12" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -426,6 +446,11 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -1043,6 +1068,11 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1248,6 +1278,15 @@ "node": ">= 6" } }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1263,8 +1302,38 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -1456,6 +1525,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1842,6 +1916,11 @@ "reusify": "^1.0.4" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -1854,6 +1933,14 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-stream-rotator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", + "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", + "dependencies": { + "moment": "^2.29.1" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1918,6 +2005,11 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2152,6 +2244,11 @@ "node": ">= 0.10" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2337,6 +2434,11 @@ "node": ">=12.0.0" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2371,6 +2473,27 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2507,6 +2630,14 @@ "node": ">=10" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, "node_modules/mongodb": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.2.0.tgz", @@ -2698,6 +2829,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -2727,6 +2866,14 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -3000,6 +3147,19 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3225,6 +3385,14 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3336,6 +3504,14 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3372,6 +3548,14 @@ "memory-pager": "^1.0.2" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -3380,6 +3564,14 @@ "node": ">= 0.6" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3465,6 +3657,11 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3523,6 +3720,14 @@ "tree-kill": "cli.js" } }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-api-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", @@ -3740,6 +3945,11 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -3802,6 +4012,68 @@ "node": ">= 8" } }, + "node_modules/winston": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", + "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-daily-rotate-file": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz", + "integrity": "sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==", + "dependencies": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "winston": "^3" + } + }, + "node_modules/winston-transport": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", + "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 7416d812e..dc9459735 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.ts", "scripts": { "start": "node build/index.js", - "dev": "ts-node-dev --openssl-legacy-provider -r tsconfig-paths/register src/index.ts", + "dev": "ts-node-dev --openssl-legacy-provider -r tsconfig-paths/register src/index.ts ", "build": "tsc", "lint": "eslint --ext .ts .", "prettier": "prettier --write ." @@ -15,7 +15,9 @@ "dotenv": "^16.1.3", "express": "^5.0.0-beta.1", "mongoose": "^8.0.2", - "warframe-items": "1.1260.121" + "warframe-items": "1.1260.121", + "winston": "^3.11.0", + "winston-daily-rotate-file": "^4.7.1" }, "devDependencies": { "@tsconfig/node20": "^1.0.0", diff --git a/src/app.ts b/src/app.ts index 3ca8bfc88..bacdc926a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,20 +1,21 @@ import express from "express"; -//import { loginRouter } from "./routes/login"; -import { requestLogger, unknownEndpointHandler } from "@/src/middleware/middleware"; +import { unknownEndpointHandler } from "@/src/middleware/middleware"; +import { requestLogger } from "@/src/middleware/morgenMiddleware"; import { apiRouter } from "@/src/routes/api"; //import { testRouter } from "@/src/routes/test"; import { cacheRouter } from "@/src/routes/cache"; import bodyParser from "body-parser"; -import morgan from "morgan"; import { steamPacksController } from "@/src/controllers/misc/steamPacksController"; import { customRouter } from "@/src/routes/custom"; import { dynamicController } from "@/src/routes/dynamic"; import { statsRouter } from "@/src/routes/stats"; import { connectDatabase } from "@/src/services/mongoService"; +import { registerLogFileCreationListener } from "@/src/utils/logger"; +void registerLogFileCreationListener(); void connectDatabase(); const app = express(); @@ -22,7 +23,7 @@ const app = express(); app.use(bodyParser.raw()); app.use(express.json()); app.use(bodyParser.text()); -app.use(morgan("dev")); +app.use(requestLogger); //app.use(requestLogger); app.use("/api", apiRouter); diff --git a/src/controllers/api/findSessionsController.ts b/src/controllers/api/findSessionsController.ts index 9e4da0f54..f69839104 100644 --- a/src/controllers/api/findSessionsController.ts +++ b/src/controllers/api/findSessionsController.ts @@ -1,23 +1,26 @@ import { RequestHandler } from "express"; import { getSession } from "@/src/managers/sessionManager"; +import { logger } from "@/src/utils/logger"; +//TODO: cleanup const findSessionsController: RequestHandler = (_req, res) => { - console.log("FindSession Request:", JSON.parse(_req.body)); + const reqBody = JSON.parse(_req.body); + logger.debug("FindSession Request ", { reqBody }); let req = JSON.parse(_req.body); if (req.id != undefined) { - console.log("Found ID"); + logger.debug("Found ID"); let session = getSession(req.id); if (session) res.json({ queryId: req.queryId, Sessions: session }); else res.json({}); } else if (req.originalSessionId != undefined) { - console.log("Found OriginalSessionID"); + logger.debug("Found OriginalSessionID"); let session = getSession(req.originalSessionId); if (session) res.json({ queryId: req.queryId, Sessions: session }); else res.json({}); } else { - console.log("Found SessionRequest"); + logger.debug("Found SessionRequest"); let session = getSession(_req.body); if (session) res.json({ queryId: req.queryId, Sessions: session }); diff --git a/src/controllers/api/getCreditsController.ts b/src/controllers/api/getCreditsController.ts index a2a2ea6ef..5f86de989 100644 --- a/src/controllers/api/getCreditsController.ts +++ b/src/controllers/api/getCreditsController.ts @@ -5,7 +5,7 @@ import { parseString } from "@/src/helpers/general"; // eslint-disable-next-line @typescript-eslint/no-misused-promises export const getCreditsController: RequestHandler = async (req, res) => { - if (config.infinitePlatinum) { + if (config.infiniteResources) { res.json({ RegularCredits: 999999999, TradesRemaining: 999999999, diff --git a/src/controllers/api/hostSessionController.ts b/src/controllers/api/hostSessionController.ts index c7ac7cb9e..f602503e1 100644 --- a/src/controllers/api/hostSessionController.ts +++ b/src/controllers/api/hostSessionController.ts @@ -1,10 +1,13 @@ import { RequestHandler } from "express"; import { createNewSession } from "@/src/managers/sessionManager"; +import { logger } from "@/src/utils/logger"; +import { ISession } from "@/src/types/session"; -const hostSessionController: RequestHandler = (_req, res) => { - console.log("HostSession Request:", JSON.parse(_req.body)); - let session = createNewSession(JSON.parse(_req.body), _req.query.accountId as string); - console.log("New Session Created: ", session); +const hostSessionController: RequestHandler = (req, res) => { + const hostSessionRequest = JSON.parse(req.body as string) as ISession; + logger.debug("HostSession Request", { hostSessionRequest }); + let session = createNewSession(hostSessionRequest, req.query.accountId as string); + logger.debug(`New Session Created`, { session }); res.json({ sessionId: { $oid: session.sessionId }, rewardSeed: 99999999 }); }; diff --git a/src/controllers/api/joinSessionController.ts b/src/controllers/api/joinSessionController.ts index 3cd6a7e00..7bf6785c5 100644 --- a/src/controllers/api/joinSessionController.ts +++ b/src/controllers/api/joinSessionController.ts @@ -1,8 +1,10 @@ import { RequestHandler } from "express"; import { getSessionByID } from "@/src/managers/sessionManager"; +import { logger } from "@/src/utils/logger"; const joinSessionController: RequestHandler = (_req, res) => { - console.log("JoinSession Request:", JSON.parse(_req.body)); + const reqBody = JSON.parse(_req.body); + logger.debug(`JoinSession Request`, { reqBody }); let req = JSON.parse(_req.body); let session = getSessionByID(req.sessionIds[0]); res.json({ rewardSeed: session?.rewardSeed, sessionId: { $oid: session?.sessionId } }); diff --git a/src/controllers/api/loginController.ts b/src/controllers/api/loginController.ts index e488f0806..3f25182b8 100644 --- a/src/controllers/api/loginController.ts +++ b/src/controllers/api/loginController.ts @@ -8,6 +8,7 @@ import { Account } from "@/src/models/loginModel"; import { createAccount, isCorrectPassword } from "@/src/services/loginService"; import { ILoginResponse } from "@/src/types/loginTypes"; import { DTLS, groups, HUB, IRC, Nonce, NRS, platformCDNs } from "@/static/fixed_responses/login_static"; +import { logger } from "@/src/utils/logger"; // eslint-disable-next-line @typescript-eslint/no-misused-promises const loginController: RequestHandler = async (request, response) => { @@ -30,7 +31,7 @@ const loginController: RequestHandler = async (request, response) => { ConsentNeeded: false, TrackedSettings: [] }); - console.log("creating new account"); + logger.debug("created new account"); // eslint-disable-next-line @typescript-eslint/no-unused-vars const { email, password, ...databaseAccount } = newAccount; const newLoginResponse: ILoginResponse = { diff --git a/src/controllers/api/rerollRandomModController.ts b/src/controllers/api/rerollRandomModController.ts index eabffb2ea..0a3bff220 100644 --- a/src/controllers/api/rerollRandomModController.ts +++ b/src/controllers/api/rerollRandomModController.ts @@ -1,7 +1,8 @@ +import { logger } from "@/src/utils/logger"; import { RequestHandler } from "express"; const rerollRandomModController: RequestHandler = (_req, res) => { - console.log("RerollRandomMod Request:", _req.body.toString("hex").replace(/(.)(.)/g, "$1$2 ")); + logger.debug("RerollRandomMod Request", { info: _req.body.toString("hex").replace(/(.)(.)/g, "$1$2 ") }); res.json({}); }; diff --git a/src/controllers/api/saveLoadout.ts b/src/controllers/api/saveLoadout.ts index 85a88a5d3..7d15593a0 100644 --- a/src/controllers/api/saveLoadout.ts +++ b/src/controllers/api/saveLoadout.ts @@ -3,6 +3,7 @@ import util from "util"; import { ISaveLoadoutRequest } from "@/src/types/saveLoadoutTypes"; import { handleInventoryItemConfigChange } from "@/src/services/saveLoadoutService"; import { parseString } from "@/src/helpers/general"; +import { logger } from "@/src/utils/logger"; // eslint-disable-next-line @typescript-eslint/no-misused-promises export const saveLoadoutController: RequestHandler = async (req, res) => { @@ -24,7 +25,7 @@ export const saveLoadoutController: RequestHandler = async (req, res) => { res.status(200).end(); } catch (error: unknown) { if (error instanceof Error) { - console.log("error in saveLoadoutController", error.message); + logger.error(`error in saveLoadoutController: ${error.message}`); res.status(400).json({ error: error.message }); } else { res.status(400).json({ error: "unknown error" }); diff --git a/src/controllers/api/setBootLocationController.ts b/src/controllers/api/setBootLocationController.ts index a2e745bc0..b469c3490 100644 --- a/src/controllers/api/setBootLocationController.ts +++ b/src/controllers/api/setBootLocationController.ts @@ -1,6 +1,6 @@ +import { logger } from "@/src/utils/logger"; import { Request, Response } from "express"; -export const setBootLocationController = (req: Request, res: Response) => { - console.log("setBootLocationController", req.query); +export const setBootLocationController = (_req: Request, res: Response) => { res.end(); }; diff --git a/src/controllers/api/updateSessionController.ts b/src/controllers/api/updateSessionController.ts index e949d83e8..c6a5f555d 100644 --- a/src/controllers/api/updateSessionController.ts +++ b/src/controllers/api/updateSessionController.ts @@ -1,5 +1,6 @@ import { RequestHandler } from "express"; import { updateSession } from "@/src/managers/sessionManager"; +import { logger } from "@/src/utils/logger"; const updateSessionGetController: RequestHandler = (_req, res) => { res.json({}); diff --git a/src/helpers/general.ts b/src/helpers/general.ts index afc52fd8c..23fb9df69 100644 --- a/src/helpers/general.ts +++ b/src/helpers/general.ts @@ -2,6 +2,13 @@ export const isEmptyObject = (obj: unknown): boolean => { return Boolean(obj && Object.keys(obj).length === 0 && obj.constructor === Object); }; +/* +alternative to isEmptyObject +export const isEmptyObject = (obj: object): boolean => { + return Object.keys(obj).length === 0; +}; +*/ + const isString = (text: unknown): text is string => { return typeof text === "string" || text instanceof String; }; diff --git a/src/index.ts b/src/index.ts index 689fa8545..450a5be5e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import http from "http"; import https from "https"; import fs from "node:fs"; import { app } from "./app"; +import { logger } from "./utils/logger"; //const morgan = require("morgan"); //const bodyParser = require("body-parser"); @@ -12,8 +13,8 @@ const options = { }; // const server = http.createServer(app).listen(80); -http.createServer(app).listen(80, () => console.log("server started on port 80")); -const server = https.createServer(options, app).listen(443, () => console.log("server started on port 443")); +http.createServer(app).listen(80, () => logger.info("cache server started on port 80")); +const server = https.createServer(options, app).listen(443, () => logger.info("game server started on port 443")); // server.keepAliveTimeout = 60 * 1000 + 1000; // server.headersTimeout = 60 * 1000 + 2000; diff --git a/src/managers/sessionManager.ts b/src/managers/sessionManager.ts index e6558d577..1138b3104 100644 --- a/src/managers/sessionManager.ts +++ b/src/managers/sessionManager.ts @@ -1,4 +1,5 @@ import { ISession, IFindSessionRequest } from "@/src/types/session"; +import { logger } from "@/src/utils/logger"; const sessions: ISession[] = []; @@ -43,11 +44,12 @@ function getSessionByID(sessionId: string): ISession | undefined { return sessions.find(session => session.sessionId === sessionId); } +//TODO: proper typings function getSession(sessionIdOrRequest: string | IFindSessionRequest): any[] { if (typeof sessionIdOrRequest === "string") { const session = sessions.find(session => session.sessionId === sessionIdOrRequest); if (session) { - console.log("Found Sessions:", session); + logger.debug("Found Sessions:", { session }); return [ { createdBy: session.creatorId, @@ -65,7 +67,7 @@ function getSession(sessionIdOrRequest: string | IFindSessionRequest): any[] { return false; } } - console.log("Found Matching Sessions:", matchingSessions); + logger.debug("Found Matching Sessions:", { matchingSessions }); return true; }); return matchingSessions.map(session => ({ diff --git a/src/middleware/middleware.ts b/src/middleware/middleware.ts index 1653864a5..92a69de73 100644 --- a/src/middleware/middleware.ts +++ b/src/middleware/middleware.ts @@ -1,16 +1,17 @@ +import { logger } from "@/src/utils/logger"; import { NextFunction, Request, Response } from "express"; const unknownEndpointHandler = (request: Request, response: Response) => { - console.error("[ERROR] Unknown Endpoint", request.url); + logger.error(`unknown endpoint ${request.method} ${request.path}`); response.status(404).json({ error: "endpoint was not found" }); }; -const requestLogger = (request: Request, _response: Response, next: NextFunction) => { - console.log("Method:", request.method); - console.log("Path: ", request.path); - console.log("Body: ", request.body); - console.log("---"); - next(); -}; +// const requestLogger = (request: Request, _response: Response, next: NextFunction) => { +// console.log("Method:", request.method); +// console.log("Path: ", request.path); +// console.log("Body: ", request.body); +// console.log("---"); +// next(); +// }; -export { unknownEndpointHandler, requestLogger }; +export { unknownEndpointHandler }; diff --git a/src/middleware/morgenMiddleware.ts b/src/middleware/morgenMiddleware.ts new file mode 100644 index 000000000..396f39cad --- /dev/null +++ b/src/middleware/morgenMiddleware.ts @@ -0,0 +1,6 @@ +import morgan from "morgan"; +import { logger } from "@/src/utils/logger"; + +export const requestLogger = morgan("dev", { + stream: { write: message => logger.http(message) } +}); diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index e50da9d35..f51063a19 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -16,6 +16,7 @@ import { } from "@/src/types/inventoryTypes/inventoryTypes"; import { IGenericUpdate } from "../types/genericUpdate"; import { IArtifactsRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes"; +import { logger } from "@/src/utils/logger"; export const createInventory = async (accountOwnerId: Types.ObjectId, loadOutPresetId: Types.ObjectId) => { try { @@ -107,7 +108,7 @@ export const updateCurrency = async (price: number, usePremium: boolean, account currencyChanges[path as currencyKeys] = -price; }); - console.log(currencyChanges, "changes"); + logger.debug(`currency changes `, { currencyChanges }); //let changes = {} as keyof currencyKeys; diff --git a/src/services/missionInventoryUpdateService .ts b/src/services/missionInventoryUpdateService .ts index cfee223af..f815627c9 100644 --- a/src/services/missionInventoryUpdateService .ts +++ b/src/services/missionInventoryUpdateService .ts @@ -3,6 +3,7 @@ import { IMissionRewardResponse, IReward, IInventoryFieldType, inventoryFields } import missionsDropTable from "@/static/json/missions-drop-table.json"; import { modNames, relicNames, miscNames, resourceNames, gearNames, blueprintNames } from "@/static/data/items"; import { IMissionInventoryUpdateRequest } from "../types/requestTypes"; +import { logger } from "@/src/utils/logger"; // need reverse engineer rewardSeed, otherwise ingame displayed rotation reward will be different than added to db or displayed on mission end const getRewards = ({ @@ -56,10 +57,10 @@ const getRewards = ({ // { chance: 7.69, name: "Health Restore (Large)", rotation: "C" }, // { chance: 7.69, name: "Vapor Specter Blueprint", rotation: "C" } // ]; - // console.log("Mission rewards:", testDrops); + // logger.debug("Mission rewards:", testDrops); // return formatRewardsToInventoryType(testDrops); - console.log("Mission rewards:", drops); + logger.debug("Mission rewards:", drops); return formatRewardsToInventoryType(drops); }; @@ -238,7 +239,7 @@ const _missionRewardsCheckAllNamings = () => { .filter(reward => !blueprintNames[reward.name]) .filter(reward => !reward.name.includes(" Endo")) .filter(reward => !reward.name.includes(" Credits Cache") && !reward.name.includes("Return: ")); - console.log(tempRewards); + logger.debug(`temp rewards`, { tempRewards }); }; // _missionRewardsCheckAllNamings(); diff --git a/src/services/mongoService.ts b/src/services/mongoService.ts index f9a6a0449..0ef0c82d9 100644 --- a/src/services/mongoService.ts +++ b/src/services/mongoService.ts @@ -1,3 +1,4 @@ +import { logger } from "@/src/utils/logger"; import * as dotenv from "dotenv"; import mongoose from "mongoose"; @@ -11,11 +12,11 @@ if (url === undefined) { const connectDatabase = async () => { try { - await mongoose.connect(url); - console.log("connected to MongoDB"); + await mongoose.connect(`${url}`); + logger.info("connected to MongoDB"); } catch (error: unknown) { if (error instanceof Error) { - console.error("error connecting to MongoDB", error.message); + logger.error(`error connecting to MongoDB ${error.message}`); } } }; diff --git a/src/services/purchaseService.ts b/src/services/purchaseService.ts index caf3375b6..567239a45 100644 --- a/src/services/purchaseService.ts +++ b/src/services/purchaseService.ts @@ -11,6 +11,7 @@ import { updateSlots } from "@/src/services/inventoryService"; import { IPurchaseRequest, IPurchaseResponse, SlotNameToInventoryName, SlotPurchase } from "@/src/types/purchaseTypes"; +import { logger } from "@/src/utils/logger"; export const getStoreItemCategory = (storeItem: string) => { const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/"); @@ -28,10 +29,10 @@ export const getStoreItemTypesCategory = (typesItem: string) => { }; export const handlePurchase = async (purchaseRequest: IPurchaseRequest, accountId: string) => { - console.log(purchaseRequest); + logger.debug("purchase request", purchaseRequest); const storeCategory = getStoreItemCategory(purchaseRequest.PurchaseParams.StoreItem); const internalName = purchaseRequest.PurchaseParams.StoreItem.replace("/StoreItems", ""); - console.log("Store category", storeCategory); + logger.debug(`store category ${storeCategory}`); let inventoryChanges; switch (storeCategory) { @@ -47,9 +48,10 @@ export const handlePurchase = async (purchaseRequest: IPurchaseRequest, accountI case "Boosters": inventoryChanges = await handleBoostersPurchase(internalName, accountId); break; - default: - throw new Error(`unknown store category: ${storeCategory} not implemented or new`); + const errorMessage = `unknown store category: ${storeCategory} not implemented or new`; + logger.error(errorMessage); + throw new Error(errorMessage); } if (!inventoryChanges) throw new Error("purchase response was undefined"); @@ -86,32 +88,26 @@ export const slotPurchaseNameToSlotName: SlotPurchase = { // // new frame = slots -1 // // number of frames = extra - slots + 2 const handleSlotPurchase = async (slotPurchaseNameFull: string, accountId: string) => { - console.log("slot name", slotPurchaseNameFull); + logger.debug(`slot name ${slotPurchaseNameFull}`); const slotPurchaseName = parseSlotPurchaseName( slotPurchaseNameFull.substring(slotPurchaseNameFull.lastIndexOf("/") + 1) ); - console.log(slotPurchaseName, "slot purchase name"); + logger.debug(`slot purchase name ${slotPurchaseName}`); - await updateSlots( - accountId, - slotPurchaseNameToSlotName[slotPurchaseName].name, - slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase, - slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase - ); + const slotName = slotPurchaseNameToSlotName[slotPurchaseName].name; + const slotsPerPurchase = slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase; - console.log( - slotPurchaseNameToSlotName[slotPurchaseName].name, - slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase, - "slots added" - ); + await updateSlots(accountId, slotName, slotsPerPurchase, slotsPerPurchase); + + logger.debug(`added ${slotsPerPurchase} slot ${slotName}`); return { InventoryChanges: { - [slotPurchaseNameToSlotName[slotPurchaseName].name]: { + [slotName]: { count: 0, platinum: 1, - Slots: slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase, - Extra: slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase + Slots: slotsPerPurchase, + Extra: slotsPerPurchase } } }; @@ -136,7 +132,7 @@ const handlePowersuitPurchase = async (powersuitName: string, accountId: string) const mechSuit = await addMechSuit(powersuitName, accountId); await updateSlots(accountId, SlotNameToInventoryName.MECHSUIT, 0, 1); - console.log("mech suit", mechSuit); + logger.debug("mech suit", mechSuit); return { InventoryChanges: { @@ -168,7 +164,7 @@ const handlePowersuitPurchase = async (powersuitName: string, accountId: string) //TODO: change to getInventory, apply changes then save at the end const handleTypesPurchase = async (typesName: string, accountId: string) => { const typeCategory = getStoreItemTypesCategory(typesName); - console.log("type category", typeCategory); + logger.debug(`type category ${typeCategory}`); switch (typeCategory) { case "SuitCustomizations": return await handleSuitCustomizationsPurchase(typesName, accountId); diff --git a/src/services/saveLoadoutService.ts b/src/services/saveLoadoutService.ts index 597339316..e8f7bc5d3 100644 --- a/src/services/saveLoadoutService.ts +++ b/src/services/saveLoadoutService.ts @@ -10,6 +10,7 @@ import { getInventory } from "@/src/services/inventoryService"; import { IOid } from "@/src/types/commonTypes"; import { Types } from "mongoose"; import { isEmptyObject } from "@/src/helpers/general"; +import { logger } from "@/src/utils/logger"; //TODO: setup default items on account creation or like originally in giveStartingItems.php @@ -38,10 +39,10 @@ export const handleInventoryItemConfigChange = async ( case "AdultOperatorLoadOuts": { const operatorConfig = equipment as IOperatorConfigEntry; const operatorLoadout = inventory[equipmentName]; - console.log("operator loadout received", equipmentName, operatorConfig); + logger.debug(`operator loadout received ${equipmentName} `, operatorConfig); // all non-empty entries are one loadout slot for (const [loadoutId, loadoutConfig] of Object.entries(operatorConfig)) { - // console.log("loadoutId", loadoutId, "loadoutconfig", loadoutConfig); + logger.debug(`loadoutId ${loadoutId} loadoutConfig`, { config: loadoutConfig }); const loadout = operatorLoadout.find(loadout => loadout._id?.toString() === loadoutId); // if no config with this id exists, create a new one @@ -58,7 +59,7 @@ export const handleInventoryItemConfigChange = async ( break; } case "LoadOuts": { - console.log("loadout received"); + logger.debug("loadout received"); const loadout = await LoadoutModel.findOne({ loadoutOwnerId: accountId }); if (!loadout) { throw new Error("loadout not found"); @@ -126,7 +127,7 @@ export const handleInventoryItemConfigChange = async ( case "DrifterMelee": case "Sentinels": case "Horses": { - console.log("general Item config saved", equipmentName, equipment); + logger.debug(`general Item config saved of type ${equipmentName}`, { config: equipment }); const itemEntries = equipment as IItemEntry; for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) { @@ -153,7 +154,7 @@ export const handleInventoryItemConfigChange = async ( break; } default: { - console.log("category not implemented", equipmentName, equipment); + logger.error(`category not implemented: ${equipmentName}`, { config: equipment }); } //case "OperatorAmps": // case "SentinelWeapons": diff --git a/src/types/purchaseTypes.ts b/src/types/purchaseTypes.ts index bbbf8c891..c6b5d6488 100644 --- a/src/types/purchaseTypes.ts +++ b/src/types/purchaseTypes.ts @@ -1,4 +1,3 @@ -import { slotPurchaseNameToSlotName } from "@/src/services/purchaseService"; import { ISuitClient } from "@/src/types/inventoryTypes/SuitTypes"; import { IFlavourItem } from "@/src/types/inventoryTypes/inventoryTypes"; import { IWeaponClient } from "@/src/types/inventoryTypes/weaponTypes"; diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 000000000..c1bfbc696 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,113 @@ +import { createLogger, format, transports, Logger, LeveledLogMethod, addColors } from "winston"; +import "winston-daily-rotate-file"; +import * as dotenv from "dotenv"; +import * as util from "util"; +import { isEmptyObject } from "@/src/helpers/general"; + +dotenv.config(); + +// const combineMessageAndSplat = () => { +// return { +// transform: (info: any, _opts: any) => { +// //combine message and args if any +// info.message = util.format(info.message, ...(info[Symbol.for("splat")] || [])); +// return info; +// } +// }; +// }; + +// const alwaysAddMetadata = () => { +// return { +// transform(info: any) { +// if (info[Symbol.for("splat")] === undefined) return info; +// info.meta = info[Symbol.for("splat")]; //[0].meta; +// return info; +// } +// }; +// }; + +//TODO: in production utils.inspect might be slowing down requests see utils.inspect +const consolelogFormat = format.printf(info => { + if (!isEmptyObject(info.metadata)) { + const metadataString = util.inspect(info.metadata, { + showHidden: false, + depth: null, + colors: true + }); + + return `${info.timestamp} [${info.version}] ${info.level}: ${info.message} ${metadataString}`; + } + return `${info.timestamp} [${info.version}] ${info.level}: ${info.message}`; +}); + +const fileFormat = format.combine( + format.uncolorize(), + //combineMessageAndSplat(), + format.timestamp(), + format.json() +); + +const errorLog = new transports.DailyRotateFile({ + filename: "logs/error.log", + format: fileFormat, + level: "error", + datePattern: "YYYY-MM-DD" +}); +const combinedLog = new transports.DailyRotateFile({ + filename: "logs/combined.log", + format: fileFormat, + datePattern: "YYYY-MM-DD" +}); + +const consoleLog = new transports.Console({ + format: format.combine( + format.colorize(), + format.timestamp({ format: "YYYY-MM-DDTHH:mm:ss:SSS" }), // uses local timezone + //combineMessageAndSplat(), + //alwaysAddMetadata(), + format.errors({ stack: true }), + format.align(), + format.metadata({ fillExcept: ["message", "level", "timestamp", "version"] }), + consolelogFormat + ) +}); + +const transportOptions = process.env.LOG_FILES === "true" ? [consoleLog, errorLog, combinedLog] : [consoleLog]; + +//possible log levels: { fatal: 0, error: 1, warn: 2, info: 3, http: 4, debug: 5, trace: 6 }, +const logLevels = { + levels: { + fatal: 0, + error: 1, + warn: 2, + info: 3, + http: 4, + debug: 5, + trace: 6 + }, + colors: { + fatal: "red", + error: "red", + warn: "yellow", + info: "green", + http: "green", + debug: "magenta", + trace: "cyan" + } +}; + +export const logger = createLogger({ + levels: logLevels.levels, + level: process.env.LOG_LEVEL, + defaultMeta: { version: process.env.npm_package_version }, + transports: transportOptions +}) as Logger & Record; + +addColors(logLevels.colors); + +export function registerLogFileCreationListener() { + errorLog.on("new", filename => logger.info(`Using error log file: ${filename}`)); + combinedLog.on("new", filename => logger.info(`Using combined log file: ${filename}`)); + errorLog.on("rotate", filename => logger.info(`Rotated error log file: ${filename}`)); + combinedLog.on("rotate", filename => logger.info(`Rotated combined log file: ${filename}`)); +}