From b4563aea06d751323aca23e6a85d1712444a19fa Mon Sep 17 00:00:00 2001 From: Andrew Borley <848217+ajborley@users.noreply.github.com> Date: Wed, 4 Nov 2020 13:31:48 +0000 Subject: [PATCH] feat: Add server-side logging capability (#59) * feat: Add server-side logging capability Contributes to: #43 Signed-off-by: Andrew Borley * fix: Address review comments Addresses initial review comments from @matthew-chirgwin. Contributes to: #43 Signed-off-by: Andrew Borley * fix: Move pino types to devDependencies Contributes to: #43 Signed-off-by: Andrew Borley --- package-lock.json | 304 +++++++++++++++++++++++- package.json | 6 + server/README.md | 1 + server/api/controller.ts | 18 +- server/api/router.ts | 7 +- server/client/router.ts | 9 +- server/config/router.ts | 5 +- server/core/app.ts | 77 ++---- server/log/router.ts | 5 +- server/logging.ts | 98 ++++++++ server/main.ts | 88 ++----- server/mockapi/router.ts | 7 +- server/placeholderFunctionsToReplace.ts | 37 +-- server/serverConfig.ts | 37 ++- server/types.ts | 28 +-- utils/dev_config/mockadmin.config.js | 7 +- utils/dev_config/server.dev.config.js | 6 + 17 files changed, 514 insertions(+), 226 deletions(-) create mode 100644 server/logging.ts diff --git a/package-lock.json b/package-lock.json index b957b2b1..11b67d37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2235,6 +2235,11 @@ "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.0.tgz", "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==" }, + "@hapi/bourne": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", + "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==" + }, "@icons/material": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", @@ -4957,6 +4962,35 @@ "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", "dev": true }, + "@types/pino": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.2.tgz", + "integrity": "sha512-dLKNzFY35feTD92DLFtFY1YPEngQxlfjczK2iEzwtGhh/M2AlTNyxshcYsbstBA6yc8wpTKYNrmjw+NcppE2YQ==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/pino-std-serializers": "*", + "@types/sonic-boom": "*" + } + }, + "@types/pino-http": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/pino-http/-/pino-http-5.0.5.tgz", + "integrity": "sha512-xx8bMUmap1LV0qxzZUlsjE9F5oX3nzoh+rPEtCY8WQgWx6UESbEv4VFwcRLRj6mtACBd0BVcTydcvBppnb6lSg==", + "dev": true, + "requires": { + "@types/pino": "*" + } + }, + "@types/pino-std-serializers": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/pino-std-serializers/-/pino-std-serializers-2.4.1.tgz", + "integrity": "sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/prettier": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz", @@ -5065,6 +5099,15 @@ "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", "dev": true }, + "@types/sonic-boom": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@types/sonic-boom/-/sonic-boom-0.7.0.tgz", + "integrity": "sha512-AfqR0fZMoUXUNwusgXKxcE9DPlHNDHQp6nKYUd4PSRpLobF5CCevSpyTEBcVZreqaWKCnGBr9KI1fHMTttoB7A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -5991,6 +6034,29 @@ "sprintf-js": "~1.0.2" } }, + "args": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", + "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", + "requires": { + "camelcase": "5.0.0", + "chalk": "2.4.2", + "leven": "2.1.0", + "mri": "1.1.4" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + } + } + }, "aria-query": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", @@ -6322,6 +6388,11 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "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==" + }, "autoprefixer": { "version": "9.8.6", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", @@ -9942,6 +10013,11 @@ "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", "dev": true }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" + }, "debug": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", @@ -10001,6 +10077,21 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, + "deep-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-3.0.0.tgz", + "integrity": "sha512-YX2i9XjJ7h5q/aQ/IM9PEwEnDqETAIYbggmdDB3HLTlSgo1CxPsj6pvhPG68rq6SVE0+p+6Ywsm5fTYNrYtBWw==", + "requires": { + "is-obj": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + } + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -11896,8 +11987,7 @@ "fast-json-parse": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==" }, "fast-json-stable-stringify": { "version": "2.1.0", @@ -11910,11 +12000,30 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-redact": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz", + "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==" + }, "fast-safe-stringify": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", - "dev": true + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "requires": { + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } }, "fastest-levenshtein": { "version": "1.0.12", @@ -12190,6 +12299,11 @@ } } }, + "flatstr": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" + }, "flatted": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", @@ -18276,6 +18390,16 @@ } } }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "joycon": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz", + "integrity": "sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ==" + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -20517,6 +20641,11 @@ } } }, + "mri": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", + "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -21654,6 +21783,156 @@ "pinkie": "^2.0.0" } }, + "pino": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.7.0.tgz", + "integrity": "sha512-vPXJ4P9rWCwzlTJt+f0Ni4THc3DWyt8iDDCO4edQ8narTu6hnpzdXu8FqeSJCGndl1W6lfbYQUQihUO54y66Lw==", + "requires": { + "fast-redact": "^3.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^2.4.2", + "quick-format-unescaped": "^4.0.1", + "sonic-boom": "^1.0.2" + } + }, + "pino-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pino-filter/-/pino-filter-1.0.0.tgz", + "integrity": "sha512-V+yweOTIkbjSrTFZ92lLeoqvz/DAkKx+oSycnlhXIFLcExz9eBwHO5NLbEEgpZYyrEVKIDrR+G3ase866CI6JA==", + "requires": { + "deep-assign": "^3.0.0", + "fast-json-parse": "^1.0.3", + "pump": "^3.0.0", + "split2": "^3.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } + }, + "pino-http": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-5.3.0.tgz", + "integrity": "sha512-aV4e7L8ez2MCa1qsuuliKYX5CDJug3LjW8oht+r4H4+fcf7ZvxPOppTs7P9dNHccF8k8oqhOcU/myiP4GvzJiA==", + "requires": { + "fast-url-parser": "^1.1.3", + "pino": "^6.0.0", + "pino-std-serializers": "^2.4.0" + } + }, + "pino-pretty": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-4.3.0.tgz", + "integrity": "sha512-uEc9SUCCGVEs0goZvyznKXBHtI1PNjGgqHviJHxOCEFEWZN6Z/IQKv5pO9gSdm/b+WfX+/dfheWhtZUyScqjlQ==", + "requires": { + "@hapi/bourne": "^2.0.0", + "args": "^5.0.1", + "chalk": "^4.0.0", + "dateformat": "^3.0.3", + "fast-safe-stringify": "^2.0.7", + "jmespath": "^0.15.0", + "joycon": "^2.2.5", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "split2": "^3.1.1", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pino-std-serializers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.5.0.tgz", + "integrity": "sha512-wXqbqSrIhE58TdrxxlfLwU9eDhrzppQDvGhBEr1gYbzzM4KKo3Y63gSjiDXRKLVS2UOXdPNR2v+KnQgNrs+xUg==" + }, "pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", @@ -22788,6 +23067,11 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, + "quick-format-unescaped": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz", + "integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A==" + }, "quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -25115,6 +25399,15 @@ } } }, + "sonic-boom": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.3.0.tgz", + "integrity": "sha512-4nX6OYvOYr6R76xfQKi6cZpTO3YSWe/vd+QdIfoH0lBy0MnPkeAbb2rRWgmgADkXUeCKPwO1FZAKlAVWAadELw==", + "requires": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -26187,8 +26480,7 @@ "strip-json-comments": { "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 + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "style-loader": { "version": "1.3.0", diff --git a/package.json b/package.json index fe572fc8..eeedb172 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,10 @@ "mini-css-extract-plugin": "^0.9.0", "optimize-css-assets-webpack-plugin": "^5.0.3", "react": "^16.13.1", + "pino": "^6.7.0", + "pino-filter": "^1.0.0", + "pino-http": "^5.3.0", + "pino-pretty": "^4.3.0", "sass": "^1.26.10", "subscriptions-transport-ws": "^0.9.18", "terser-webpack-plugin": "^3.0.7", @@ -74,6 +78,8 @@ "@types/express": "^4.17.8", "@types/jest": "^26.0.14", "@types/node": "^14.11.2", + "@types/pino": "^6.3.2", + "@types/pino-http": "^5.0.5", "@types/supertest": "^2.0.10", "@typescript-eslint/eslint-plugin": "^4.2.0", "@typescript-eslint/parser": "^4.2.0", diff --git a/server/README.md b/server/README.md index de0bbb40..49cb3489 100644 --- a/server/README.md +++ b/server/README.md @@ -9,6 +9,7 @@ This directory contains all server code for the Strimzi UI - ie code which is re - [`log`](./log/README.md) - module that handles client logging events. - [`mockapi`](./mockapi/README.md) - handlers for emulating a real instance of `Strimzi-admin` in dev and test scenarios. Also allows the configuration of the server to be changed to enable test scenarios. - [`test`](./test/README.md) - common test code and helpers for the UI server. +- `logging.ts` - logging handling module. Uses the logging configuration from the server's configuration to create the `pino` and `pino-http` loggers, and extends the Logger object with entry and exit tracing methods. - `main.ts` - the build entry point for the production UI server. It bootstraps the server, and owns the creation and management of a node `http`/`https` server (and binding express to it). - `serverConfig.ts` - configuration handling module. If an `configPath` envar is provided, the file specified is used for the server's configuration, else, `server.config.json` in the current working directory will be used. If neither exist, a default config defined in this module will be used. - `types.ts` - custom types and interfaces used in the server code base. diff --git a/server/api/controller.ts b/server/api/controller.ts index df403153..322a5e13 100644 --- a/server/api/controller.ts +++ b/server/api/controller.ts @@ -9,10 +9,10 @@ export const proxyErrorHandler: ( req: strimziUIRequestType, res: strimziUiResponseType ) => void = (err, req, res) => { - const { entry } = res.locals.strimziuicontext.loggers; - const { exit, debug } = entry('proxyErrorHandler', req.url, err.message); - debug(`Error occurred during proxy`, err); - exit(500); + res.locals.strimziuicontext.logger.debug( + { err }, + `Error occurred whilst proxying request '${req.url}'. ${err.message}` + ); res.sendStatus(500); }; @@ -21,9 +21,9 @@ export const proxyStartHandler: ( req: strimziUIRequestType, res: strimziUiResponseType ) => void = (_, req, res) => { - const { entry } = res.locals.strimziuicontext.loggers; - const { exit } = entry('proxyStartHandler'); - exit(`Starting proxy of request '${req.url}' to the backend api`); + res.locals.strimziuicontext.logger.debug( + `Proxying request '${req.url}' to the backend api` + ); }; export const proxyCompleteHandler: ( @@ -34,9 +34,7 @@ export const proxyCompleteHandler: ( req: strimziUIRequestType, res: strimziUiResponseType ) => void = ({ statusCode, statusMessage }, req, res) => { - const { entry } = res.locals.strimziuicontext.loggers; - const { exit } = entry('proxyCompleteHandler'); - exit( + res.locals.strimziuicontext.logger.debug( `Response from backend api for request '${req.url}' : ${statusCode} - ${statusMessage}` ); }; diff --git a/server/api/router.ts b/server/api/router.ts index 839bb270..e4ba1d07 100644 --- a/server/api/router.ts +++ b/server/api/router.ts @@ -16,10 +16,9 @@ const moduleName = 'api'; export const ApiModule: UIServerModule = { moduleName, - addModule: (logGenerator, authFn, serverConfig) => { - const { entry } = logGenerator(moduleName); + addModule: (logger, authFn, serverConfig) => { const { proxy } = serverConfig; - const { debug, exit } = entry('addModule', proxy); + const { exit } = logger.entry('addModule', proxy); const { hostname, port, contextRoot, transport } = proxy; const { cert, minTLS } = transport; @@ -31,7 +30,7 @@ export const ApiModule: UIServerModule = { secure: cert ? true : false, }; - debug(`api proxy configuration`, JSON.stringify(proxyConfig)); + logger.debug({ proxyConfig }, `api proxy configuration`); const routerForModule = express.Router(); const backendProxy = createProxyServer(proxyConfig); diff --git a/server/client/router.ts b/server/client/router.ts index c9a73620..50a6395c 100644 --- a/server/client/router.ts +++ b/server/client/router.ts @@ -11,10 +11,9 @@ const moduleName = 'client'; export const ClientModule: UIServerModule = { moduleName, - addModule: (logGenerator, authFn, serverConfig) => { + addModule: (logger, authFn, serverConfig) => { const { publicDir } = serverConfig.client.configOverrides; - const { entry } = logGenerator(moduleName); - const { debug, exit } = entry('addModule', publicDir); + const { exit } = logger.entry('addModule', publicDir); const routerForModule = express.Router(); const { @@ -24,10 +23,10 @@ export const ClientModule: UIServerModule = { hasIndexFile, } = getFiles(publicDir); - debug( + logger.debug( `Client is hosting ${totalNumberOfFiles} static files, ${protectedFiles.length} of which are protected and require authentication` ); - debug(`Client has index.html to serve? ${hasIndexFile}`); + logger.debug(`Client has index.html to serve? ${hasIndexFile}`); // add the auth middleware to all non public files protectedFiles.forEach((file) => routerForModule.get(`${file}`, authFn)); diff --git a/server/config/router.ts b/server/config/router.ts index 225136bb..3313ad8f 100644 --- a/server/config/router.ts +++ b/server/config/router.ts @@ -9,9 +9,8 @@ const moduleName = 'config'; export const ConfigModule: UIServerModule = { moduleName, - addModule: (logGenerator, authFn) => { - const { entry } = logGenerator(moduleName); - const { exit } = entry('addModule'); + addModule: (logger, authFn) => { + const { exit } = logger.entry('addModule'); const routerForModule = express.Router(); // implementation to follow diff --git a/server/core/app.ts b/server/core/app.ts index 7957a7db..d1eba1e0 100644 --- a/server/core/app.ts +++ b/server/core/app.ts @@ -4,26 +4,28 @@ */ import express from 'express'; import helmet from 'helmet'; -import { randomBytes } from 'crypto'; import * as availableModules from './modules'; import { serverConfig, UIServerModule } from 'types'; +import { authFunction } from 'placeholderFunctionsToReplace'; import { - generateLoggers, - log, - authFunction, -} from 'placeholderFunctionsToReplace'; - -const STRIMZI_UI_REQUEST_ID_HEADER = 'x-strimzi-ui-request'; + generateLogger, + generateHttpLogger, + STRIMZI_UI_REQUEST_ID_HEADER, +} from 'logging'; export const returnExpress: ( serverName: string, getConfig: () => serverConfig ) => express.Application = (serverName, getConfig) => { + const logger = generateLogger('core'); const app = express(); // add helmet middleware app.use(helmet()); + // add pino-http middleware + app.use(generateHttpLogger()); + // for each module, call the function to add it to the routing table const routingTable = Object.values(availableModules).reduce( ( @@ -33,26 +35,14 @@ export const returnExpress: ( >, { moduleName, addModule }: UIServerModule ) => { - log( - serverName, - 'startup', - 'core', - 'moduleMount', - `Mounting module '${moduleName}'` - ); + logger.info(`Mounting module '${moduleName}'`); const config = getConfig(); const { mountPoint, routerForModule } = addModule( - (moduleName) => generateLoggers(serverName, moduleName, 'startup'), + generateLogger(moduleName), authFunction(config.authentication), config ); - log( - serverName, - 'startup', - 'core', - 'moduleMount', - `Mounted module '${moduleName}' on '${mountPoint}'` - ); + logger.info(`Mounted module '${moduleName}' on '${mountPoint}'`); return { ...acc, [moduleName]: { mountPoint, routerForModule } }; }, {} @@ -60,51 +50,34 @@ export const returnExpress: ( // before all handlers, add context and request start/end handlers app.all('*', (req, res, next) => { - // add id to request for use downstream - if (!req.headers[STRIMZI_UI_REQUEST_ID_HEADER]) { - req.headers[STRIMZI_UI_REQUEST_ID_HEADER] = randomBytes(8).toString( - 'hex' - ); - } - const requestID = req.headers[STRIMZI_UI_REQUEST_ID_HEADER] as string; - // and make sure the response has the header - res.setHeader(STRIMZI_UI_REQUEST_ID_HEADER, requestID); - // create a 'context' for this request, containing config, a request ID, and loggers. Available to handlers via `res.locals.strimziuicontext` + // log start of request (end of request is automatically logged) + req.log.debug('Request received'); + // make sure the response has the requestID header (set via the pino-http middleware) + res.setHeader(STRIMZI_UI_REQUEST_ID_HEADER, req.id as string); + + // create a 'context' for this request, containing config and the request ID. Available to handlers via `res.locals.strimziuicontext` res.locals.strimziuicontext = { config: getConfig(), - requestID, + requestID: req.id, }; - // set up loggers for start/end of request - const { event } = generateLoggers(serverName, 'core', requestID); - event(`requestStart`, `${req.method} of ${req.url} starting`); - res.once('finish', () => { - event( - `requestEnd`, - `${req.method} of ${req.url} complete RC: ${res.statusCode}` - ); - }); next(); }); Object.entries(routingTable).forEach( ([moduleName, { mountPoint, routerForModule }]) => app.use(`${mountPoint}`, (req, res, next) => { - // add loggers for this module + // add logger for this module res.locals.strimziuicontext = { ...res.locals.strimziuicontext, - loggers: generateLoggers( - serverName, - moduleName, - res.locals.strimziuicontext.requestID - ), + logger: generateLogger(moduleName, req.id as string), }; - const { entry } = res.locals.strimziuicontext.loggers; - const { debug, exit } = entry(`module enabled check`); const isEnabled = res.locals.strimziuicontext.config.modules[moduleName]; - debug(`Enabled?`, isEnabled); - exit(isEnabled); + res.locals.strimziuicontext.logger.debug( + `%s module is ${isEnabled ? '' : 'not '}enabled`, + moduleName + ); isEnabled ? routerForModule(req, res, next) : next(); // if enabled, call the router for the module so it can handle the request. Else, call the next module }) ); diff --git a/server/log/router.ts b/server/log/router.ts index dee8c882..fe4e9fba 100644 --- a/server/log/router.ts +++ b/server/log/router.ts @@ -9,9 +9,8 @@ const moduleName = 'log'; export const LogModule: UIServerModule = { moduleName, - addModule: (logGenerator, authFn) => { - const { entry } = logGenerator(moduleName); - const { exit } = entry('addModule'); + addModule: (logger, authFn) => { + const { exit } = logger.entry('addModule'); const routerForModule = express.Router(); // implementation to follow diff --git a/server/logging.ts b/server/logging.ts new file mode 100644 index 00000000..4b2aaf1a --- /dev/null +++ b/server/logging.ts @@ -0,0 +1,98 @@ +/* + * Copyright Strimzi authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ + +import pinoLogger from 'pino'; +import pinoHttpLogger from 'pino-http'; +import { randomBytes } from 'crypto'; + +import { getServerName } from 'serverConfig'; +import { entryExitLoggerType } from 'types'; + +const STRIMZI_UI_REQUEST_ID_HEADER = 'x-strimzi-ui-request'; + +const serverName = getServerName(); + +let rootLogger = pinoLogger(); + +/** Replaces the rootLogger with a new pinoLogger with the supplied options */ +const updateRootLoggerOptions: ( + loggerOptions: pinoLogger.LoggerOptions, + isUpdate: boolean +) => void = (loggerOptions, isUpdate) => { + rootLogger.info( + { + serverName, + module: 'logging', + loggerOptions, + }, + `Strimzi ui logging options${isUpdate ? ' updated' : ''}` + ); + try { + // Update the root logger with the new options + rootLogger = pinoLogger(loggerOptions); + } catch (err) { + rootLogger.error( + { + serverName, + module: 'logging', + loggerOptions, + err, + }, + `Failed to configure logging options: ${err.message}` + ); + } +}; + +/** Generate an entryExitLogger */ +const generateLogger: ( + module: string, + requestID?: string +) => entryExitLoggerType = (module, requestID) => { + const logger = rootLogger.child({ + serverName, + module, + requestID, + }); + + const entryExitLogger = logger; + entryExitLogger.entry = (fnName, ...params) => { + logger.trace({ fnName, params }, 'entry'); + return { + exit: (returns) => { + logger.trace({ fnName, returns }, 'exit'); + return returns; // return params so you can do `return exit(.....)` + }, + }; + }; + + return entryExitLogger as entryExitLoggerType; +}; + +/** Generate a pino-http HttpLogger */ +const generateHttpLogger: () => pinoHttpLogger.HttpLogger = () => + pinoHttpLogger({ + logger: rootLogger, + useLevel: 'debug', + genReqId: generateRequestID, + reqCustomProps: () => ({ + serverName, + module: 'core', + }), + }); + +/** Generate or retrieve the request ID used in the pino-http HttpLogger */ +const generateRequestID: (Request) => string = (req) => { + if (!req.headers[STRIMZI_UI_REQUEST_ID_HEADER]) { + req.headers[STRIMZI_UI_REQUEST_ID_HEADER] = randomBytes(8).toString('hex'); + } + return req.headers[STRIMZI_UI_REQUEST_ID_HEADER] as string; +}; + +export { + generateLogger, + generateHttpLogger, + updateRootLoggerOptions, + STRIMZI_UI_REQUEST_ID_HEADER, +}; diff --git a/server/main.ts b/server/main.ts index ab8fd47d..0883d942 100644 --- a/server/main.ts +++ b/server/main.ts @@ -8,61 +8,39 @@ import https from 'https'; import { loadConfig, watchConfig, getServerName } from 'serverConfig'; import { returnExpress } from 'core'; -import { log } from 'placeholderFunctionsToReplace'; +import { generateLogger, updateRootLoggerOptions } from 'logging'; +let logger = generateLogger('main'); const errorHandler: (err: Error, ...others: unknown[]) => void = ( err, ...others ) => { - log( - serverName, - 'runtime', - 'main', - 'Error', - `Error thrown: ${err.message}`, - err, - others - ); - // trace the error to syserr, but dont kill the process - // eslint-disable-next-line no-console - console.trace(); + logger.error({ err, ...others }, `Error thrown: ${err.message}`); }; -const serverName = getServerName(); - -log( - serverName, - 'startup', - 'main', - 'server starting', - `Strimzi ui server initialising` -); +logger.info('Strimzi ui server initialising'); loadConfig((loadedInitialConfig) => { let config = loadedInitialConfig; - log( - serverName, - 'startup', - 'main', - 'server starting', - `Strimzi ui server starting with config`, - JSON.stringify(config) + logger.info( + { config }, // include the config in the log event JSON + 'Strimzi ui server starting with config' ); + updateRootLoggerOptions(config.logging, false); + logger = generateLogger('main'); watchConfig((latestConfig) => { - log( - serverName, - 'runtime', - 'main', - 'configReload', - `Strimzi ui server configuration changing to for future requests:`, - JSON.stringify(latestConfig) - ); config = latestConfig; - }); // load config and update config value + logger.info( + { config }, // include the updated config in the log event JSON + 'Strimzi ui server configuration update' + ); + updateRootLoggerOptions(config.logging, true); + logger = generateLogger('main'); + }, logger); // load config and update config value - const expressAppForServer = returnExpress(serverName, () => config); + const expressAppForServer = returnExpress(getServerName(), () => config); const { cert, key, ciphers, minTLS } = config.client.transport; let server; @@ -70,13 +48,7 @@ loadConfig((loadedInitialConfig) => { if (cert && key) { isServerSecure = true; - log( - serverName, - 'startup', - 'main', - 'server starting', - `Strimzi ui server will server via HTTPS` - ); + logger.info('Strimzi ui server will serve via HTTPS'); const httpsConfig = { key, cert, @@ -85,22 +57,12 @@ loadConfig((loadedInitialConfig) => { }; server = https.createServer(httpsConfig, expressAppForServer); } else { - log( - serverName, - 'startup', - 'main', - 'server starting', - `Strimzi ui server will server via HTTP` - ); + logger.info('Strimzi ui server will serve via HTTP'); server = http.createServer(expressAppForServer); } const instance = server.listen(config.port, config.hostname, () => - log( - serverName, - 'startup', - 'main', - 'server ready', + logger.info( `Strimzi ui server ready at http${isServerSecure ? 's' : ''}://${ config.hostname }:${config.port}` @@ -109,19 +71,13 @@ loadConfig((loadedInitialConfig) => { const shutdown = (server) => () => server.close(() => { - log( - serverName, - 'teardown', - 'main', - 'server closing', - `Strimzi ui server closed` - ); + logger.info('Strimzi ui server closed'); process.exit(0); }); process.on('SIGTERM', shutdown(instance)); process.on('SIGINT', shutdown(instance)); -}); +}, logger); // catch errors gracefully process.on('uncaughtException', errorHandler); diff --git a/server/mockapi/router.ts b/server/mockapi/router.ts index 302ff194..90145abd 100644 --- a/server/mockapi/router.ts +++ b/server/mockapi/router.ts @@ -9,14 +9,13 @@ const moduleName = 'mockapi'; export const MockApiModule: UIServerModule = { moduleName, - addModule: (logGenerator) => { - const { entry } = logGenerator(moduleName); - const { exit } = entry('addModule'); + addModule: (logger) => { + const { exit } = logger.entry('addModule'); const routerForModule = express.Router(); // endpoint used for test purposes routerForModule.get('/test', (_, res) => { - const { entry } = res.locals.strimziuicontext.loggers; + const { entry } = res.locals.strimziuicontext.logger; const { exit } = entry('`/test` handler'); res.setHeader('x-strimzi-ui-module', moduleName); res.sendStatus(418); diff --git a/server/placeholderFunctionsToReplace.ts b/server/placeholderFunctionsToReplace.ts index 35a0ef24..459e5948 100644 --- a/server/placeholderFunctionsToReplace.ts +++ b/server/placeholderFunctionsToReplace.ts @@ -5,7 +5,7 @@ // placeholder functions - to be replaced by actual implementation later import express from 'express'; -import { createLogger, authenticationConfigType } from 'types'; +import { authenticationConfigType } from 'types'; // https://github.com/orgs/strimzi/projects/2#card-44265081 // function which returns a piece of express middleware for a given auth strategy @@ -26,37 +26,4 @@ const authFunction: ( } }; -//https://github.com/orgs/strimzi/projects/2#card-46109274 -const log: ( - prefix: string, - requestId: string, - messageSource: string, - handler: string, - msg: string, - ...params: unknown[] -) => void = (prefix, requestId, messageSource, handler, msg, ...params) => - console.log( - `${prefix} : ${new Date()} ${requestId} - ${messageSource} - ${handler} - ${msg} ${params.reduce( - (acc, param) => `- ${acc} ${param}`, - '' - )}` - ); - -//https://github.com/orgs/strimzi/projects/2#card-46109274 -const generateLoggers: createLogger = (prefix, moduleName, requestID) => ({ - entry: (fnName, ...params) => { - log(prefix, requestID, moduleName, fnName, `entry`, ...params); - return { - exit: (params) => { - log(prefix, requestID, moduleName, fnName, 'exit', params); - return params; // return params so you could do return exit(.....) - }, - debug: (msg, ...params) => - log(prefix, requestID, moduleName, fnName, `debug: ${msg}`, ...params), // entry logs and returns exit/debug functions - }; - }, - event: (eventName, msg, ...params) => - log(prefix, requestID, moduleName, eventName, msg, ...params), -}); - -export { generateLoggers, log, authFunction }; +export { authFunction }; diff --git a/server/serverConfig.ts b/server/serverConfig.ts index 9623bf32..41adc61a 100644 --- a/server/serverConfig.ts +++ b/server/serverConfig.ts @@ -7,8 +7,11 @@ import { existsSync, watch } from 'fs'; import { resolve } from 'path'; import merge from 'lodash.merge'; -import { log } from 'placeholderFunctionsToReplace'; -import { serverConfig, supportedAuthenticationStrategyTypes } from 'types'; +import { + serverConfig, + supportedAuthenticationStrategyTypes, + loggerType, +} from 'types'; /** Out of the box when built by webpack, it replaces `require` with it's own version (`__webpack_require__`), which requires static paths. As we use require to load a config from an envvar, we need the node require function (`__non_webpack_require__`, as called by webpack). Thus, check if we are in a webpack built environment (I.e `__non_webpack_require__` is defined), and if so, use it, else use `require` (which will be the normal node require, used via ts-node etc) */ /* eslint-disable no-undef */ @@ -42,7 +45,7 @@ const defaultConfig: serverConfig = { port: 9080, transport: {}, }, - logging: true, + logging: {}, hostname: '0.0.0.0', port: 3000, }; @@ -58,19 +61,14 @@ const configFileExists = existsSync(pathToConfigFile); export const getServerName: () => string = () => process.env.serverName || 'Strimzi-ui server'; -export const loadConfig: (callback: (config: serverConfig) => void) => void = ( - callback -) => { +export const loadConfig: ( + callback: (config: serverConfig) => void, + logger: loggerType +) => void = (callback, logger) => { let config = merge({}, defaultConfig); if (configFileExists) { - log( - getServerName(), - 'runtime', - 'serverConfig', - 'loadConfig', - `Using config file '${pathToConfigFile}'` - ); + logger.info(`Using config file '${pathToConfigFile}'`); delete requireForConfigLoad.cache[ requireForConfigLoad.resolve(pathToConfigFile) @@ -81,11 +79,7 @@ export const loadConfig: (callback: (config: serverConfig) => void) => void = ( // merge parsed with core/std config config = merge(config, loadedConfig); } else { - log( - getServerName(), - 'runtime', - 'serverConfig', - 'Error', + logger.error( `The file specified config file '${pathToConfigFile}' was not found. Will fallback to default config` ); } @@ -93,11 +87,12 @@ export const loadConfig: (callback: (config: serverConfig) => void) => void = ( }; export const watchConfig: ( - callbackOnConfigChange: (newConfig: serverConfig) => void -) => void = (callbackOnConfigChange) => + callbackOnConfigChange: (newConfig: serverConfig) => void, + logger: loggerType +) => void = (callbackOnConfigChange, logger) => configFileExists && watch( pathToConfigFile, undefined, - (evt) => evt === 'change' && loadConfig(callbackOnConfigChange) + (evt) => evt === 'change' && loadConfig(callbackOnConfigChange, logger) ); diff --git a/server/types.ts b/server/types.ts index 57bcd5e0..59cee6bd 100644 --- a/server/types.ts +++ b/server/types.ts @@ -4,6 +4,7 @@ */ import express from 'express'; import { SecureVersion } from 'tls'; +import { Logger, LoggerOptions } from 'pino'; export type supportedAuthenticationStrategyTypes = 'none' | 'scram' | 'oauth'; @@ -70,7 +71,7 @@ export type serverConfig = { /** feature flag configuration overrides (for both client and server) */ featureFlags: featureFlagsConfigType; /** logging configuration */ - logging: boolean; + logging: LoggerOptions; /** module configuration */ modules: moduleConfigType; /** proxy (Strimzi-admin) configuration options */ @@ -81,24 +82,19 @@ export type serverConfig = { port: number; }; -export interface createLogger { - /** function which returns a configured logger with the provided values baked into it */ - (prefix: string, moduleName: string, requestID: string): loggerType; -} +/** Re-export the pino Logger type */ +export type loggerType = Logger; -type loggerType = { - /** function which logs entry into a function. Returns an object containing debug, exit loggers with the given name baked in */ +/** Extend the pino Logger type with entry/exit tracing */ +export type entryExitLoggerType = Logger & { + /** function which logs entry into a function. Returns an object containing an exit loggers with the given name baked in */ entry: ( functionName: string, ...params: Array ) => { - /** called on exit of a function. Returns the parameter provided (enabling return exit('foobar');) */ - exit: (params: T) => T; - /** debug level trace handler */ - debug: (msg: string, ...params: Array) => void; + /** called on exit of a function. Returns the parameter provided (enabling `return exit('foobar');`) */ + exit: (returns: T) => T; }; - /** general event handler */ - event: (eventName: string, msg: string, ...params: Array) => void; }; export type strimziUIContextType = { @@ -106,14 +102,14 @@ export type strimziUIContextType = { config: serverConfig; /** the unique id for this request */ requestID: string; - /** an logger object containing pre configured loggers to use for the life of this request */ - loggers: loggerType; + /** a pre-configured logger object to use for the life of this request */ + logger: entryExitLoggerType; }; interface addModule { /** function called to add a module to the UI server */ ( - mountLogger: (moduleName: string) => loggerType, + mountLogger: entryExitLoggerType, authFunction: expressMiddleware, configAtServerStart: serverConfig ): { diff --git a/utils/dev_config/mockadmin.config.js b/utils/dev_config/mockadmin.config.js index 0c3b4430..7876a65e 100644 --- a/utils/dev_config/mockadmin.config.js +++ b/utils/dev_config/mockadmin.config.js @@ -17,6 +17,12 @@ module.exports = { ...mockAdminCertificates, }, }, + logging: { + level: 'debug', + prettyPrint: { + translateTime: true, + }, + }, modules: { api: false, client: false, @@ -26,6 +32,5 @@ module.exports = { proxy: { transport: {}, }, - logging: true, ...mockadminServer, }; diff --git a/utils/dev_config/server.dev.config.js b/utils/dev_config/server.dev.config.js index b22042e3..c1205fba 100644 --- a/utils/dev_config/server.dev.config.js +++ b/utils/dev_config/server.dev.config.js @@ -15,6 +15,12 @@ module.exports = { ...serverCertificates, }, }, + logging: { + level: 'debug', + prettyPrint: { + translateTime: true, + }, + }, modules: { api: true, client: false,