From 351c315736306652410de63343d3c03fe9bd45de Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Tue, 10 May 2016 19:26:10 -0400 Subject: [PATCH] common: improve error logging --- lib/addresses.js | 22 +++++++++++++--------- lib/blocks.js | 24 +++++++++++++----------- lib/common.js | 17 +++++++++++------ lib/messages.js | 8 +++++--- lib/status.js | 14 ++++++++------ lib/transactions.js | 35 +++++++++++++++++++---------------- lib/utils.js | 5 +++-- test/blocks.js | 9 ++++++++- test/index.js | 36 ++++++++++++++++++++++++++++++------ 9 files changed, 110 insertions(+), 60 deletions(-) diff --git a/lib/addresses.js b/lib/addresses.js index 84129a4..beae11f 100644 --- a/lib/addresses.js +++ b/lib/addresses.js @@ -1,16 +1,18 @@ 'use strict'; -var common = require('./common'); var bitcore = require('bitcore-lib'); var async = require('async'); var TxController = require('./transactions'); +var Common = require('./common'); function AddressController(node) { this.node = node; this.txController = new TxController(node); + this.common = new Common({log: this.node.log}); } AddressController.prototype.show = function(req, res) { + var self; var options = { noTxList: parseInt(req.query.noTxList) }; @@ -22,7 +24,7 @@ AddressController.prototype.show = function(req, res) { this.getAddressSummary(req.addr, options, function(err, data) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp(data); @@ -46,9 +48,10 @@ AddressController.prototype.unconfirmedBalance = function(req, res) { }; AddressController.prototype.addressSummarySubQuery = function(req, res, param) { + var self = this; this.getAddressSummary(req.addr, {}, function(err, data) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp(data[param]); @@ -97,8 +100,9 @@ AddressController.prototype.checkAddrs = function(req, res, next) { }; AddressController.prototype.check = function(req, res, next, addresses) { + var self = this; if(!addresses.length || !addresses[0]) { - return common.handleErrors({ + return self.common.handleErrors({ message: 'Must include address', code: 1 }, res); @@ -108,7 +112,7 @@ AddressController.prototype.check = function(req, res, next, addresses) { try { var a = new bitcore.Address(addresses[i]); } catch(e) { - return common.handleErrors({ + return self.common.handleErrors({ message: 'Invalid address: ' + e.message, code: 1 }, res); @@ -123,7 +127,7 @@ AddressController.prototype.utxo = function(req, res) { this.node.getAddressUnspentOutputs(req.addr, {}, function(err, utxos) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } else if (!utxos.length) { return res.jsonp([]); } @@ -137,7 +141,7 @@ AddressController.prototype.multiutxo = function(req, res) { if(err && err.code === -5) { return res.jsonp([]); } else if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp(utxos.map(self.transformUtxo.bind(self))); @@ -176,12 +180,12 @@ AddressController.prototype.multitxs = function(req, res, next) { self.node.getAddressHistory(req.addrs, options, function(err, result) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } self.transformAddressHistoryForMultiTxs(result.items, function(err, items) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp({ totalItems: result.totalCount, diff --git a/lib/blocks.js b/lib/blocks.js index 62c8e43..ff174cc 100644 --- a/lib/blocks.js +++ b/lib/blocks.js @@ -1,12 +1,11 @@ 'use strict'; -var common = require('./common'); var async = require('async'); var bitcore = require('bitcore-lib'); var pools = require('../pools.json'); var BN = bitcore.crypto.BN; var LRU = require('lru-cache'); - +var Common = require('./common'); function BlockController(options) { var self = this; @@ -25,6 +24,8 @@ function BlockController(options) { }; }); }); + + this.common = new Common({log: this.node.log}); } var BLOCK_LIMIT = 200; @@ -47,13 +48,13 @@ BlockController.prototype.block = function(req, res, next) { } else { self.node.getBlock(hash, function(err, block) { if(err && err.code === -5) { - return common.handleErrors(null, res); + return self.common.handleErrors(null, res); } else if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } self.node.services.bitcoind.getBlockHeader(hash, function(err, info) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } var blockResult = self.transformBlock(block, info); if (blockResult.confirmations >= self.blockCacheConfirmations) { @@ -75,9 +76,9 @@ BlockController.prototype.rawBlock = function(req, res, next) { self.node.getRawBlock(blockArg, function(err, blockBuffer) { if(err && err.code === -5) { - return common.handleErrors(null, res); + return self.common.handleErrors(null, res); } else if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } req.rawBlock = { rawblock: blockBuffer.toString('hex') @@ -138,10 +139,11 @@ BlockController.prototype.showRaw = function(req, res) { }; BlockController.prototype.blockIndex = function(req, res) { + var self = this; var height = req.params.height; this.node.services.bitcoind.getBlockHeader(parseInt(height), function(err, info) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp({ blockHash: info.hash @@ -221,7 +223,7 @@ BlockController.prototype.list = function(req, res) { dateStr = req.query.blockDate; var datePattern = /\d{4}-\d{2}-\d{2}/; if(!datePattern.test(dateStr)) { - return common.handleErrors(new Error('Please use yyyy-mm-dd format'), res); + return self.common.handleErrors(new Error('Please use yyyy-mm-dd format'), res); } isToday = dateStr === todayStr; @@ -242,7 +244,7 @@ BlockController.prototype.list = function(req, res) { self.node.services.bitcoind.getBlockHashesByTimestamp(lte, gte, function(err, hashes) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } hashes.reverse(); @@ -259,7 +261,7 @@ BlockController.prototype.list = function(req, res) { }, function(err, blocks) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } blocks.sort(function(a, b) { diff --git a/lib/common.js b/lib/common.js index d7fb9af..ea90111 100644 --- a/lib/common.js +++ b/lib/common.js @@ -1,19 +1,24 @@ 'use strict'; -exports.notReady = function (err, res, p) { +function Common(options) { + this.log = options.log; +} + +Common.prototype.notReady = function (err, res, p) { res.status(503).send('Server not yet ready. Sync Percentage:' + p); }; -exports.handleErrors = function (err, res) { +Common.prototype.handleErrors = function (err, res) { if (err) { if (err.code) { res.status(400).send(err.message + '. Code:' + err.code); - } - else { + } else { + this.log.error(err.stack); res.status(503).send(err.message); } - } - else { + } else { res.status(404).send('Not found'); } }; + +module.exports = Common; diff --git a/lib/messages.js b/lib/messages.js index 79b2ec5..ac7e573 100644 --- a/lib/messages.js +++ b/lib/messages.js @@ -3,18 +3,20 @@ var bitcore = require('bitcore-lib'); var _ = bitcore.deps._; var Message = require('bitcore-message'); -var common = require('./common'); +var Common = require('./common'); function MessagesController(node) { this.node = node; + this.common = new Common({log: this.node.log}); } MessagesController.prototype.verify = function(req, res) { + var self = this; var address = req.body.address || req.query.address; var signature = req.body.signature || req.query.signature; var message = req.body.message || req.query.message; if(_.isUndefined(address) || _.isUndefined(signature) || _.isUndefined(message)) { - return common.handleErrors({ + return self.common.handleErrors({ message: 'Missing parameters (expected "address", "signature" and "message")', code: 1 }, res); @@ -23,7 +25,7 @@ MessagesController.prototype.verify = function(req, res) { try { valid = new Message(message).verify(address, signature); } catch(err) { - return common.handleErrors({ + return self.common.handleErrors({ message: 'Unexpected error: ' + err.message, code: 1 }, res); diff --git a/lib/status.js b/lib/status.js index 1f850a6..bc4b7ad 100644 --- a/lib/status.js +++ b/lib/status.js @@ -1,19 +1,21 @@ 'use strict'; -var common = require('./common'); +var Common = require('./common'); function StatusController(node) { this.node = node; + this.common = new Common({log: this.node.log}); } StatusController.prototype.show = function(req, res) { + var self = this; var option = req.query.q; switch(option) { case 'getDifficulty': this.getDifficulty(function(err, result) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp(result); }); @@ -24,7 +26,7 @@ StatusController.prototype.show = function(req, res) { case 'getBestBlockHash': this.getBestBlockHash(function(err, result) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp(result); }); @@ -33,7 +35,7 @@ StatusController.prototype.show = function(req, res) { default: this.getInfo(function(err, result) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp({ info: result @@ -82,7 +84,7 @@ StatusController.prototype.sync = function(req, res) { this.node.services.bitcoind.isSynced(function(err, synced) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } if (synced) { status = 'finished'; @@ -90,7 +92,7 @@ StatusController.prototype.sync = function(req, res) { self.node.services.bitcoind.syncPercentage(function(err, percentage) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } var info = { status: status, diff --git a/lib/transactions.js b/lib/transactions.js index 9765ede..4ff3eeb 100644 --- a/lib/transactions.js +++ b/lib/transactions.js @@ -3,13 +3,14 @@ var bitcore = require('bitcore-lib'); var _ = bitcore.deps._; var $ = bitcore.util.preconditions; -var common = require('./common'); +var Common = require('./common'); var async = require('async'); var MAXINT = 0xffffffff; // Math.pow(2, 32) - 1; function TxController(node) { this.node = node; + this.common = new Common({log: this.node.log}); } TxController.prototype.show = function(req, res) { @@ -27,9 +28,9 @@ TxController.prototype.transaction = function(req, res, next) { this.node.getTransactionWithBlockInfo(txid, function(err, transaction) { if (err && err.code === -5) { - return common.handleErrors(null, res); + return self.common.handleErrors(null, res); } else if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } transaction.populateInputs(self.node.services.bitcoind, [], function(err) { @@ -41,7 +42,7 @@ TxController.prototype.transaction = function(req, res, next) { self.transformTransaction(transaction, function(err, transformedTransaction) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } req.transaction = transformedTransaction; next(); @@ -191,13 +192,14 @@ TxController.prototype.transformInvTransaction = function(transaction) { }; TxController.prototype.rawTransaction = function(req, res, next) { + var self = this; var txid = req.params.txid; this.node.getTransaction(txid, function(err, transaction) { if (err && err.code === -5) { - return common.handleErrors(null, res); + return self.common.handleErrors(null, res); } else if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } req.rawTransaction = { @@ -226,14 +228,14 @@ TxController.prototype.list = function(req, res) { if(blockHash) { self.node.getBlock(blockHash, function(err, block) { if(err && err.message === 'Block not found.') { - return common.handleErrors(null, res); + return self.common.handleErrors(null, res); } else if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } self.node.services.bitcoind.getBlockHeader(block.hash, function(err, blockInfo) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } var totalTxs = block.transactions.length; var txs; @@ -254,13 +256,13 @@ TxController.prototype.list = function(req, res) { // get previous outputs tx.populateInputs(self.node.services.bitcoind, [], function(err) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } // get spent info tx.populateSpentInfo(self.node.services.bitcoind, {}, function(err) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } self.transformTransaction(tx, next); }); @@ -268,7 +270,7 @@ TxController.prototype.list = function(req, res) { }); }, function(err, transformed) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp({ @@ -288,7 +290,7 @@ TxController.prototype.list = function(req, res) { self.node.getAddressHistory(address, options, function(err, result) { if(err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } var txs = result.items.map(function(info) { @@ -304,7 +306,7 @@ TxController.prototype.list = function(req, res) { }, function(err, transformed) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp({ pagesTotal: Math.ceil(result.totalCount / pageLength), @@ -314,15 +316,16 @@ TxController.prototype.list = function(req, res) { ); }); } else { - return common.handleErrors(new Error('Block hash or address expected'), res); + return self.common.handleErrors(new Error('Block hash or address expected'), res); } }; TxController.prototype.send = function(req, res) { + var self = this; this.node.sendTransaction(req.body.rawtx, function(err, txid) { if(err) { // TODO handle specific errors - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.json({'txid': txid}); diff --git a/lib/utils.js b/lib/utils.js index 1028fb5..e4ddeec 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -2,10 +2,11 @@ var _ = require('lodash'); var async = require('async'); -var common = require('./common'); +var Common = require('./common'); function UtilsController(node) { this.node = node; + this.common = new Common({log: this.node.log}); } UtilsController.prototype.estimateFee = function(req, res) { @@ -24,7 +25,7 @@ UtilsController.prototype.estimateFee = function(req, res) { }); }, function(err, result) { if (err) { - return common.handleErrors(err, res); + return self.common.handleErrors(err, res); } res.jsonp(_.zipObject(result)); }); diff --git a/test/blocks.js b/test/blocks.js index 2836d73..88073c9 100644 --- a/test/blocks.js +++ b/test/blocks.js @@ -72,6 +72,7 @@ describe('Blocks', function() { var bitcoreBlock = bitcore.Block.fromBuffer(new Buffer(blocks['0000000000000afa0c3c0afd450c793a1e300ec84cbe9555166e06132f19a8f7'], 'hex')); var node = { + log: sinon.stub(), getBlock: sinon.stub().callsArgWith(1, null, bitcoreBlock), services: { bitcoind: { @@ -105,6 +106,7 @@ describe('Blocks', function() { it('block pool info should be correct', function(done) { var block = bitcore.Block.fromString(blocks['000000000000000004a118407a4e3556ae2d5e882017e7ce526659d8073f13a4']); var node = { + log: sinon.stub(), getBlock: sinon.stub().callsArgWith(1, null, block), services: { bitcoind: { @@ -183,6 +185,7 @@ describe('Blocks', function() { '000000000008fbb2e358e382a6f6948b2da24563bba183af447e6e2542e8efc7' ]; var node = { + log: sinon.stub(), services: { bitcoind: { getRawBlock: stub, @@ -217,6 +220,7 @@ describe('Blocks', function() { describe('/block-index/:height route', function() { var node = { + log: sinon.stub(), services: { bitcoind: { getBlockHeader: function(height, callback) { @@ -252,7 +256,10 @@ describe('Blocks', function() { }); describe('#getBlockReward', function() { - var blocks = new BlockController({}); + var node = { + log: sinon.stub() + }; + var blocks = new BlockController({node: node}); it('should give a block reward of 50 * 1e8 for block before first halvening', function() { blocks.getBlockReward(100000).should.equal(50 * 1e8); diff --git a/test/index.js b/test/index.js index 2d8e5da..4975877 100644 --- a/test/index.js +++ b/test/index.js @@ -7,8 +7,12 @@ var InsightAPI = require('../lib/index'); describe('Index', function() { describe('#cache', function() { it('will set cache control header', function(done) { + var node = { + log: sinon.stub() + }; var index = new InsightAPI({ - enableCache: true + enableCache: true, + node: node }); var req = {}; var res = { @@ -23,8 +27,12 @@ describe('Index', function() { }); }); it('will NOT set cache control header', function(done) { + var node = { + log: sinon.stub() + }; var index = new InsightAPI({ - enableCache: false + enableCache: false, + node: node }); var req = {}; var res = { @@ -39,9 +47,13 @@ describe('Index', function() { }); describe('#cacheShort', function() { it('will set SHORT cache control header', function(done) { + var node = { + log: sinon.stub() + }; var index = new InsightAPI({ enableCache: true, - cacheShortSeconds: 35 + cacheShortSeconds: 35, + node: node }); var req = {}; var res = { @@ -56,8 +68,12 @@ describe('Index', function() { }); }); it('will set SHORT DEFAULT cache control header', function(done) { + var node = { + log: sinon.stub() + }; var index = new InsightAPI({ - enableCache: true + enableCache: true, + node: node }); var req = {}; var res = { @@ -74,9 +90,13 @@ describe('Index', function() { }); describe('#cacheLong', function() { it('will set LONG cache control header', function(done) { + var node = { + log: sinon.stub() + }; var index = new InsightAPI({ enableCache: true, - cacheLongSeconds: 86400000 + cacheLongSeconds: 86400000, + node: node }); var req = {}; var res = { @@ -91,8 +111,12 @@ describe('Index', function() { }); }); it('will set LONG DEFAULT cache control header', function(done) { + var node = { + log: sinon.stub() + }; var index = new InsightAPI({ - enableCache: true + enableCache: true, + node: node }); var req = {}; var res = {