diff --git a/package.json b/package.json index 99a0f25..5cf34cb 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "typescript": "~3.8.3", "wait-on": "^4.0.2", "webpack": "^4.42.1", + "winston": "^3.2.1", "zone.js": "~0.10.2" } } diff --git a/src/electron/components/window.ts b/src/electron/components/window.ts index ad08b86..fcdb528 100644 --- a/src/electron/components/window.ts +++ b/src/electron/components/window.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as url from 'url'; import { AbstractService } from '../services/abstract-service'; import { MultiplesService } from '../services/multiples-service'; +import { Logger } from '../utils/logger'; declare const global: any; declare const __static: string; @@ -43,7 +44,7 @@ export class Window { let iconObj = null; if (global.gConfig.isIconAvailable) { const iconPath = path.join(__static, 'icons/icon.png'); - console.debug('Icon Path ', iconPath); + Logger.debug('Icon Path', iconPath); iconObj = nativeImage.createFromPath(iconPath); // Change dock icon on MacOS if (iconObj && process.platform === 'darwin') { @@ -91,12 +92,12 @@ export class Window { const service = new AnyService(); ipcMain.on(service.receptionChannel(), async (event, ...args) => { // Handling input - console.log(`Received [${service.receptionChannel()}] : `, args); + Logger.debug(`Received [${service.receptionChannel()}]`, args); const data = await service.process(...args); // Handling output if (service.sendingChannel()) { - console.log(`Sent [${service.sendingChannel()}] : `, data); + Logger.debug(`Sent [${service.sendingChannel()}]`, data); this._window.webContents.send(service.sendingChannel(), ...data); } }); diff --git a/src/electron/utils/logger.ts b/src/electron/utils/logger.ts new file mode 100644 index 0000000..0cae265 --- /dev/null +++ b/src/electron/utils/logger.ts @@ -0,0 +1,139 @@ +import { app } from 'electron'; +import * as os from 'os'; +import * as path from 'path'; +import * as winston from 'winston'; + +declare const global: any; + +export class Logger { + private static singleton: Logger; + private _logger: winston.Logger; + + public static error(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.error(message, ...meta); + } + + public static warn(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.warn(message, ...meta); + } + + public static info(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.info(message, ...meta); + } + + public static http(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.http(message, ...meta); + } + + public static verbose(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.verbose(message, ...meta); + } + + public static debug(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.debug(message, ...meta); + } + + public static silly(message: string, ...meta: any[]) { + Logger.initSingleton(); + Logger.singleton._logger.silly(message, ...meta); + } + + private static initSingleton() { + if (!Logger.singleton) { + Logger.singleton = new Logger(); + } + } + + private constructor() { + this._logger = winston.createLogger({ + level: 'debug', + format: winston.format.json(), + defaultMeta: { service: 'user-service' }, + transports: [ + new winston.transports.File({ + filename: this.getLogFilename(), + level: global.gConfig.mainLogLevel, + format: winston.format.combine( + winston.format.timestamp(), + this.fileFormat + ), + }), + ], + }); + + // If we're not in production then log also to the `console` with the format: + // `${info.timestamp} ${info.level}: ${info.message} JSON.stringify({ ...rest }) ` + if (global.gConfig.config_id === 'development') { + this._logger.add( + new winston.transports.Console({ + stderrLevels: ['error', 'warn'], + format: winston.format.combine( + winston.format.timestamp(), + this.consoleFormat + ), + }) + ); + } + } + + /** + * Returns log filename with standard path + * In production, returns absolute standard path depending on platform + */ + private getLogFilename() { + let filename = global.gConfig.mainLogFile; + if (global.gConfig.config_id === 'production') { + const appName = app.getName(); + if (process.platform == 'linux') { + filename = `.config/${appName}/${filename}`; + } else if (process.platform == 'darwin') { + filename = `Library/Logs/${appName}/${filename}`; + } else if (process.platform == 'win32') { + filename = `AppData\\Roaming\\${appName}\\${filename}`; + } + } + return path.join(os.homedir(), filename); + } + + /** + * Custom winston file format + * Write JSON logs with given format : + * `${timestamp} ${level} : ${info.message} : ${meta})` + */ + private fileFormat = winston.format.printf((data: any) => { + return JSON.stringify(this.prepareLogData(data)); + }); + + /** + * Custom winston console format + * Write logs with given format : + * `${timestamp} ${level} : ${info.message} : JSON.stringify({ ...meta }) ` + */ + private consoleFormat = winston.format.printf((data: any) => { + const preparedData = this.prepareLogData(data); + return ( + `${preparedData.timestamp} ${preparedData.level} : ` + + `${preparedData.message} : ${JSON.stringify(preparedData.meta)}` + ); + }); + + private prepareLogData = (data: any) => { + const additionalData = { ...data }; + delete additionalData.timestamp; + delete additionalData.level; + delete additionalData.message; + delete additionalData.service; + return { + timestamp: data.timestamp, + level: data.level, + message: data.message, + meta: additionalData, + }; + }; +} diff --git a/src/static/config.json b/src/static/config.json index 3cd3fba..efac02a 100644 --- a/src/static/config.json +++ b/src/static/config.json @@ -1,6 +1,8 @@ { "development": { "config_id": "development", + "mainLogFile": "dist/dev-main.log", + "mainLogLevel": "debug", "isIconAvailable": true, "isNodeIntegration": false, "isContextIsolation": true, @@ -9,6 +11,8 @@ }, "e2e-test": { "config_id": "e2e-test", + "mainLogFile": "dist/e2e-main.log", + "mainLogLevel": "error", "isIconAvailable": true, "isNodeIntegration": true, "isContextIsolation": false, @@ -17,6 +21,8 @@ }, "production": { "config_id": "production", + "mainLogFile": "main.log", + "mainLogLevel": "error", "isIconAvailable": false, "isOpenDevTools": false } diff --git a/yarn.lock b/yarn.lock index 1ccd544..eb5a89c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2086,7 +2086,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^2.0.0, async@^2.5.0, async@^2.6.2: +async@^2.0.0, async@^2.5.0, async@^2.6.1, async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -3066,6 +3066,14 @@ color-string@^1.5.2: color-name "^1.0.0" simple-swizzle "^0.2.2" +color@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" + integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + color@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" @@ -3074,16 +3082,29 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" +colornames@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96" + integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y= + colors@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= -colors@^1.1.0: +colors@^1.1.0, colors@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +colorspace@1.1.x: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" + integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ== + dependencies: + color "3.0.x" + text-hex "1.0.x" + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -3964,6 +3985,15 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= +diagnostics@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a" + integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ== + dependencies: + colorspace "1.1.x" + enabled "1.0.x" + kuler "1.0.x" + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -4326,6 +4356,13 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +enabled@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93" + integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M= + dependencies: + env-variable "0.0.x" + encodeurl@^1.0.2, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -4428,6 +4465,11 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== +env-variable@0.0.x: + version "0.0.6" + resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.6.tgz#74ab20b3786c545b62b4a4813ab8cf22726c9808" + integrity sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg== + err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" @@ -4761,6 +4803,11 @@ fast-json-stable-stringify@2.1.0, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-safe-stringify@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + fastparse@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -4794,6 +4841,11 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fecha@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" + integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg== + figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" @@ -6722,6 +6774,13 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +kuler@1.0.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6" + integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ== + dependencies: + colornames "^1.1.1" + latest-version@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -6915,6 +6974,17 @@ log4js@^4.0.0: rfdc "^1.1.4" streamroller "^1.0.6" +logform@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360" + integrity sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ== + dependencies: + colors "^1.2.1" + fast-safe-stringify "^2.0.4" + fecha "^2.3.3" + ms "^2.1.1" + triple-beam "^1.3.0" + loglevel@^1.6.6: version "1.6.8" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" @@ -7824,6 +7894,11 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +one-time@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e" + integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4= + onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -10156,6 +10231,11 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + stat-mode@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465" @@ -10616,6 +10696,11 @@ terser@^4.1.2, terser@^4.4.3, terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + throttleit@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" @@ -10758,6 +10843,11 @@ trim-newlines@^2.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= +triple-beam@^1.2.0, triple-beam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" + integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== + truncate-utf8-bytes@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" @@ -11472,6 +11562,29 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +winston-transport@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.3.0.tgz#df68c0c202482c448d9b47313c07304c2d7c2c66" + integrity sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A== + dependencies: + readable-stream "^2.3.6" + triple-beam "^1.2.0" + +winston@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.2.1.tgz#63061377976c73584028be2490a1846055f77f07" + integrity sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw== + dependencies: + async "^2.6.1" + diagnostics "^1.1.1" + is-stream "^1.1.0" + logform "^2.1.1" + one-time "0.0.4" + readable-stream "^3.1.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.3.0" + wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"