From e6c701baa1b4c614f3d46668ad724df760d7e6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Walter?= Date: Mon, 18 Dec 2017 14:38:02 +0100 Subject: [PATCH 1/3] add loggly support --- package.json | 5 ++-- src/logger.js | 60 +++++++++++++++++++++++++++++++------- src/output/index.js | 11 +++++-- src/output/logglyFormat.js | 35 ++++++++++++++++++++++ yarn.lock | 56 +++++++++++++++++++++++++++++++---- 5 files changed, 147 insertions(+), 20 deletions(-) create mode 100644 src/output/logglyFormat.js diff --git a/package.json b/package.json index 58a9151..bdfb2fd 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "request": "^2.82.0", "request-promise": "^4.2.1", "web3": "0.19.0", - "winston": "2.3.1", - "yamljs": "^0.3.0" + "winston": "^2.4.0", + "yamljs": "^0.3.0", + "winston-loggly-bulk": "^2.0.1" } } diff --git a/src/logger.js b/src/logger.js index 850087f..7d38dbb 100644 --- a/src/logger.js +++ b/src/logger.js @@ -1,43 +1,83 @@ import winston from 'winston'; + import { getCommandVars } from './command'; +require('winston-loggly-bulk'); + const loggerConsoleOptions = { timestamp: false, colorize: false, formatter: options => `${options.message}`, + json: true, + stringify: true, }; -const logger = new (winston.Logger)({ - transports: [ - new (winston.transports.Console)(loggerConsoleOptions), - ] }); +let logger; + +function getLogger() { + logger = new winston.Logger(); + logger.add(winston.transports.Console, loggerConsoleOptions); + + return logger; +} + +logger = getLogger(); /** -* sets logger level -* @param {string} -*/ + * sets logger level + * @param {string} + */ export const setLoggerLevel = (logLevel) => { logger.transports.console.level = logLevel; }; + +/** + * add loggly transport + * @param token + * @param subdomain + * @param tags + */ +export const setLogglyTransport = (token, subdomain, tags) => { + logger.add(winston.transports.Loggly, { + token, + subdomain, + tags: [tags], + json: true, + }); +}; + /** * This will print out the error as json formatted * @param {*} error * @param {*} customMessage */ export const logError = (error, customMessage = null, isStack = true) => { - switch (getCommandVars('outputType')) { + const commandVars = getCommandVars('outputType'); + switch (commandVars) { case 'terminal': logger.error(customMessage); logger.error(error.message); logger.error(error.stack); break; + case 'loggly': + const json = { + type: 'Error', + message: error.message, + stack: isStack ? error.stack : null, + details: customMessage, + }; + winston.log('error', json); + logger.error(JSON.stringify(json)); + break; case 'graylog': default: - logger.error(JSON.stringify({ type: 'Error', + logger.error(JSON.stringify({ + type: 'Error', message: error.message, stack: isStack ? error.stack : null, - details: customMessage })); + details: customMessage, + })); break; } }; diff --git a/src/output/index.js b/src/output/index.js index 4005403..961424a 100644 --- a/src/output/index.js +++ b/src/output/index.js @@ -1,6 +1,7 @@ import logger from '../logger'; import grayLogFromat from './graylogFormat'; import terminalFormat from './terminalFormat'; +import logglyFormat from './logglyFormat'; export default (data, type = 'terminal') => { switch (type) { @@ -8,10 +9,14 @@ export default (data, type = 'terminal') => { logger.log('info', terminalFormat(data)); break; case 'graylog': - logger.log('info', JSON.stringify(grayLogFromat(data.transaction, - data.decodedInputDataResult, data.decodedLogs))); + logger.log('info', grayLogFromat(data.transaction, + data.decodedInputDataResult, data.decodedLogs)); + break; + case 'loggly': + logger.log('info', logglyFormat(data.transaction, + data.decodedInputDataResult, data.decodedLogs)); break; default: - throw new Error(`${type} output module is undefind`); + throw new Error(`${type} output module is undefined`); } }; diff --git a/src/output/logglyFormat.js b/src/output/logglyFormat.js new file mode 100644 index 0000000..2be1768 --- /dev/null +++ b/src/output/logglyFormat.js @@ -0,0 +1,35 @@ +const formatLogs = (logs) => { + if (!logs) return []; + + return logs.map((log) => { + let eventText = `${log.name}(`; + log.events.forEach((i, idx, events) => { + eventText += `${events[idx].name}=${events[idx].value}`; + if (idx !== events.length - 1) { + eventText += ','; + } + }); + eventText += ')'; + return eventText; + }); +}; +export default (transaction, decodedTransaction, decodedLogs) => ({ + networkId: transaction.networkId, + blockHash: transaction.blockHash, + blockNumber: transaction.blockNumber, + fromAddress: transaction.from, + toAddress: transaction.to, + transactionHash: transaction.hash, + input: transaction.creates ? + decodedTransaction.constructorData : transaction.input, + gas: transaction.gas, + gasPrice: transaction.gasPrice, + status: transaction.status, + value: transaction.value, + transactionType: transaction.contractAddress ? 'Contract Creation' : 'Transaction', + contractAddress: transaction.contractAddress, + methodName: decodedTransaction.name, + methodParameters: decodedTransaction.params, + etherscanLink: `https://etherscan.io/tx/${transaction.hash}`, + events: formatLogs(decodedLogs), +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index dee130c..199d479 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2242,7 +2242,7 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@~5.0.1: +json-stringify-safe@5.0.x, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -2515,6 +2515,10 @@ mocha@^3.5.3: mkdirp "0.5.1" supports-color "3.1.2" +moment@^2.18.1: + version "2.19.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.4.tgz#17e5e2c6ead8819c8ecfad83a0acccb312e94682" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -2552,6 +2556,14 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" +node-loggly-bulk@^2.0.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-loggly-bulk/-/node-loggly-bulk-2.2.1.tgz#c4ee8b0e3c334ecbb744e321f5ffe73f0c3a88d5" + dependencies: + json-stringify-safe "5.0.x" + moment "^2.18.1" + request ">=2.76.0 <3.0.0" + node-pre-gyp@^0.6.36: version "0.6.37" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.37.tgz#3c872b236b2e266e4140578fe1ee88f693323a05" @@ -3055,6 +3067,33 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +"request@>=2.76.0 <3.0.0": + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + request@^2.81.0, request@^2.82.0: version "2.82.0" resolved "https://registry.yarnpkg.com/request/-/request-2.82.0.tgz#2ba8a92cd7ac45660ea2b10a53ae67cd247516ea" @@ -3463,7 +3502,7 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" -tough-cookie@>=2.3.3, tough-cookie@~2.3.0: +tough-cookie@>=2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" dependencies: @@ -3603,9 +3642,16 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -winston@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119" +winston-loggly-bulk@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/winston-loggly-bulk/-/winston-loggly-bulk-2.0.1.tgz#9110858ff51efccae94159355b5519c72fefd8b7" + dependencies: + node-loggly-bulk "^2.0.1" + winston "^2.3.1" + +winston@^2.3.1, winston@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee" dependencies: async "~1.0.0" colors "1.0.x" From 4b9f42c2ddd008a30680d9648ee85b41e4593135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Walter?= Date: Mon, 18 Dec 2017 15:11:34 +0100 Subject: [PATCH 2/3] updated readme and pass options to setLogglyTransport --- README.md | 11 +++++++++++ src/command.js | 10 ++++++++++ src/index.js | 11 +++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 25dc6cc..3e27ade 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,10 @@ ex, `-s ./example-file-path` or `--save-state ./example-file-path`. `-e or --access-token` Etherscan access token, used to access etherscan for ABI importing. +`--loggly-token` Loggly access token +`--loggly-subdomain` Loggly subdomain +`--loggly-tag` Loggly tag + ### ENV Variables Environmental variables come second in priority, you can specify every parameter indicated as an ENV variable. Additionally you can mix between different settings if convenient for your application.In your `.env` you can specify parameters as @@ -66,6 +70,13 @@ Environmental variables come second in priority, you can specify every parameter `ACCESS_TOKEN` +`LOGGLY_ACCESS_TOKEN` + +`LOGGLY_SUB_DOMAIN` + +`LOGGLY_TAG` + + The inputs are very similar to when using CLI only `QUICK_MODE` is different in the sense that it can use true/false values ### Config file diff --git a/src/command.js b/src/command.js index e30a9bf..ab08e7c 100644 --- a/src/command.js +++ b/src/command.js @@ -18,6 +18,10 @@ const defaultSaveState = null; const defaultOutputType = 'terminal'; const defaultAccessToken = ''; +const defaultLogglyAccessToken = ''; +const defaultLogglySubDomain = ''; +const defaultLogglyTag = ''; + const validLoggerValues = ['info', 'error', 'debug']; /** @@ -109,6 +113,9 @@ export default (watchPath) => { .option('-l, --log-level [n]', 'Log level', handelInputValues('LOG_LEVEL', watchConfig.logLevel, defaultLogLevel)) .option('-o,--output-type [n]', 'Output type', handelInputValues('OUTPUT_TYPE', watchConfig.outputType, defaultOutputType)) .option('-e,--access-token [n]', 'etherscan access token', handelInputValues('ACCESS_TOKEN', watchConfig.accessToken, defaultAccessToken)) + .option('--loggly-token,--loggly-token [n]', 'loggly access token', handelInputValues('LOGGLY_ACCESS_TOKEN', watchConfig.logglyAccessToken, defaultLogglyAccessToken)) + .option('--loggly-subdomain,--loggly-subdomain [n]', 'loggly subdomain', handelInputValues('LOGGLY_SUB_DOMAIN', watchConfig.logglySubDomain, defaultLogglySubDomain)) + .option('--loggly-tag,--loggly-tag [n]', 'loggly tag', handelInputValues('LOGGLY_TAG', watchConfig.logglyTag, defaultLogglyTag)) .parse(process.argv); } if (typeof program === 'undefined') { throw new Error(noArgserrorMsg); } @@ -125,6 +132,9 @@ export default (watchPath) => { logLevel: validateParamBasedOnValue(program.logLevel, validLoggerValues, loggererrorMsg), outputType: program.outputType, accessToken: program.accessToken, + logglyAccessToken: program.logglyToken, + logglySubDomain: program.logglySubdomain, + logglyTag: program.logglyTag }; }; diff --git a/src/index.js b/src/index.js index 4c331d8..0717deb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -import logger, { logError, setLoggerLevel } from './logger'; +import logger, { logError, setLoggerLevel, setLogglyTransport } from './logger'; import command, { getCommandVars } from './command'; import Decoder from './decoder'; import { isAddress } from './web3/utils'; @@ -63,8 +63,15 @@ const transactionHandler = async (transaction) => { */ const main = async () => { const { from, to, addresses, quickMode, - lastBlockNumberFilePath, logLevel } = command(); + lastBlockNumberFilePath, logLevel, + logglyAccessToken, + logglySubDomain, + logglyTag + } = command(); + setLoggerLevel(logLevel); + setLogglyTransport(logglyAccessToken, logglySubDomain, logglyTag); + logger.debug('Start process'); addresses.forEach((address) => { if (!isAddress(address)) throw new Error(`Address ${address} is not a valid ethereum address`); }); const PromisifiedAbiObjects = addresses.map(async address => ( From 2fb6f358a3ca0025b4a5ab5e574f6d40ec56faca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Walter?= Date: Tue, 19 Dec 2017 16:25:38 +0100 Subject: [PATCH 3/3] fixing most of eslint error --- src/command.js | 2 +- src/index.js | 2 +- src/output/logglyFormat.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/command.js b/src/command.js index ab08e7c..329865d 100644 --- a/src/command.js +++ b/src/command.js @@ -134,7 +134,7 @@ export default (watchPath) => { accessToken: program.accessToken, logglyAccessToken: program.logglyToken, logglySubDomain: program.logglySubdomain, - logglyTag: program.logglyTag + logglyTag: program.logglyTag, }; }; diff --git a/src/index.js b/src/index.js index 0717deb..675e0e9 100644 --- a/src/index.js +++ b/src/index.js @@ -66,7 +66,7 @@ const main = async () => { lastBlockNumberFilePath, logLevel, logglyAccessToken, logglySubDomain, - logglyTag + logglyTag, } = command(); setLoggerLevel(logLevel); diff --git a/src/output/logglyFormat.js b/src/output/logglyFormat.js index 2be1768..b22dc90 100644 --- a/src/output/logglyFormat.js +++ b/src/output/logglyFormat.js @@ -32,4 +32,4 @@ export default (transaction, decodedTransaction, decodedLogs) => ({ methodParameters: decodedTransaction.params, etherscanLink: `https://etherscan.io/tx/${transaction.hash}`, events: formatLogs(decodedLogs), -}); \ No newline at end of file +});