From 175c0e4843e204de7acc7bfcfb22ef95e8fb7eca Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 29 Mar 2022 13:53:28 +1100 Subject: [PATCH] move logging.js to ts --- package.json | 4 +- app/logging.js => ts/node/logging.ts | 99 +++++++++++++++------------- yarn.lock | 64 ++++++------------ 3 files changed, 75 insertions(+), 92 deletions(-) rename app/logging.js => ts/node/logging.ts (69%) diff --git a/package.json b/package.json index 6fafa872e..37c524d64 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "react-toastify": "^6.0.9", "react-use": "^17.2.1", "react-virtualized": "9.22.3", - "read-last-lines": "1.3.0", + "read-last-lines-ts": "^1.2.1", "redux": "4.0.1", "redux-logger": "3.0.6", "redux-persist": "^6.0.0", @@ -119,6 +119,7 @@ "@types/better-sqlite3": "5.4.1", "@types/blueimp-load-image": "5.14.4", "@types/buffer-crc32": "^0.2.0", + "@types/bunyan": "^1.8.8", "@types/bytebuffer": "^5.0.41", "@types/chai": "4.2.18", "@types/chai-as-promised": "^7.1.2", @@ -129,6 +130,7 @@ "@types/electron-is-dev": "^1.1.1", "@types/emoji-mart": "^2.11.3", "@types/filesize": "3.6.0", + "@types/firstline": "^2.0.2", "@types/fs-extra": "5.0.5", "@types/jquery": "3.3.29", "@types/libsodium-wrappers-sumo": "^0.7.5", diff --git a/app/logging.js b/ts/node/logging.ts similarity index 69% rename from app/logging.js rename to ts/node/logging.ts index 7adf48ea8..21c23d628 100644 --- a/app/logging.js +++ b/ts/node/logging.ts @@ -1,29 +1,30 @@ // NOTE: Temporarily allow `then` until we convert the entire file to `async` / `await`: /* eslint-disable more/no-then */ -const path = require('path'); -const fs = require('fs'); +import path from 'path'; +import fs from 'fs'; -const electron = require('electron'); -const bunyan = require('bunyan'); -const _ = require('lodash'); -const readFirstLine = require('firstline'); -const readLastLines = require('read-last-lines').read; -const rimraf = require('rimraf'); +import { app, ipcMain as ipc } from 'electron'; +import Logger from 'bunyan'; +import _ from 'lodash'; +import firstline from 'firstline'; +import { readLastLinesEnc } from 'read-last-lines-ts'; +import rimraf from 'rimraf'; -const { redactAll } = require('../ts/util/privacy'); +import { redactAll } from '../util/privacy'; -const { app, ipcMain: ipc } = electron; const LEVELS = ['fatal', 'error', 'warn', 'info', 'debug', 'trace']; -let logger; - -module.exports = { - initialize, - getLogger, - fetch, +let logger: Logger | undefined; +// tslint:disable: non-literal-fs-path +// tslint:disable: no-console + +type ConsoleCustom = typeof console & { + _log: (...args: any) => void; + _warn: (...args: any) => void; + _error: (...args: any) => void; }; -function initialize() { +export async function initialize() { if (logger) { throw new Error('Already called initialize!'); } @@ -39,7 +40,7 @@ function initialize() { const logFile = path.join(logPath, 'log.log'); - logger = bunyan.createLogger({ + logger = Logger.createLogger({ name: 'log', streams: [ { @@ -56,8 +57,8 @@ function initialize() { }); LEVELS.forEach(level => { - ipc.on(`log-${level}`, (first, ...rest) => { - logger[level](...rest); + ipc.on(`log-${level}`, (_first, ...rest) => { + (logger as any)[level](...rest); }); }); @@ -69,7 +70,7 @@ function initialize() { event.sender.send('fetched-log', data); }, error => { - logger.error(`Problem loading log from disk: ${error.stack}`); + logger?.error(`Problem loading log from disk: ${error.stack}`); } ); }); @@ -78,7 +79,7 @@ function initialize() { try { await deleteAllLogs(logPath); } catch (error) { - logger.error(`Problem deleting all logs: ${error.stack}`); + logger?.error(`Problem deleting all logs: ${error.stack}`); } event.sender.send('delete-all-logs-complete'); @@ -86,7 +87,7 @@ function initialize() { }); } -async function deleteAllLogs(logPath) { +async function deleteAllLogs(logPath: string) { return new Promise((resolve, reject) => { rimraf( logPath, @@ -95,16 +96,18 @@ async function deleteAllLogs(logPath) { }, error => { if (error) { - return reject(error); + reject(error); + return; } - return resolve(); + resolve(undefined); + return; } ); }); } -async function cleanupLogs(logPath) { +async function cleanupLogs(logPath: string) { const now = new Date(); const earliestDate = new Date( Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - 6) @@ -128,7 +131,7 @@ async function cleanupLogs(logPath) { } } -function isLineAfterDate(line, date) { +function isLineAfterDate(line: string, date: Date) { if (!line) { return false; } @@ -142,13 +145,13 @@ function isLineAfterDate(line, date) { } } -function eliminateOutOfDateFiles(logPath, date) { +async function eliminateOutOfDateFiles(logPath: string, date: Date) { const files = fs.readdirSync(logPath); const paths = files.map(file => path.join(logPath, file)); return Promise.all( _.map(paths, target => - Promise.all([readFirstLine(target), readLastLines(target, 2)]).then(results => { + Promise.all([firstline(target), readLastLinesEnc('utf8')(target, 2)]).then(results => { const start = results[0]; const end = results[1].split('\n'); @@ -170,22 +173,22 @@ function eliminateOutOfDateFiles(logPath, date) { ); } -function eliminateOldEntries(files, date) { +async function eliminateOldEntries(files: any, date: Date) { const earliest = date.getTime(); return Promise.all( _.map(files, file => - fetchLog(file.path).then(lines => { + fetchLog(file.path).then((lines: any) => { const recent = _.filter(lines, line => new Date(line.time).getTime() >= earliest); const text = _.map(recent, line => JSON.stringify(line)).join('\n'); - return fs.writeFileSync(file.path, `${text}\n`); + fs.writeFileSync(file.path, `${text}\n`); }) ) ); } -function getLogger() { +export function getLogger() { if (!logger) { throw new Error("Logger hasn't been initialized yet!"); } @@ -193,11 +196,12 @@ function getLogger() { return logger; } -function fetchLog(logFile) { +async function fetchLog(logFile: string) { return new Promise((resolve, reject) => { fs.readFile(logFile, { encoding: 'utf8' }, (err, text) => { if (err) { - return reject(err); + reject(err); + return; } const lines = _.compact(text.split('\n')); @@ -211,15 +215,18 @@ function fetchLog(logFile) { }) ); - return resolve(data); + resolve(data); + return; }); }); } -function fetch(logPath) { +export async function fetch(logPath: string) { // Check that the file exists locally if (!fs.existsSync(logPath)) { - console._log('Log folder not found while fetching its content. Quick! Creating it.'); + (console as ConsoleCustom)._log( + 'Log folder not found while fetching its content. Quick! Creating it.' + ); fs.mkdirSync(logPath, { recursive: true }); } const files = fs.readdirSync(logPath); @@ -242,10 +249,10 @@ function fetch(logPath) { }); } -function logAtLevel(level, ...args) { +function logAtLevel(level: string, ...args: any) { if (logger) { // To avoid [Object object] in our log since console.log handles non-strings smoothly - const str = args.map(item => { + const str = args.map((item: any) => { if (typeof item !== 'string') { try { return JSON.stringify(item); @@ -256,18 +263,18 @@ function logAtLevel(level, ...args) { return item; }); - logger[level](redactAll(str.join(' '))); + (logger as any)[level](redactAll(str.join(' '))); } else { - console._log(...args); + (console as ConsoleCustom)._log(...args); } } // This blows up using mocha --watch, so we ensure it is run just once -if (!console._log) { - console._log = console.log; +if (!(console as ConsoleCustom)._log) { + (console as ConsoleCustom)._log = console.log; console.log = _.partial(logAtLevel, 'info'); - console._error = console.error; + (console as ConsoleCustom)._error = console.error; console.error = _.partial(logAtLevel, 'error'); - console._warn = console.warn; + (console as ConsoleCustom)._warn = console.warn; console.warn = _.partial(logAtLevel, 'warn'); } diff --git a/yarn.lock b/yarn.lock index 65d14603d..c861fd2e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -848,6 +848,13 @@ dependencies: "@types/node" "*" +"@types/bunyan@^1.8.8": + version "1.8.8" + resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.8.tgz#8d6d33f090f37c07e2a80af30ae728450a101008" + integrity sha512-Cblq+Yydg3u+sGiz2mjHjC5MPmdjY+No4qvHrF+BUhblsmSfMvsHLbOG62tPbonsqBj6sbWv1LHcsoe5Jw+/Ow== + dependencies: + "@types/node" "*" + "@types/bytebuffer@^5.0.41": version "5.0.41" resolved "https://registry.yarnpkg.com/@types/bytebuffer/-/bytebuffer-5.0.41.tgz#6850dba4d4cd2846596b4842874d5bfc01cd3db1" @@ -959,6 +966,13 @@ resolved "https://registry.yarnpkg.com/@types/filesize/-/filesize-3.6.0.tgz#5f1a25c7b4e3d5ee2bc63133d374d096b7008c8d" integrity sha512-rOWxCKMjt2DBuwddUnl5GOpf/jAkkqteB+XldncpVxVX+HPTmK2c5ACMOVEbp9gaH81IlhTdC3TwvRa5nopasw== +"@types/firstline@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/firstline/-/firstline-2.0.2.tgz#b7b051c235a667f25f205eaedbfaeeb6c92b8488" + integrity sha512-/Qjs+MO7PwS7EI2k6Iwcc7jHLqf7AlIMDyEmPGB7LrIUFqQWZtbk6UsQxqlPMpOM10f0XiSc6RMsEIKbEGOrGw== + dependencies: + "@types/node" "*" + "@types/fs-extra@5.0.5": version "5.0.5" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.5.tgz#080d90a792f3fa2c5559eb44bd8ef840aae9104b" @@ -1633,11 +1647,6 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= - app-builder-bin@3.5.9: version "3.5.9" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.9.tgz#a3ac0c25286bac68357321cb2eaf7128b0bc0a4f" @@ -3645,7 +3654,7 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fs-extra@0.26.7, fs-extra@^0.26.5: +fs-extra@0.26.7: version "0.26.7" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.26.7.tgz#9ae1fdd94897798edab76d0918cf42d0c3184fa9" integrity sha1-muH92UiXeY7at20JGM9C0MMYT6k= @@ -3692,16 +3701,6 @@ fs-minipass@^2.0.0: dependencies: minipass "^3.0.0" -fs-promise@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-0.5.0.tgz#4347d6bf624655a7061a4319213c393276ad3ef3" - integrity sha1-Q0fWv2JGVacGGkMZITw5MnatPvM= - dependencies: - any-promise "^1.0.0" - fs-extra "^0.26.5" - mz "^2.3.1" - thenify-all "^1.6.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -5353,15 +5352,6 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -mz@^2.3.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - nan@2.14.2, nan@^2.13.2: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" @@ -6424,12 +6414,10 @@ read-config-file@6.0.0: json5 "^2.1.2" lazy-val "^1.0.4" -read-last-lines@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/read-last-lines/-/read-last-lines-1.3.0.tgz#0dd170188d46124a23eb1a87156baf46b315ac4b" - integrity sha1-DdFwGI1GEkoj6xqHFWuvRrMVrEs= - dependencies: - fs-promise "^0.5.0" +read-last-lines-ts@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/read-last-lines-ts/-/read-last-lines-ts-1.2.1.tgz#99e46288c5373c06e16e90e666a46b595dad80a1" + integrity sha512-1VcCrAU38DILYiF4sbNY13zdrMGwrFqjGQnXJy28G1zLJItvnWtgCbqoAJlnZZSiEICMKdM4Ol7LYvVMEoKrAg== read-pkg-up@^1.0.1: version "1.0.1" @@ -7526,20 +7514,6 @@ text-table@~0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -thenify-all@^1.0.0, thenify-all@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.0" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= - dependencies: - any-promise "^1.0.0" - throttle-debounce@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb"