From cff0e89b0d9770f812e8b60c5139774e2084c169 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 17 Mar 2026 16:19:36 -0700 Subject: [PATCH] Reducing logging noise for common errors --- dev-docs/update-logs/2026-03-17.md | 18 +++++++++- src/adapters/fulcrum-api.js | 36 +++++++++++++++++-- .../rest-api/fulcrum/controller.js | 26 +++++++++++--- src/use-cases/fulcrum-use-cases.js | 11 ++---- 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/dev-docs/update-logs/2026-03-17.md b/dev-docs/update-logs/2026-03-17.md index 08bdf62..710707b 100644 --- a/dev-docs/update-logs/2026-03-17.md +++ b/dev-docs/update-logs/2026-03-17.md @@ -2,7 +2,7 @@ ## Summary -Enhanced REST request logging to capture client network identity in Winston logs and enabled proxy-aware IP resolution. +Enhanced REST request logging to capture client network identity in Winston logs, enabled proxy-aware IP resolution, and reduced Fulcrum error-log noise for expected missing-transaction requests. ## Changes Made @@ -12,6 +12,19 @@ Enhanced REST request logging to capture client network identity in Winston logs - Added structured Winston metadata fields to request logs: - `client_ip` from `req.ip` - `remote_address` from `req.socket.remoteAddress` +- Updated `src/adapters/fulcrum-api.js`: + - Added parsing helpers to normalize Fulcrum error messages from multiple response shapes. + - Mapped common daemon missing-TX error (`No such mempool or blockchain transaction`) to: + - status `404` + - message `Transaction not found` +- Updated `src/use-cases/fulcrum-use-cases.js`: + - Removed duplicate error logging in `getTransactionDetails()` and now rethrows adapter errors without a second error-level log. +- Updated `src/controllers/rest-api/fulcrum/controller.js`: + - Added TXID validation (`64`-character hex) for `GET /v6/fulcrum/tx/data/:txid`. + - Updated `handleError()` logging policy: + - `Transaction not found` (`404`) logs at `info` + - other `4xx` logs at `warn` + - `5xx` logs at `error` ## Useful Fields Available for REST Request Logging @@ -58,3 +71,6 @@ Enhanced REST request logging to capture client network identity in Winston logs - Request logs now preserve existing behavior while adding IP attribution fields. - `trust proxy` ensures `req.ip` is proxy-aware when the server is deployed behind a reverse proxy. - The project now has a documented list of high-value request fields for future logging expansion. +- Fulcrum missing-transaction lookups now return cleaner API semantics (`404 Transaction not found`). +- Duplicate error logs for a single missing TX lookup were removed. +- Invalid TXIDs are rejected early with a `400` validation error. diff --git a/src/adapters/fulcrum-api.js b/src/adapters/fulcrum-api.js index d39a7f7..fd2c744 100644 --- a/src/adapters/fulcrum-api.js +++ b/src/adapters/fulcrum-api.js @@ -65,17 +65,28 @@ class FulcrumAPIAdapter { // Attempt to extract error message from response data if (err.response && err.response.data) { const data = err.response.data + const status = err.response.status || 400 + const message = this._extractErrorMessage(data) + + if (this._isCommonMissingTxError(message)) { + return this._formatError('Transaction not found', 404) + } + + if (message) { + return this._formatError(message, status) + } + // Handle structured error responses if (data.error) { - return this._formatError(data.error, err.response.status || 400) + return this._formatError(data.error, status) } // Handle string error messages if (typeof data === 'string') { - return this._formatError(data, err.response.status || 400) + return this._formatError(data, status) } // Handle object responses that might contain error info if (typeof data === 'object' && data.message) { - return this._formatError(data.message, err.response.status || 400) + return this._formatError(data.message, status) } // Fallback to returning the status return this._formatError('Fulcrum API error', err.response.status || 500) @@ -119,6 +130,25 @@ class FulcrumAPIAdapter { status: status || 500 } } + + _extractErrorMessage (data) { + if (!data) return '' + + if (typeof data === 'string') return data + + if (typeof data === 'object') { + if (typeof data.error === 'string') return data.error + if (data.error && typeof data.error === 'object' && data.error.message) return data.error.message + if (data.message) return data.message + } + + return '' + } + + _isCommonMissingTxError (message = '') { + return typeof message === 'string' && + message.includes('No such mempool or blockchain transaction') + } } export default FulcrumAPIAdapter diff --git a/src/controllers/rest-api/fulcrum/controller.js b/src/controllers/rest-api/fulcrum/controller.js index f6e6d45..dd88d63 100644 --- a/src/controllers/rest-api/fulcrum/controller.js +++ b/src/controllers/rest-api/fulcrum/controller.js @@ -87,6 +87,16 @@ class FulcrumRESTController { return cashAddr } + _isValidTxid (txid) { + return typeof txid === 'string' && /^[a-fA-F0-9]{64}$/.test(txid) + } + + _isCommonMissingTxError (err) { + return err?.status === 404 && + typeof err?.message === 'string' && + err.message.includes('Transaction not found') + } + /** * @api {get} /v6/fulcrum/balance/:address Get balance for a single address * @apiName GetBalance @@ -239,10 +249,10 @@ class FulcrumRESTController { try { const txid = req.params.txid - if (typeof txid !== 'string') { + if (!this._isValidTxid(txid)) { return res.status(400).json({ success: false, - error: 'txid must be a string' + error: 'txid must be a 64-character hex string' }) } @@ -575,9 +585,17 @@ class FulcrumRESTController { } handleError (err, res) { - wlogger.error('Error in FulcrumRESTController:', err) - const status = err.status || 500 + const isCommonMissingTxError = this._isCommonMissingTxError(err) + + if (isCommonMissingTxError) { + wlogger.info(`Fulcrum transaction not found: ${err.message}`) + } else if (status >= 500) { + wlogger.error('Error in FulcrumRESTController:', err) + } else { + wlogger.warn(`Fulcrum client error (${status}): ${err.message}`) + } + const message = err.message || 'Internal server error' return res.status(status).json({ error: message }) diff --git a/src/use-cases/fulcrum-use-cases.js b/src/use-cases/fulcrum-use-cases.js index 9a0e90a..1a9c833 100644 --- a/src/use-cases/fulcrum-use-cases.js +++ b/src/use-cases/fulcrum-use-cases.js @@ -62,14 +62,9 @@ class FulcrumUseCases { } async getTransactionDetails ({ txid }) { - try { - const response = await this.fulcrum.get(`electrumx/tx/data/${txid}`) - // console.log(`getTransactionDetails() TXID ${txid}: ${JSON.stringify(response, null, 2)}`) - return response - } catch (err) { - wlogger.error('Error in FulcrumUseCases.getTransactionDetails()', err) - throw err - } + const response = await this.fulcrum.get(`electrumx/tx/data/${txid}`) + // console.log(`getTransactionDetails() TXID ${txid}: ${JSON.stringify(response, null, 2)}`) + return response } async getTransactionDetailsBulk ({ txids, verbose }) {