log errors to redis

This commit is contained in:
smart_ex 2022-04-11 14:16:57 +10:00 committed by Danil Kovtonyuk
parent 5b2815e6a0
commit 7d8a6dc30f
11 changed files with 69 additions and 42 deletions

@ -1,4 +1,4 @@
const { getTornadoWithdrawInputError } = require('./validator') const { getTornadoWithdrawInputError } = require('./modules/validator')
const { postJob } = require('./queue') const { postJob } = require('./queue')
const { jobType } = require('./constants') const { jobType } = require('./constants')

@ -1,12 +1,10 @@
const Web3 = require('web3') const Web3 = require('web3')
const Redis = require('ioredis')
const { toBN, fromWei } = require('web3-utils') const { toBN, fromWei } = require('web3-utils')
const { setSafeInterval } = require('./utils') const { setSafeInterval } = require('./utils')
const { redisUrl, httpRpcUrl, privateKey, minimumBalance, nativeCurrency, instances } = require('./config') const { httpRpcUrl, privateKey, minimumBalance, nativeCurrency, instances } = require('./config')
const web3 = new Web3(httpRpcUrl) const web3 = new Web3(httpRpcUrl)
const redis = new Redis(redisUrl) const { redis } = require('modules/redis')
async function main() { async function main() {
try { try {

9
src/modules/redis.js Normal file

@ -0,0 +1,9 @@
const { createClient } = require('ioredis')
const { redisUrl } = require('../config')
const redis = createClient(redisUrl)
module.exports = {
redis,
redisUrl,
}

@ -1,6 +1,6 @@
const { isAddress, toChecksumAddress } = require('web3-utils') const { isAddress, toChecksumAddress } = require('web3-utils')
const { getInstance } = require('./utils') const { getInstance } = require('../utils')
const { rewardAccount } = require('./config') const { rewardAccount } = require('../config')
const Ajv = require('ajv') const Ajv = require('ajv')
const ajv = new Ajv({ format: 'fast' }) const ajv = new Ajv({ format: 'fast' })

@ -1,9 +1,7 @@
const { v4: uuid } = require('uuid') const { v4: uuid } = require('uuid')
const Queue = require('bull') const Queue = require('bull')
const Redis = require('ioredis')
const { redisUrl } = require('./config')
const { status } = require('./constants') const { status } = require('./constants')
const redis = new Redis(redisUrl) const { redis, redisUrl } = require('./modules/redis')
const queue = new Queue('proofs', redisUrl, { const queue = new Queue('proofs', redisUrl, {
lockDuration: 300000, // Key expiration time for job locks. lockDuration: 300000, // Key expiration time for job locks.

27
src/router.js Normal file

@ -0,0 +1,27 @@
const { controller, status } = require('./contollers')
const router = require('express').Router()
// Add CORS headers
router.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
next()
})
// Log error to console but don't send it to the client to avoid leaking data
router.use((err, req, res, next) => {
if (err) {
console.error(err)
return res.sendStatus(500)
}
next()
})
router.get('/', status.index)
router.get('/v1/status', status.status)
router.get('/v1/jobs/:id', status.getJob)
router.post('/v1/tornadoWithdraw', controller.tornadoWithdraw)
router.get('/status', status.status)
router.post('/relay', controller.tornadoWithdraw)
module.exports = router

@ -1,39 +1,16 @@
const express = require('express') const express = require('express')
const status = require('./status') const router = require('./router')
const controller = require('./controller')
const { port, rewardAccount } = require('./config') const { port, rewardAccount } = require('./config')
const { version } = require('../package.json') const { version } = require('../package.json')
const { isAddress } = require('web3-utils') const { isAddress } = require('web3-utils')
const app = express()
app.use(express.json())
// Add CORS headers
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
next()
})
// Log error to console but don't send it to the client to avoid leaking data
app.use((err, req, res, next) => {
if (err) {
console.error(err)
return res.sendStatus(500)
}
next()
})
app.get('/', status.index)
app.get('/v1/status', status.status)
app.get('/v1/jobs/:id', status.getJob)
app.post('/v1/tornadoWithdraw', controller.tornadoWithdraw)
app.get('/status', status.status)
app.post('/relay', controller.tornadoWithdraw)
if (!isAddress(rewardAccount)) { if (!isAddress(rewardAccount)) {
throw new Error('No REWARD_ACCOUNT specified') throw new Error('No REWARD_ACCOUNT specified')
} }
const app = express()
app.use(express.json())
app.use(router)
app.listen(port) app.listen(port)
console.log(`Relayer ${version} started on port ${port}`) console.log(`Relayer ${version} started on port ${port}`)

@ -2,11 +2,12 @@ const queue = require('./queue')
const { netId, tornadoServiceFee, instances, redisUrl, rewardAccount } = require('./config') const { netId, tornadoServiceFee, instances, redisUrl, rewardAccount } = require('./config')
const { version } = require('../package.json') const { version } = require('../package.json')
const Redis = require('ioredis') const Redis = require('ioredis')
const { readRelayerErrors } = require('./utils')
const redis = new Redis(redisUrl) const redis = new Redis(redisUrl)
async function status(req, res) { async function status(req, res) {
const health = await redis.hgetall('health') const health = await redis.hgetall('health')
health.errorsLog = readRelayerErrors(redis)
const { waiting: currentQueue } = await queue.queue.getJobCounts() const { waiting: currentQueue } = await queue.queue.getJobCounts()
res.json({ res.json({

@ -70,8 +70,24 @@ function fromDecimals(value, decimals) {
return new BN(wei.toString(10), 10) return new BN(wei.toString(10), 10)
} }
const logRelayerError = async (redis, e) => {
await redis.zadd('errors', 'INCR', 1, e.message)
}
const readRelayerErrors = async redis => {
const set = await redis.zrevrange('errors', 0, -1, 'WITHSCORES')
const errors = []
while (set.length) {
const [message, score] = set.splice(0, 2)
errors.push({ message, score })
}
return errors
}
module.exports = { module.exports = {
getInstance, getInstance,
setSafeInterval, setSafeInterval,
fromDecimals, fromDecimals,
logRelayerError,
readRelayerErrors,
} }

@ -1,10 +1,10 @@
const Web3 = require('web3') const Web3 = require('web3')
const { GasPriceOracle } = require('gas-price-oracle') const { GasPriceOracle } = require('gas-price-oracle')
const { toBN, toWei, fromWei, toHex } = require('web3-utils') const { toBN, toWei, fromWei, toHex } = require('web3-utils')
const { redis } = require('modules/redis')
const proxyLightABI = require('../abis/proxyLightABI.json') const proxyLightABI = require('../abis/proxyLightABI.json')
const { queue } = require('./queue') const { queue } = require('./queue')
const { getInstance, fromDecimals } = require('./utils') const { getInstance, fromDecimals, logRelayerError } = require('./utils')
const { jobType, status } = require('./constants') const { jobType, status } = require('./constants')
const { const {
netId, netId,
@ -46,6 +46,7 @@ function start() {
queue.process(processJob) queue.process(processJob)
console.log('Worker started') console.log('Worker started')
} catch (e) { } catch (e) {
logRelayerError(redis, e.message)
console.error('error on start worker', e.message) console.error('error on start worker', e.message)
} }
} }

@ -1,6 +1,6 @@
require('chai').should() require('chai').should()
const { getTornadoWithdrawInputError } = require('../src/validator') const { getTornadoWithdrawInputError } = require('../src/modules/validator')
describe('Validator', () => { describe('Validator', () => {
describe('#getTornadoWithdrawInputError', () => { describe('#getTornadoWithdrawInputError', () => {