diff --git a/docker-compose.yml b/docker-compose.yml index 933eb022d..503d874b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -74,7 +74,7 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - - SERVICES=ses,secretsmanager + - SERVICES=ses,secretsmanager,cloudwatch,logs - DEBUG=0 - AWS_ACCESS_KEY_ID=test - AWS_SECRET_ACCESS_KEY=test @@ -115,6 +115,7 @@ services: aws --endpoint-url=http://localstack:4566 ses verify-domain-identity --domain imex.online --region ca-central-1 aws --endpoint-url=http://localstack:4566 ses verify-email-identity --email-address noreply@imex.online --region ca-central-1 aws --endpoint-url=http://localstack:4566 secretsmanager create-secret --name CHATTER_PRIVATE_KEY --secret-string file:///tmp/certs/id_rsa + aws --endpoint-url=http://localstack:4566 logs create-log-group --log-group-name development --region ca-central-1 " # Node App: The Main IMEX API node-app: diff --git a/package-lock.json b/package-lock.json index e75f13b42..47fd2ec73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,6 @@ "firebase-admin": "^12.6.0", "graphql": "^16.9.0", "graphql-request": "^6.1.0", - "graylog2": "^0.2.1", "inline-css": "^4.0.2", "intuit-oauth": "^4.1.2", "ioredis": "^5.4.1", @@ -56,6 +55,8 @@ "ssh2-sftp-client": "^10.0.3", "twilio": "^4.23.0", "uuid": "^10.0.0", + "winston": "^3.15.0", + "winston-cloudwatch": "^6.3.0", "xml2js": "^0.6.2", "xmlbuilder2": "^3.1.1" }, @@ -1245,6 +1246,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", "engines": { "node": ">=0.1.90" } @@ -2698,7 +2700,8 @@ "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==" + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" }, "node_modules/@types/uuid": { "version": "9.0.8", @@ -2731,7 +2734,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "optional": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -2944,8 +2946,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "optional": true + ] }, "node_modules/base64id": { "version": "2.0.0", @@ -3083,6 +3084,30 @@ "node": ">= 0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3158,7 +3183,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3174,7 +3198,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4161,11 +4184,19 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "optional": true, "engines": { "node": ">=6" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/express": { "version": "4.21.1", "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", @@ -4326,7 +4357,8 @@ "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==" + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" }, "node_modules/file-uri-to-path": { "version": "2.0.0", @@ -4862,14 +4894,6 @@ "graphql": "14 - 16" } }, - "node_modules/graylog2": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/graylog2/-/graylog2-0.2.1.tgz", - "integrity": "sha512-vjysakwOhrAqMeIvSK0WZcmzKvkpxY6pCfT9QqtdSVAidPFIynuin7adqbdFp9MCCTbTE402WIxvg8cph5OWTA==", - "engines": { - "node": ">=0.6.11" - } - }, "node_modules/gtoken": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.0.1.tgz", @@ -4902,7 +4926,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -5058,6 +5081,26 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5468,6 +5511,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", + "license": "MIT" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -5485,6 +5534,12 @@ "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "license": "MIT" }, + "node_modules/lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", + "license": "MIT" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -5501,6 +5556,18 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, + "node_modules/lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==", + "license": "MIT" + }, + "node_modules/lodash.iserror": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.iserror/-/lodash.iserror-3.1.1.tgz", + "integrity": "sha512-eT/VeNns9hS7vAj1NKW/rRX6b+C3UX3/IAAqEE7aC4Oo2C0iD82NaP5IS4bSlQsammTii4qBJ8G1zd1LTL8hCw==", + "license": "MIT" + }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -5527,9 +5594,10 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, "node_modules/logform": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", - "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz", + "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", + "license": "MIT", "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", @@ -6193,6 +6261,15 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -6536,9 +6613,10 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "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==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", "engines": { "node": ">=10" } @@ -7510,6 +7588,7 @@ "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==", + "license": "MIT", "engines": { "node": ">= 14.0.0" } @@ -7749,39 +7828,76 @@ } }, "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==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz", + "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==", + "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.4.0", + "logform": "^2.6.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" + "winston-transport": "^4.7.0" }, "engines": { "node": ">= 12.0.0" } }, - "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==", + "node_modules/winston-cloudwatch": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/winston-cloudwatch/-/winston-cloudwatch-6.3.0.tgz", + "integrity": "sha512-ffLMBUtas4qCpAyNfA6yUjZUQPepl6XduwHjukxRtI8hSWE4dKmy1k1lcLpyYiglrsgZop+OQYAV/iJJ+7Z94g==", + "license": "MIT", "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", + "async": "^3.1.0", + "chalk": "^4.0.0", + "fast-safe-stringify": "^2.0.7", + "lodash.assign": "^4.2.0", + "lodash.find": "^4.6.0", + "lodash.isempty": "^4.4.0", + "lodash.iserror": "^3.1.1" + }, + "peerDependencies": { + "@aws-sdk/client-cloudwatch-logs": "^3.0.0", + "winston": "^3.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.8.0.tgz", + "integrity": "sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA==", + "license": "MIT", + "dependencies": { + "logform": "^2.6.1", + "readable-stream": "^4.5.2", "triple-beam": "^1.3.0" }, "engines": { "node": ">= 12.0.0" } }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index 057c1d1be..8531ae19a 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "firebase-admin": "^12.6.0", "graphql": "^16.9.0", "graphql-request": "^6.1.0", - "graylog2": "^0.2.1", "inline-css": "^4.0.2", "intuit-oauth": "^4.1.2", "ioredis": "^5.4.1", @@ -66,6 +65,8 @@ "ssh2-sftp-client": "^10.0.3", "twilio": "^4.23.0", "uuid": "^10.0.0", + "winston": "^3.15.0", + "winston-cloudwatch": "^6.3.0", "xml2js": "^0.6.2", "xmlbuilder2": "^3.1.1" }, diff --git a/server/accounting/pbs/pbs-ap-allocations.js b/server/accounting/pbs/pbs-ap-allocations.js index 3b8a20996..269e22c4f 100644 --- a/server/accounting/pbs/pbs-ap-allocations.js +++ b/server/accounting/pbs/pbs-ap-allocations.js @@ -24,7 +24,7 @@ axios.interceptors.request.use((x) => { const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${ x.url } | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`; - console.log(printable); + //console.log(printable); CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data); @@ -35,7 +35,7 @@ axios.interceptors.response.use((x) => { const socket = x.config.socket; const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`; - console.log(printable); + //console.log(printable); CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data); return x; diff --git a/server/accounting/pbs/pbs-job-export.js b/server/accounting/pbs/pbs-job-export.js index b43aa0e3b..34db63a17 100644 --- a/server/accounting/pbs/pbs-job-export.js +++ b/server/accounting/pbs/pbs-job-export.js @@ -26,7 +26,7 @@ axios.interceptors.request.use((x) => { const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${ x.url } | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`; - console.log(printable); + //console.log(printable); CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data); @@ -37,7 +37,7 @@ axios.interceptors.response.use((x) => { const socket = x.config.socket; const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`; - console.log(printable); + //console.log(printable); CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data); return x; diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js index 0dedb4472..8476ce6d4 100644 --- a/server/accounting/qb-receivables-lines.js +++ b/server/accounting/qb-receivables-lines.js @@ -207,7 +207,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes }); if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) { - // console.log("Adding MAPA Line Manually."); + // //console.log("Adding MAPA Line Manually."); const mapaAccountName = responsibilityCenters.defaults.profits.MAPA; const mapaAccount = responsibilityCenters.profits.find((c) => c.name === mapaAccountName); @@ -272,12 +272,12 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes }); } } else { - //console.log("NO MAPA ACCOUNT FOUND!!"); + ////console.log("NO MAPA ACCOUNT FOUND!!"); } } if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) { - // console.log("Adding MASH Line Manually."); + // //console.log("Adding MASH Line Manually."); const mashAccountName = responsibilityCenters.defaults.profits.MASH; @@ -341,7 +341,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes }); } } else { - // console.log("NO MASH ACCOUNT FOUND!!"); + // //console.log("NO MASH ACCOUNT FOUND!!"); } } @@ -795,7 +795,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes : taxCodes[taxAccountCode]; for (let tyCounter = 1; tyCounter <= 5; tyCounter++) { const taxAmount = Dinero(job_totals.totals.us_sales_tax_breakdown[`ty${tyCounter}Tax`]); - console.log(`Tax ${tyCounter}`, taxAmount.toFormat()); + //console.log(`Tax ${tyCounter}`, taxAmount.toFormat()); if (taxAmount.getAmount() > 0) { if (qbo) { InvoiceLineAdd.push({ diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js index c0673cbc5..9b5cf2558 100644 --- a/server/accounting/qbo/qbo-payables.js +++ b/server/accounting/qbo/qbo-payables.js @@ -121,7 +121,7 @@ exports.default = async (req, res) => { res.status(200).json(ret); } catch (error) { - console.log(error); + //console.log(error); logger.log("qbo-payable-create-error", "ERROR", req.user.email, { error: error.message, stack: error.stack diff --git a/server/accounting/qbo/qbo-payments.js b/server/accounting/qbo/qbo-payments.js index 436efca71..b5d884f02 100644 --- a/server/accounting/qbo/qbo-payments.js +++ b/server/accounting/qbo/qbo-payments.js @@ -182,7 +182,7 @@ exports.default = async (req, res) => { res.status(200).json(ret); } catch (error) { - console.log(error); + //console.log(error); logger.log("qbo-payment-create-error", "ERROR", req.user.email, { error: error.message, stack: error.stack diff --git a/server/accounting/qbo/qbo-receivables.js b/server/accounting/qbo/qbo-receivables.js index 51aeade0f..f57c6711a 100644 --- a/server/accounting/qbo/qbo-receivables.js +++ b/server/accounting/qbo/qbo-receivables.js @@ -185,7 +185,7 @@ exports.default = async (req, res) => { error?.response?.data || error?.message }); - console.log(error); + //console.log(error); logger.log("qbo-receivable-create-error", "ERROR", req.user.email, { error: error.message, stack: error.stack @@ -211,7 +211,7 @@ exports.default = async (req, res) => { res.status(200).json(ret); } catch (error) { - console.log(error); + //console.log(error); logger.log("qbo-receivable-create-error", "ERROR", req.user.email, { error: error.message, stack: error.stack diff --git a/server/admin/adminops.js b/server/admin/adminops.js index 7e8b1c676..d134bdcba 100644 --- a/server/admin/adminops.js +++ b/server/admin/adminops.js @@ -9,7 +9,7 @@ require("dotenv").config({ const client = require("../graphql-client/graphql-client").client; exports.createAssociation = async (req, res) => { - logger.log("admin-create-association", "ADMIN", req.user.email, null, { + logger.log("admin-create-association", "debug", req.user.email, null, { request: req.body, ioadmin: true }); @@ -31,7 +31,7 @@ exports.createAssociation = async (req, res) => { res.json(result); }; exports.createShop = async (req, res) => { - logger.log("admin-create-shop", "ADMIN", req.user.email, null, { + logger.log("admin-create-shop", "debug", req.user.email, null, { request: req.body, ioadmin: true }); @@ -64,7 +64,7 @@ exports.createShop = async (req, res) => { } }; exports.updateCounter = async (req, res) => { - logger.log("admin-update-counter", "ADMIN", req.user.email, null, { + logger.log("admin-update-counter", "debug", req.user.email, null, { request: req.body, ioadmin: true }); @@ -91,7 +91,7 @@ exports.updateCounter = async (req, res) => { } }; exports.updateShop = async (req, res) => { - logger.log("admin-update-shop", "ADMIN", req.user.email, null, { + logger.log("admin-update-shop", "debug", req.user.email, null, { request: req.body, ioadmin: true }); diff --git a/server/cdk/cdk-calculate-allocations.js b/server/cdk/cdk-calculate-allocations.js index ddac4ee4c..afe9549ea 100644 --- a/server/cdk/cdk-calculate-allocations.js +++ b/server/cdk/cdk-calculate-allocations.js @@ -22,7 +22,7 @@ exports.defaultRoute = async function (req, res) { const jobData = await QueryJobData(req, req.BearerToken, req.body.jobid); return res.status(200).json({ data: calculateAllocations(req, jobData) }); } catch (error) { - console.log(error); + ////console.log(error); CdkBase.createLogEvent(req, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`); res.status(500).json({ error: `Error encountered in CdkCalculateAllocations. ${error}` }); } @@ -33,7 +33,7 @@ exports.default = async function (socket, jobid) { const jobData = await QueryJobData(socket, "Bearer " + socket.handshake.auth.token, jobid); return calculateAllocations(socket, jobData); } catch (error) { - console.log(error); + ////console.log(error); CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`); } }; @@ -212,7 +212,7 @@ function calculateAllocations(connectionData, job) { }); if (!hasMapaLine && job.job_totals.rates.mapa.total.amount > 0) { - // console.log("Adding MAPA Line Manually."); + // //console.log("Adding MAPA Line Manually."); const mapaAccountName = selectedDmsAllocationConfig.profits.MAPA; const mapaAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === mapaAccountName); @@ -224,7 +224,7 @@ function calculateAllocations(connectionData, job) { Dinero(job.job_totals.rates.mapa.total) ); } else { - //console.log("NO MAPA ACCOUNT FOUND!!"); + ////console.log("NO MAPA ACCOUNT FOUND!!"); } } diff --git a/server/data/arms.js b/server/data/arms.js index ec3d026e8..70ad3be5e 100644 --- a/server/data/arms.js +++ b/server/data/arms.js @@ -820,7 +820,7 @@ exports.default = async (req, res) => { job: JSON.stringify({ id: job.id, ro_number: job.ro_number }), error: error.message || JSON.stringify(error) }); - console.log(error); + //console.log(error); } } catch (error) { logger.log("arms-failed-job", "ERROR", "api", job.shopid, { @@ -886,7 +886,10 @@ exports.default = async (req, res) => { const [result, rawResponse, , rawRequest] = entegralResponse; } catch (error) { fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); - console.log(error); + //console.log(error); + logger.log("arms-error-shop", "ERROR", "api", bodyshop.id, { + error + }); } } catch (error) { //Error at the shop level. diff --git a/server/data/autohouse.js b/server/data/autohouse.js index fa52679df..9b6494e67 100644 --- a/server/data/autohouse.js +++ b/server/data/autohouse.js @@ -206,9 +206,6 @@ const CreateRepairOrderTag = (job, errorCallback) => { const repairCosts = CreateCosts(job); - if (job.ro_number === "QBD209") { - console.log("Stop here"); - } //Calculate detail only lines. const detailAdjustments = job.joblines .filter((jl) => jl.ah_detail_line && jl.mod_lbr_ty) diff --git a/server/firebase/firebase-handler.js b/server/firebase/firebase-handler.js index 2590e6f57..ec20114f9 100644 --- a/server/firebase/firebase-handler.js +++ b/server/firebase/firebase-handler.js @@ -16,7 +16,7 @@ admin.initializeApp({ }); const createUser = async (req, res) => { - logger.log("admin-create-user", "ADMIN", req.user.email, null, { + logger.log("admin-create-user", "debug", req.user.email, null, { request: req.body, ioadmin: true }); @@ -97,7 +97,7 @@ const sendPromanagerWelcomeEmail = (req, res) => { // Validate email before proceeding if (!dbUser.validemail) { - logger.log("admin-send-welcome-email-skip", "ADMIN", req.user.email, null, { + logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, { message: "User email is not valid, skipping email.", email }); @@ -107,7 +107,7 @@ const sendPromanagerWelcomeEmail = (req, res) => { // Check if the user's company is ProManager const convenientCompany = dbUser.associations?.[0]?.bodyshop?.convenient_company; if (convenientCompany !== "promanager") { - logger.log("admin-send-welcome-email-skip", "ADMIN", req.user.email, null, { + logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, { message: 'convenient_company is not "promanager", skipping email.', convenientCompany }); @@ -141,7 +141,7 @@ const sendPromanagerWelcomeEmail = (req, res) => { }) .then(() => { // Log success and return response - logger.log("admin-send-welcome-email", "ADMIN", req.user.email, null, { + logger.log("admin-send-welcome-email", "debug", req.user.email, null, { request: req.body, ioadmin: true, emailSentTo: email @@ -161,7 +161,7 @@ const sendPromanagerWelcomeEmail = (req, res) => { }; const updateUser = (req, res) => { - logger.log("admin-update-user", "ADMIN", req.user.email, null, { + logger.log("admin-update-user", "debug", req.user.email, null, { request: req.body, ioadmin: true }); @@ -184,7 +184,7 @@ const updateUser = (req, res) => { .then((userRecord) => { // See the UserRecord reference doc for the contents of userRecord. - logger.log("admin-update-user-success", "ADMIN", req.user.email, null, { + logger.log("admin-update-user-success", "debug", req.user.email, null, { userRecord, ioadmin: true }); @@ -199,7 +199,7 @@ const updateUser = (req, res) => { }; const getUser = (req, res) => { - logger.log("admin-get-user", "ADMIN", req.user.email, null, { + logger.log("admin-get-user", "debug", req.user.email, null, { request: req.body, ioadmin: true }); @@ -321,7 +321,7 @@ module.exports = { // admin.auth().setCustomUserClaims(uid, { // ioadmin: true, // "https://hasura.io/jwt/claims": { -// "x-hasura-default-role": "admin", +// "x-hasura-default-role": "debug", // "x-hasura-allowed-roles": ["admin"], // "x-hasura-user-id": uid, // }, diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 3c6289b9b..c231f8261 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -78,7 +78,7 @@ exports.lightbox_credentials = async (req, res) => { res.send(response.data); } catch (error) { - console.log(error); + //console.log(error); logger.log("intellipay-lightbox-credentials-error", "ERROR", req.user?.email, null, { error: JSON.stringify(error) }); @@ -109,7 +109,7 @@ exports.payment_refund = async (req, res) => { res.send(response.data); } catch (error) { - console.log(error); + //console.log(error); logger.log("intellipay-refund-error", "ERROR", req.user?.email, null, { error: JSON.stringify(error) }); @@ -143,7 +143,7 @@ exports.generate_payment_url = async (req, res) => { res.send(response.data); } catch (error) { - console.log(error); + //console.log(error); logger.log("intellipay-payment-url-error", "ERROR", req.user?.email, null, { error: JSON.stringify(error) }); diff --git a/server/ioevent/ioevent.js b/server/ioevent/ioevent.js index a657e31d8..5d4223f73 100644 --- a/server/ioevent/ioevent.js +++ b/server/ioevent/ioevent.js @@ -28,10 +28,10 @@ exports.default = async (req, res) => { // } // }); - ioRedis.to(getBodyshopRoom(bodyshopid)).emit("bodyshop-message", { - operationName, - useremail - }); + // ioRedis.to(getBodyshopRoom(bodyshopid)).emit("bodyshop-message", { + // operationName, + // useremail + // }); res.sendStatus(200); } catch (error) { diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js index ca9a74bca..4e123850e 100644 --- a/server/job/job-totals-USA.js +++ b/server/job/job-totals-USA.js @@ -866,8 +866,8 @@ function CalculateTaxesTotals(job, otherTotals) { } }); - console.log("*** Taxable Amounts***"); - console.table(JSON.parse(JSON.stringify(taxableAmounts))); + // console.log("*** Taxable Amounts***"); + // console.table(JSON.parse(JSON.stringify(taxableAmounts))); //For the taxable amounts, figure out which tax type applies. //Then sum up the total of that tax type and then calculate the thresholds. @@ -979,8 +979,8 @@ function CalculateTaxesTotals(job, otherTotals) { } const remainingTaxableAmounts = taxableAmountsByTier; - console.log("*** Taxable Amounts by Tier***"); - console.table(JSON.parse(JSON.stringify(taxableAmountsByTier))); + // console.log("*** Taxable Amounts by Tier***"); + // console.table(JSON.parse(JSON.stringify(taxableAmountsByTier))); Object.keys(taxableAmountsByTier).forEach((taxTierKey) => { try { @@ -1030,8 +1030,8 @@ function CalculateTaxesTotals(job, otherTotals) { } }); - console.log("*** Total Tax by Tier Amounts***"); - console.table(JSON.parse(JSON.stringify(totalTaxByTier))); + // console.log("*** Total Tax by Tier Amounts***"); + // console.table(JSON.parse(JSON.stringify(totalTaxByTier))); stateTax = stateTax .add(totalTaxByTier.ty1Tax) diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 079f54cba..4cd45e13c 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -182,7 +182,7 @@ async function AutoAddAtsIfRequired({ job, client }) { job.joblines[atsLineIndex].act_price = atsAmount; } - console.log(job.jobLines); + //console.log(job.jobLines); } } diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js index ba35eebd9..930933373 100644 --- a/server/opensearch/os-handler.js +++ b/server/opensearch/os-handler.js @@ -148,7 +148,7 @@ async function OpenSearchUpdateHandler(req, res) { }; const response = await osClient.index(payload); - console.log(response.body); + //console.log(response.body); res.status(200).json(response.body); } } catch (error) { @@ -255,7 +255,7 @@ async function OpenSearchSearchHandler(req, res) { res.json(body); } catch (error) { - console.log(error); + //console.log(error); logger.log("os-search-error", "ERROR", req.user.email, null, { error: JSON.stringify(error) }); diff --git a/server/render/canvas-handler.js b/server/render/canvas-handler.js index 010a3bec3..0af2a7f53 100644 --- a/server/render/canvas-handler.js +++ b/server/render/canvas-handler.js @@ -1,18 +1,19 @@ const { createCanvas } = require("canvas"); const Chart = require("chart.js/auto"); +const logger = require("../utils/logger"); const { backgroundColors, borderColors } = require("./canvas-colors"); const { isObject, defaultsDeep, isNumber } = require("lodash"); exports.canvastest = function (req, res) { - console.log("Incoming test request.", req); + //console.log("Incoming test request.", req); res.status(200).send("OK"); }; exports.canvas = function (req, res) { const { w, h, values, keys, override } = req.body; - console.log("Incoming Canvas Request:", w, h, values, keys, override); - + //console.log("Incoming Canvas Request:", w, h, values, keys, override); + logger.log("inbound-canvas-creation", "debug", "jsr", null, { w, h, values, keys, override }); // Gate required values if (!values || !keys) { res.status(400).send("Missing required data"); diff --git a/server/sms/receive.js b/server/sms/receive.js index ad9291a7f..c34147833 100644 --- a/server/sms/receive.js +++ b/server/sms/receive.js @@ -47,7 +47,7 @@ exports.receive = async (req, res) => { //Found a bodyshop - should always happen. if (response.bodyshops[0].conversations.length === 0) { //No conversation Found, create one. - console.log("[SMS Receive] No conversation found. Creating one."); + //console.log("[SMS Receive] No conversation found. Creating one."); newMessage.conversation = { data: { bodyshopid: response.bodyshops[0].id, @@ -56,7 +56,7 @@ exports.receive = async (req, res) => { }; } else if (response.bodyshops[0].conversations.length === 1) { //Just add it to the conversation - console.log("[SMS Receive] Conversation found. Added ID."); + //console.log("[SMS Receive] Conversation found. Added ID."); newMessage.conversationid = response.bodyshops[0].conversations[0].id; } else { //We should never get here. @@ -123,7 +123,14 @@ exports.receive = async (req, res) => { } } } catch (e1) { - console.log("e1", e1); + logger.log("sms-inbound-error", "ERROR", "api", null, { + msid: req.body.SmsMessageSid, + text: req.body.Body, + image: !!req.body.MediaUrl0, + image_path: generateMediaArray(req.body), + messagingServiceSid: req.body.MessagingServiceSid, + error: e1 + }); res.sendStatus(500).json(e1); } } diff --git a/server/utils/logger.js b/server/utils/logger.js index 357dcba3d..46167cab4 100644 --- a/server/utils/logger.js +++ b/server/utils/logger.js @@ -1,25 +1,90 @@ -const graylog2 = require("graylog2"); +const InstanceManager = require("../utils/instanceMgr").default; +const winston = require("winston"); +const WinstonCloudWatch = require("winston-cloudwatch"); +const { isString, isEmpty } = require("lodash"); -const logger = new graylog2.graylog({ - servers: [{ host: "logs.bodyshop.app", port: 12201 }] -}); - -function log(message, type, user, record, object) { - if (type !== "ioevent") - console.log(message, { - type, - env: process.env.NODE_ENV || "development", - user, - record, - ...object +const createLogger = () => { + try { + const region = InstanceManager({ + imex: "ca-central-1", + rome: "us-east-2" }); - logger.log(message, message, { - type, - env: process.env.NODE_ENV || "development", - user, - record, - ...object - }); -} -module.exports = { log }; + const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME); + + const logGroupName = isLocal ? "development" : process.env.CLOUDWATCH_LOG_GROUP; + + const winstonCloudwatchTransportDefaults = { + logGroupName: logGroupName, + awsOptions: { + region + }, + jsonMessage: true + }; + + if (isLocal) { + winstonCloudwatchTransportDefaults.awsOptions.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`; + console.log( + `Winston Transports set to LocalStack end point: ${winstonCloudwatchTransportDefaults.awsOptions.endpoint}` + ); + } + + const getDevelopmentTransports = () => [ + new winston.transports.Console({ + level: "silly", + format: winston.format.combine( + winston.format.colorize(), + winston.format.timestamp(), + winston.format.printf(({ level, message, timestamp, user, record, object }) => { + return `${timestamp} [${level}]: ${message} ${ + user ? `| user: ${JSON.stringify(user)}` : "" + } ${record ? `| record: ${JSON.stringify(record)}` : ""} ${ + object ? `| object: ${JSON.stringify(object, null, 2)}` : "" + }`; + }) + ) + }) + ]; + + const getProductionTransports = () => [ + new WinstonCloudWatch({ + level: "error", + logStreamName: "errors", + ...winstonCloudwatchTransportDefaults + }), + new WinstonCloudWatch({ + level: "warn", + logStreamName: "warn", + ...winstonCloudwatchTransportDefaults + }), + new WinstonCloudWatch({ + level: "debug", + logStreamName: "debug", + ...winstonCloudwatchTransportDefaults + }) + ]; + + const winstonLogger = winston.createLogger({ + format: winston.format.json(), + transports: + process.env.NODE_ENV === "production" + ? getProductionTransports() + : [...getDevelopmentTransports(), ...getProductionTransports()] + }); + + return (message, type, user, record, object) => { + winstonLogger.log({ + level: type.toLowerCase(), + message: message, + user: user, + record: record, + meta: object + }); + }; + } catch (e) { + console.error("Logger setup failed", e); + return () => {}; // Return a no-op function in case of failure + } +}; + +module.exports = { log: createLogger() }; diff --git a/server/web-sockets/redisSocketEvents.js b/server/web-sockets/redisSocketEvents.js index f0c028d17..a19953311 100644 --- a/server/web-sockets/redisSocketEvents.js +++ b/server/web-sockets/redisSocketEvents.js @@ -8,7 +8,7 @@ const redisSocketEvents = ({ }) => { // Logging helper functions const createLogEvent = (socket, level, message) => { - console.log(`[IOREDIS LOG EVENT] - ${socket?.user?.email} - ${socket.id} - ${message}`); + //console.log(`[IOREDIS LOG EVENT] - ${socket?.user?.email} - ${socket.id} - ${message}`); logger.log("ioredis-log-event", level, socket?.user?.email, null, { wsmessage: message }); }; @@ -33,7 +33,7 @@ const redisSocketEvents = ({ next(new Error("Authentication error - no authorization token.")); } } catch (error) { - console.log("Uncaught connection error:::", error); + //console.log("Uncaught connection error:::", error); logger.log("websocket-connection-error", "error", null, null, { ...error }); diff --git a/server/web-sockets/web-socket.js b/server/web-sockets/web-socket.js index c19f77dcb..3140c2e87 100644 --- a/server/web-sockets/web-socket.js +++ b/server/web-sockets/web-socket.js @@ -31,7 +31,7 @@ io.use(function (socket, next) { next(new Error("Authentication error - no authorization token.")); } } catch (error) { - console.log("Uncaught connection error:::", error); + //console.log("Uncaught connection error:::", error); logger.log("websocket-connection-error", "error", null, null, { token: socket.handshake.auth.token, ...error @@ -122,7 +122,7 @@ io.on("connection", (socket) => { function createLogEvent(socket, level, message) { if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) { - console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`); + // console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`); socket.emit("log-event", { timestamp: new Date(), level, @@ -148,7 +148,7 @@ function createLogEvent(socket, level, message) { function createJsonEvent(socket, level, message, json) { if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) { - console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`); + //console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`); socket.emit("log-event", { timestamp: new Date(), level,