diff --git a/backend/src/api/backend-info.ts b/backend/src/api/backend-info.ts index 8f028bac8..bf3b459de 100644 --- a/backend/src/api/backend-info.ts +++ b/backend/src/api/backend-info.ts @@ -1,5 +1,6 @@ import * as fs from 'fs'; import * as os from 'os'; +import logger from '../logger'; class BackendInfo { gitCommitHash = ''; @@ -21,7 +22,7 @@ class BackendInfo { try { this.gitCommitHash = fs.readFileSync('../.git/refs/heads/master').toString().trim(); } catch (e) { - console.log('Could not load git commit info, skipping.'); + logger.err('Could not load git commit info, skipping.'); } } } diff --git a/backend/src/api/bisq/bisq.ts b/backend/src/api/bisq/bisq.ts index 9770ff7ae..8167318e9 100644 --- a/backend/src/api/bisq/bisq.ts +++ b/backend/src/api/bisq/bisq.ts @@ -4,7 +4,7 @@ import * as request from 'request'; import { BisqBlocks, BisqBlock, BisqTransaction, BisqStats, BisqTrade } from './interfaces'; import { Common } from '../common'; import { Block } from '../../interfaces'; - +import logger from '../../logger'; class Bisq { private static BLOCKS_JSON_FILE_PATH = '/all/blocks.json'; private latestBlockHeight = 0; @@ -38,7 +38,7 @@ class Bisq { handleNewBitcoinBlock(block: Block): void { if (block.height - 2 > this.latestBlockHeight && this.latestBlockHeight !== 0) { - console.log(`Bitcoin block height (#${block.height}) has diverged from the latest Bisq block height (#${this.latestBlockHeight}). Restarting watchers...`); + logger.info(`Bitcoin block height (#${block.height}) has diverged from the latest Bisq block height (#${this.latestBlockHeight}). Restarting watchers...`); this.startTopDirectoryWatcher(); this.startSubDirectoryWatcher(); } @@ -82,7 +82,7 @@ class Bisq { private checkForBisqDataFolder() { if (!fs.existsSync(config.BISQ_BLOCKS_DATA_PATH + Bisq.BLOCKS_JSON_FILE_PATH)) { - console.log(config.BISQ_BLOCKS_DATA_PATH + Bisq.BLOCKS_JSON_FILE_PATH + ` doesn't exist. Make sure Bisq is running and the config is correct before starting the server.`); + logger.info(config.BISQ_BLOCKS_DATA_PATH + Bisq.BLOCKS_JSON_FILE_PATH + ` doesn't exist. Make sure Bisq is running and the config is correct before starting the server.`); return process.exit(1); } } @@ -100,7 +100,7 @@ class Bisq { this.subdirectoryWatcher.close(); } fsWait = setTimeout(() => { - console.log(`Bisq restart detected. Resetting both watchers in 3 minutes.`); + logger.info(`Bisq restart detected. Resetting both watchers in 3 minutes.`); setTimeout(() => { this.startTopDirectoryWatcher(); this.startSubDirectoryWatcher(); @@ -115,7 +115,7 @@ class Bisq { this.subdirectoryWatcher.close(); } if (!fs.existsSync(config.BISQ_BLOCKS_DATA_PATH + Bisq.BLOCKS_JSON_FILE_PATH)) { - console.log(config.BISQ_BLOCKS_DATA_PATH + Bisq.BLOCKS_JSON_FILE_PATH + ` doesn't exist. Trying to restart sub directory watcher again in 3 minutes.`); + logger.warn(config.BISQ_BLOCKS_DATA_PATH + Bisq.BLOCKS_JSON_FILE_PATH + ` doesn't exist. Trying to restart sub directory watcher again in 3 minutes.`); setTimeout(() => this.startSubDirectoryWatcher(), 180000); return; } @@ -125,7 +125,7 @@ class Bisq { clearTimeout(fsWait); } fsWait = setTimeout(() => { - console.log(`Change detected in the Bisq data folder.`); + logger.info(`Change detected in the Bisq data folder.`); this.loadBisqDumpFile(); }, 2000); }); @@ -133,7 +133,7 @@ class Bisq { private updatePrice() { request('https://markets.bisq.network/api/trades/?market=bsq_btc', { json: true }, (err, res, trades: BisqTrade[]) => { - if (err) { return console.log(err); } + if (err) { return logger.err(err); } const prices: number[] = []; trades.forEach((trade) => { @@ -154,7 +154,7 @@ class Bisq { this.buildIndex(); this.calculateStats(); } catch (e) { - console.log('loadBisqDumpFile() error.', e.message); + logger.err('loadBisqDumpFile() error.' + e.message); } } @@ -198,7 +198,7 @@ class Bisq { }); const time = new Date().getTime() - start; - console.log('Bisq data index rebuilt in ' + time + ' ms'); + logger.info('Bisq data index rebuilt in ' + time + ' ms'); } private calculateStats() { @@ -236,14 +236,14 @@ class Bisq { private async loadBisqBlocksDump(cacheData: string): Promise { const start = new Date().getTime(); if (cacheData && cacheData.length !== 0) { - console.log('Processing Bisq data dump...'); + logger.info('Processing Bisq data dump...'); const data: BisqBlocks = JSON.parse(cacheData); if (data.blocks && data.blocks.length !== this.blocks.length) { this.blocks = data.blocks.filter((block) => block.txs.length > 0); this.blocks.reverse(); this.latestBlockHeight = data.chainHeight; const time = new Date().getTime() - start; - console.log('Bisq dump processed in ' + time + ' ms'); + logger.info('Bisq dump processed in ' + time + ' ms'); } else { throw new Error(`Bisq dump didn't contain any blocks`); } diff --git a/backend/src/api/bisq/markets.ts b/backend/src/api/bisq/markets.ts index 5f82e6d05..96b70dbcc 100644 --- a/backend/src/api/bisq/markets.ts +++ b/backend/src/api/bisq/markets.ts @@ -2,6 +2,7 @@ const config = require('../../../mempool-config.json'); import * as fs from 'fs'; import { OffersData as OffersData, TradesData, Currency } from './interfaces'; import bisqMarket from './markets-api'; +import logger from '../../logger'; class Bisq { private static FOLDER_WATCH_CHANGE_DETECTION_DEBOUNCE = 4000; @@ -30,7 +31,7 @@ class Bisq { private checkForBisqDataFolder() { if (!fs.existsSync(Bisq.MARKET_JSON_PATH + Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency)) { - console.log(Bisq.MARKET_JSON_PATH + Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency + ` doesn't exist. Make sure Bisq is running and the config is correct before starting the server.`); + logger.err(Bisq.MARKET_JSON_PATH + Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency + ` doesn't exist. Make sure Bisq is running and the config is correct before starting the server.`); return process.exit(1); } } @@ -40,7 +41,7 @@ class Bisq { this.subdirectoryWatcher.close(); } if (!fs.existsSync(Bisq.MARKET_JSON_PATH + Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency)) { - console.log(Bisq.MARKET_JSON_PATH + Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency + ` doesn't exist. Trying to restart sub directory watcher again in 3 minutes.`); + logger.warn(Bisq.MARKET_JSON_PATH + Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency + ` doesn't exist. Trying to restart sub directory watcher again in 3 minutes.`); setTimeout(() => this.startBisqDirectoryWatcher(), 180000); return; } @@ -50,7 +51,7 @@ class Bisq { clearTimeout(fsWait); } fsWait = setTimeout(() => { - console.log(`Change detected in the Bisq market data folder.`); + logger.info(`Change detected in the Bisq market data folder.`); this.loadBisqDumpFile(); }, Bisq.FOLDER_WATCH_CHANGE_DETECTION_DEBOUNCE); }); @@ -65,7 +66,7 @@ class Bisq { if (cryptoMtime > this.cryptoCurrencyLastMtime || fiatMtime > this.fiatCurrencyLastMtime) { const cryptoCurrencyData = await this.loadData(Bisq.MARKET_JSON_FILE_PATHS.cryptoCurrency); const fiatCurrencyData = await this.loadData(Bisq.MARKET_JSON_FILE_PATHS.fiatCurrency); - console.log('Updating Bisq Market Currency Data'); + logger.info('Updating Bisq Market Currency Data'); bisqMarket.setCurrencyData(cryptoCurrencyData, fiatCurrencyData); if (cryptoMtime > this.cryptoCurrencyLastMtime) { this.cryptoCurrencyLastMtime = cryptoMtime; @@ -78,7 +79,7 @@ class Bisq { const offersMtime = this.getFileMtime(Bisq.MARKET_JSON_FILE_PATHS.offers); if (offersMtime > this.offersLastMtime) { const offersData = await this.loadData(Bisq.MARKET_JSON_FILE_PATHS.offers); - console.log('Updating Bisq Market Offers Data'); + logger.info('Updating Bisq Market Offers Data'); bisqMarket.setOffersData(offersData); this.offersLastMtime = offersMtime; marketsDataUpdated = true; @@ -86,7 +87,7 @@ class Bisq { const tradesMtime = this.getFileMtime(Bisq.MARKET_JSON_FILE_PATHS.trades); if (tradesMtime > this.tradesLastMtime) { const tradesData = await this.loadData(Bisq.MARKET_JSON_FILE_PATHS.trades); - console.log('Updating Bisq Market Trades Data'); + logger.info('Updating Bisq Market Trades Data'); bisqMarket.setTradesData(tradesData); this.tradesLastMtime = tradesMtime; marketsDataUpdated = true; @@ -94,10 +95,10 @@ class Bisq { if (marketsDataUpdated) { bisqMarket.updateCache(); const time = new Date().getTime() - start; - console.log('Bisq market data updated in ' + time + ' ms'); + logger.info('Bisq market data updated in ' + time + ' ms'); } } catch (e) { - console.log('loadBisqMarketDataDumpFile() error.', e.message); + logger.err('loadBisqMarketDataDumpFile() error.' + e.message); } } diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index a4b20a076..04efc19d5 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -1,5 +1,6 @@ const config = require('../../mempool-config.json'); import bitcoinApi from './bitcoin/electrs-api'; +import logger from '../logger'; import memPool from './mempool'; import { Block, TransactionExtended, TransactionMinerInfo } from '../interfaces'; import { Common } from './common'; @@ -35,7 +36,7 @@ class Blocks { } if (blockHeightTip - this.currentBlockHeight > config.INITIAL_BLOCK_AMOUNT * 2) { - console.log(`${blockHeightTip - this.currentBlockHeight} blocks since tip. Fast forwarding to the ${config.INITIAL_BLOCK_AMOUNT} recent blocks`); + logger.info(`${blockHeightTip - this.currentBlockHeight} blocks since tip. Fast forwarding to the ${config.INITIAL_BLOCK_AMOUNT} recent blocks`); this.currentBlockHeight = blockHeightTip - config.INITIAL_BLOCK_AMOUNT; } @@ -51,7 +52,7 @@ class Blocks { this.currentBlockHeight = blockHeightTip; } else { this.currentBlockHeight++; - console.log(`New block found (#${this.currentBlockHeight})!`); + logger.info(`New block found (#${this.currentBlockHeight})!`); } const blockHash = await bitcoinApi.getBlockHash(this.currentBlockHeight); @@ -69,7 +70,7 @@ class Blocks { transactions.push(mempool[txIds[i]]); found++; } else { - console.log(`Fetching block tx ${i} of ${txIds.length}`); + logger.info(`Fetching block tx ${i} of ${txIds.length}`); const tx = await memPool.getTransactionExtended(txIds[i]); if (tx) { transactions.push(tx); @@ -78,7 +79,7 @@ class Blocks { } } - console.log(`${found} of ${txIds.length} found in mempool. ${notFound} not found.`); + logger.info(`${found} of ${txIds.length} found in mempool. ${notFound} not found.`); block.reward = transactions[0].vout.reduce((acc, curr) => acc + curr.value, 0); block.coinbaseTx = this.stripCoinbaseTransaction(transactions[0]); @@ -101,7 +102,7 @@ class Blocks { } } catch (err) { - console.log('updateBlocks error', err); + logger.err('updateBlocks error' + err); } } diff --git a/backend/src/api/disk-cache.ts b/backend/src/api/disk-cache.ts index 2f74fe3a5..2ae3bb580 100644 --- a/backend/src/api/disk-cache.ts +++ b/backend/src/api/disk-cache.ts @@ -3,6 +3,7 @@ import * as fs from 'fs'; import * as process from 'process'; import memPool from './mempool'; import blocks from './blocks'; +import logger from '../logger'; class DiskCache { static FILE_NAME = './cache.json'; @@ -26,13 +27,13 @@ class DiskCache { mempool: memPool.getMempool(), blocks: blocks.getBlocks(), })); - console.log('Mempool and blocks data saved to disk cache'); + logger.info('Mempool and blocks data saved to disk cache'); } loadMempoolCache() { const cacheData = this.loadData(); if (cacheData) { - console.log('Restoring mempool and blocks data from disk cache'); + logger.info('Restoring mempool and blocks data from disk cache'); const data = JSON.parse(cacheData); memPool.setMempool(data.mempool); blocks.setBlocks(data.blocks); diff --git a/backend/src/api/donations.ts b/backend/src/api/donations.ts index c3ab24f33..3178094a4 100644 --- a/backend/src/api/donations.ts +++ b/backend/src/api/donations.ts @@ -1,6 +1,7 @@ const config = require('../../mempool-config.json'); import * as request from 'request'; import { DB } from '../database'; +import logger from '../logger'; class Donations { private notifyDonationStatusCallback: ((invoiceId: string) => void) | undefined; @@ -45,6 +46,7 @@ class Donations { } async $handleWebhookRequest(data: any) { + logger.debug('Received BTCPayServer webhook data: ' + JSON.stringify(data)); if (!data || !data.id) { return; } @@ -70,21 +72,24 @@ class Donations { imageUrl = hiveData.imageUrl; handle = hiveData.screenName; } catch (e) { - console.log('Error fetching twitter image', e.message); + logger.err('Error fetching twitter image' + e.message); } } + logger.debug('Creating database entry for donation with invoice id: ' + response.id); this.$addDonationToDatabase(response.btcPaid, handle, response.id, imageUrl); } private getStatus(id: string): Promise { return new Promise((resolve, reject) => { + logger.debug('Fetching status for invoice: ' + id); request.get({ uri: '/invoices/' + id, json: true, ...this.options, }, (err, res, body) => { if (err) { return reject(err); } + logger.debug('Invoice status received: ' + JSON.stringify(body.data)); resolve(body.data); }); }); @@ -98,7 +103,7 @@ class Donations { connection.release(); return rows; } catch (e) { - console.log('$getDonationsFromDatabase() error', e); + logger.err('$getDonationsFromDatabase() error' + e); } } @@ -115,17 +120,19 @@ class Donations { const [result]: any = await connection.query(query, params); connection.release(); } catch (e) { - console.log('$addDonationToDatabase() error', e); + logger.err('$addDonationToDatabase() error' + e); } } private async $getTwitterImageUrl(handle: string): Promise { return new Promise((resolve, reject) => { + logger.debug('Fetching Hive.one data...'); request.get({ uri: `https://api.hive.one/v1/influencers/screen_name/${handle}/?format=json`, json: true, }, (err, res, body) => { if (err) { return reject(err); } + logger.debug('Hive.one data fetched:' + JSON.stringify(body.data)); resolve(body.data); }); }); diff --git a/backend/src/api/fiat-conversion.ts b/backend/src/api/fiat-conversion.ts index 959d8ae27..1089bc805 100644 --- a/backend/src/api/fiat-conversion.ts +++ b/backend/src/api/fiat-conversion.ts @@ -1,4 +1,5 @@ import * as request from 'request'; +import logger from '../logger'; class FiatConversion { private tickers = { @@ -10,7 +11,7 @@ class FiatConversion { constructor() { } public startService() { - console.log('Starting currency rates service'); + logger.info('Starting currency rates service'); setInterval(this.updateCurrency.bind(this), 1000 * 60 * 60); this.updateCurrency(); } @@ -21,7 +22,7 @@ class FiatConversion { private updateCurrency() { request('https://api.opennode.co/v1/rates', { json: true }, (err, res, body) => { - if (err) { return console.log(err); } + if (err) { return logger.info(err); } if (body && body.data) { this.tickers = body.data; } diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts index feba09f36..cc1ef4e3e 100644 --- a/backend/src/api/mempool.ts +++ b/backend/src/api/mempool.ts @@ -1,6 +1,7 @@ const config = require('../../mempool-config.json'); import bitcoinApi from './bitcoin/electrs-api'; import { MempoolInfo, TransactionExtended, Transaction, VbytesPerSecond } from '../interfaces'; +import logger from '../logger'; import { Common } from './common'; class Mempool { @@ -49,8 +50,8 @@ class Mempool { public async updateMemPoolInfo() { try { this.mempoolInfo = await bitcoinApi.getMempoolInfo(); - } catch (err) { - console.log('Error getMempoolInfo', err); + } catch (e) { + logger.err('Error getMempoolInfo ' + e.message || e); } } @@ -87,13 +88,13 @@ class Mempool { firstSeen: Math.round((new Date().getTime() / 1000)), }, transaction); } catch (e) { - console.log(txId + ' not found'); + logger.warn(txId + ' not found'); return false; } } public async updateMempool() { - console.log('Updating mempool'); + logger.info('Updating mempool'); const start = new Date().getTime(); let hasChange: boolean = false; const currentMempoolSize = Object.keys(this.mempoolCache).length; @@ -118,13 +119,13 @@ class Mempool { } hasChange = true; if (diff > 0) { - console.log('Fetched transaction ' + txCount + ' / ' + diff); + logger.info('Fetched transaction ' + txCount + ' / ' + diff); } else { - console.log('Fetched transaction ' + txCount); + logger.info('Fetched transaction ' + txCount); } newTransactions.push(transaction); } else { - console.log('Error finding transaction in mempool.'); + logger.err('Error finding transaction in mempool.'); } } @@ -137,10 +138,10 @@ class Mempool { if (this.mempoolProtection === 0 && transactions.length / currentMempoolSize <= 0.80) { this.mempoolProtection = 1; this.inSync = false; - console.log('Mempool clear protection triggered.'); + logger.info('Mempool clear protection triggered.'); setTimeout(() => { this.mempoolProtection = 2; - console.log('Mempool clear protection resumed.'); + logger.info('Mempool clear protection resumed.'); }, 1000 * 60 * 2); } @@ -170,7 +171,7 @@ class Mempool { if (!this.inSync && transactions.length === Object.keys(newMempool).length) { this.inSync = true; - console.log('The mempool is now in sync!'); + logger.info('The mempool is now in sync!'); } if (this.mempoolChangedCallback && (hasChange || deletedTransactions.length)) { @@ -180,10 +181,10 @@ class Mempool { const end = new Date().getTime(); const time = end - start; - console.log(`New mempool size: ${Object.keys(newMempool).length} Change: ${diff}`); - console.log('Mempool updated in ' + time / 1000 + ' seconds'); + logger.info(`New mempool size: ${Object.keys(newMempool).length} Change: ${diff}`); + logger.info('Mempool updated in ' + time / 1000 + ' seconds'); } catch (err) { - console.log('getRawMempool error.', err); + logger.err('getRawMempool error. ' + err.message || err); } } diff --git a/backend/src/api/statistics.ts b/backend/src/api/statistics.ts index 6e5eb8119..c2a4db0c5 100644 --- a/backend/src/api/statistics.ts +++ b/backend/src/api/statistics.ts @@ -1,5 +1,6 @@ import memPool from './mempool'; import { DB } from '../database'; +import logger from '../logger'; import { Statistic, TransactionExtended, OptimizedStatistic } from '../interfaces'; @@ -14,7 +15,7 @@ class Statistics { constructor() { } public startStatistics(): void { - console.log('Starting statistics service'); + logger.info('Starting statistics service'); const now = new Date(); const nextInterval = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), @@ -37,7 +38,7 @@ class Statistics { const txPerSecond = memPool.getTxPerSecond(); const vBytesPerSecond = memPool.getVBytesPerSecond(); - console.log('Running statistics'); + logger.info('Running statistics'); let memPoolArray: TransactionExtended[] = []; for (const i in currentMempool) { @@ -233,7 +234,7 @@ class Statistics { connection.release(); return result.insertId; } catch (e) { - console.log('$create() error', e); + logger.err('$create() error' + e); } } @@ -292,7 +293,7 @@ class Statistics { return this.mapStatisticToOptimizedStatistic([rows[0]])[0]; } } catch (e) { - console.log('$list2H() error', e); + logger.err('$list2H() error' + e); } } @@ -304,7 +305,7 @@ class Statistics { connection.release(); return this.mapStatisticToOptimizedStatistic(rows); } catch (e) { - console.log('$list2H() error', e); + logger.err('$list2H() error' + e); return []; } } @@ -329,7 +330,7 @@ class Statistics { connection.release(); return this.mapStatisticToOptimizedStatistic(rows); } catch (e) { - console.log('$list1W() error', e); + logger.err('$list1W() error' + e); return []; } } @@ -342,7 +343,7 @@ class Statistics { connection.release(); return this.mapStatisticToOptimizedStatistic(rows); } catch (e) { - console.log('$list1M() error', e); + logger.err('$list1M() error' + e); return []; } } @@ -355,7 +356,7 @@ class Statistics { connection.release(); return this.mapStatisticToOptimizedStatistic(rows); } catch (e) { - console.log('$list3M() error', e); + logger.err('$list3M() error' + e); return []; } } @@ -368,7 +369,7 @@ class Statistics { connection.release(); return this.mapStatisticToOptimizedStatistic(rows); } catch (e) { - console.log('$list6M() error', e); + logger.err('$list6M() error' + e); return []; } } @@ -381,7 +382,7 @@ class Statistics { connection.release(); return this.mapStatisticToOptimizedStatistic(rows); } catch (e) { - console.log('$list6M() error', e); + logger.err('$list6M() error' + e); return []; } } diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 9957356d3..2a860dcf8 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -1,5 +1,5 @@ const config = require('../../mempool-config.json'); - +import logger from '../logger'; import * as WebSocket from 'ws'; import { Block, TransactionExtended, WebsocketResponse, MempoolBlock, OptimizedStatistic } from '../interfaces'; import blocks from './blocks'; @@ -107,7 +107,7 @@ class WebsocketHandler { client.send(JSON.stringify(response)); } } catch (e) { - console.log(e); + logger.err(e); } }); }); diff --git a/backend/src/database.ts b/backend/src/database.ts index 9f30254ec..6d1ea7414 100644 --- a/backend/src/database.ts +++ b/backend/src/database.ts @@ -1,5 +1,6 @@ const config = require('../mempool-config.json'); import { createPool } from 'mysql2/promise'; +import logger from './logger'; export class DB { static pool = createPool({ @@ -16,11 +17,11 @@ export class DB { export async function checkDbConnection() { try { const connection = await DB.pool.getConnection(); - console.log('Database connection established.'); + logger.info('Database connection established.'); connection.release(); } catch (e) { - console.log('Could not connect to database.'); - console.log(e); + logger.err('Could not connect to database.'); + logger.err(e); process.exit(1); } } diff --git a/backend/src/index.ts b/backend/src/index.ts index b297df58c..4555ab068 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -20,6 +20,7 @@ import fiatConversion from './api/fiat-conversion'; import bisq from './api/bisq/bisq'; import bisqMarkets from './api/bisq/markets'; import donations from './api/donations'; +import logger from './logger'; class Server { private wss: WebSocket.Server | undefined; @@ -35,7 +36,7 @@ class Server { } if (cluster.isMaster) { - console.log(`Mempool Server is running on port ${config.HTTP_PORT}`); + logger.info(`Mempool Server is running on port ${config.HTTP_PORT}`); const numCPUs = config.CLUSTER_NUM_CORES; for (let i = 0; i < numCPUs; i++) { @@ -46,7 +47,7 @@ class Server { cluster.on('exit', (worker, code, signal) => { const workerId = worker.process['env'].workerId; - console.log(`Mempool Worker PID #${worker.process.pid} workerId: ${workerId} died. Restarting in 10 seconds...`, signal || code); + logger.info(`Mempool Worker PID #${worker.process.pid} workerId: ${workerId} died. Restarting in 10 seconds... ${signal || code}`); setTimeout(() => { const env = { workerId: workerId }; const newWorker = cluster.fork(env); @@ -104,9 +105,9 @@ class Server { this.server.listen(config.HTTP_PORT, () => { if (worker) { - console.log(`Mempool Server worker #${process.pid} started`); + logger.info(`Mempool Server worker #${process.pid} started`); } else { - console.log(`Mempool Server is running on port ${config.HTTP_PORT}`); + logger.info(`Mempool Server is running on port ${config.HTTP_PORT}`); } }); } diff --git a/backend/src/logger.ts b/backend/src/logger.ts new file mode 100644 index 000000000..6f3637b0b --- /dev/null +++ b/backend/src/logger.ts @@ -0,0 +1,155 @@ +import * as dgram from 'dgram'; + +class Logger { + static priorities = { + emerg: 0, + alert: 1, + crit: 2, + err: 3, + warn: 4, + notice: 5, + info: 6, + debug: 7 + }; + static facilities = { + kern: 0, + user: 1, + mail: 2, + daemon: 3, + auth: 4, + syslog: 5, + lpr: 6, + news: 7, + uucp: 8, + local0: 16, + local1: 17, + local2: 18, + local3: 19, + local4: 20, + local5: 21, + local6: 22, + local7: 23 + }; + + // @ts-ignore + public emerg: ((msg: string) => void); + // @ts-ignore + public alert: ((msg: string) => void); + // @ts-ignore + public crit: ((msg: string) => void); + // @ts-ignore + public err: ((msg: string) => void); + // @ts-ignore + public warn: ((msg: string) => void); + // @ts-ignore + public notice: ((msg: string) => void); + // @ts-ignore + public info: ((msg: string) => void); + // @ts-ignore + public debug: ((msg: string) => void); + + private name = 'mempool'; + private fac: any; + private loghost: string; + private logport: number; + + constructor(fac) { + let prio; + this.fac = fac != null ? fac : Logger.facilities.local0; + this.loghost = '127.0.0.1'; + this.logport = 514; + for (prio in Logger.priorities) { + if (true) { + this.addprio(prio); + } + } + } + + private addprio(prio): void { + this[prio] = (function(_this) { + return function(msg) { + return _this.msg(prio, msg); + }; + })(this); + } + + private tag() { + let e, stack, stacklevel, tag; + stacklevel = 4; + try { + const err = new Error().stack; + if (err) { + stack = err.replace(/^\s+at\s+/gm, '').replace(/^Object.\s*\(/gm, '{anonymous}()@').split('\n'); + tag = stack[stacklevel].split(' ')[1]; + tag = '(' + tag.split('/').reverse()[0]; + } else { + tag = ''; + } + } catch (_error) { + e = _error; + tag = ''; + } + return tag; + } + + private msg(priority, msg) { + let consolemsg, prionum, syslogmsg; + if (typeof msg === 'string' && msg.length > 0) { + while (msg[msg.length - 1].charCodeAt(0) === 10) { + msg = msg.slice(0, msg.length - 1); + } + } + prionum = Logger.priorities[priority] || Logger.priorities.info; + const tag = this.tag(); + syslogmsg = `<${(this.fac * 8 + prionum)}> ${this.name}[${process.pid}]: ${tag}: ${priority.toUpperCase()} ${msg}`; + consolemsg = `${this.ts()} [${process.pid}] ${priority.toUpperCase()}: ${msg}`; + + this.syslog(syslogmsg); + if (priority === 'warning') { + priority = 'warn'; + } + if (priority === 'debug') { + priority = 'info'; + } + if (priority === 'err') { + priority = 'error'; + } + return (console[priority] || console.error)(consolemsg); + } + + private syslog(msg) { + let client, msgbuf; + msgbuf = Buffer.from(msg); + client = dgram.createSocket('udp4'); + client.send(msgbuf, 0, msgbuf.length, this.logport, this.loghost, function(err, bytes) { + if (err) { + console.log(err); + } + client.close(); + }); + } + + private leadZero(n: number): number | string { + if (n < 10) { + return '0' + n; + } + return n; + } + + private ts() { + let day, dt, hours, minutes, month, months, seconds; + dt = new Date(); + hours = this.leadZero(dt.getHours()); + minutes = this.leadZero(dt.getMinutes()); + seconds = this.leadZero(dt.getSeconds()); + month = dt.getMonth(); + day = dt.getDate(); + if (day < 10) { + day = ' ' + day; + } + months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + return months[month] + ' ' + day + ' ' + hours + ':' + minutes + ':' + seconds; + } +} + +export default new Logger(Logger.facilities.local7); diff --git a/backend/src/routes.ts b/backend/src/routes.ts index cde97e39c..d492cdb14 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -10,6 +10,7 @@ import bisqMarket from './api/bisq/markets-api'; import { RequiredSpec } from './interfaces'; import { MarketsApiError } from './api/bisq/interfaces'; import donations from './api/donations'; +import logger from './logger'; class Routes { private cache = {}; @@ -28,7 +29,7 @@ class Routes { this.cache['3m'] = await statistics.$list3M(); this.cache['6m'] = await statistics.$list6M(); this.cache['1y'] = await statistics.$list1Y(); - console.log('Statistics cache created'); + logger.info('Statistics cache created'); } public async get2HStatistics(req: Request, res: Response) { diff --git a/frontend/src/app/services/audio.service.ts b/frontend/src/app/services/audio.service.ts index 4b3060b24..58e2ff553 100644 --- a/frontend/src/app/services/audio.service.ts +++ b/frontend/src/app/services/audio.service.ts @@ -17,7 +17,7 @@ export class AudioService { this.audio.src = '../../../resources/sounds/' + name + '.mp3'; this.audio.load(); this.audio.play().catch((e) => { - console.log('Play sound failed', e); + console.log('Play sound failed' + e); }); setTimeout(() => this.isPlaying = false, 100); }