Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[master] fix: improve influx cardinality #1011

Merged
merged 14 commits into from
Dec 8, 2022
11 changes: 8 additions & 3 deletions src/services/metrics-recorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { Point, WriteApi } from '@influxdata/influxdb-client'

import { BLOCK_TIMING_ERROR, CheckMethods } from '../utils/constants'
import { CherryPicker } from './cherry-picker'
const os = require('os')
const logger = require('../services/logger')

export class MetricsRecorder {
Expand Down Expand Up @@ -191,15 +190,21 @@ export class MetricsRecorder {
// Redis timestamp for bulk logs
const redisTimestamp = Math.floor(new Date().getTime() / 1000)

// Reduce multi-method calls for metrics/logging purposes
let simplifiedMethod = method

if (method && method.split(',').length > 1) {
simplifiedMethod = 'multiple'
}

// InfluxDB
const pointRelay = new Point('relay')
.tag('applicationPublicKey', applicationPublicKey)
.tag('nodePublicKey', serviceNode && !fallback ? 'network' : 'fallback')
.tag('method', method)
.tag('method', simplifiedMethod)
.tag('result', result.toString())
.tag('blockchain', blockchainID) // 0021
.tag('blockchainSubdomain', blockchain) // eth-mainnet
.tag('host', os.hostname())
.tag('region', process.env.REGION || '')
.floatField('bytes', bytes)
.floatField('elapsedTime', elapsedTime.toFixed(4))
Expand Down
146 changes: 146 additions & 0 deletions tests/unit/metrics-recorder.unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { Pool } from 'pg'
import sinon from 'sinon'
import { InfluxDB, Point, WriteApi } from '@influxdata/influxdb-client'
import { Cache } from '../../src/services/cache'
import { CherryPicker } from '../../src/services/cherry-picker'
import { MetricsRecorder } from '../../src/services/metrics-recorder'

// import { metricsRecorderMock } from '../mocks/metrics-recorder'

const Redis = require('ioredis-mock')

describe('Metrics Recorder (unit)', () => {
let cache: Cache
let pgPool: Pool
let influxClient: InfluxDB
let influxWriteApi: WriteApi
let writeInfluxSpy: sinon.SinonSpy
let cherryPicker: CherryPicker
let metricsRecorder: MetricsRecorder

before('Initialize variables', async () => {
cache = new Cache(new Redis(0, ''), new Redis(1, ''))
pgPool = new Pool({ connectionString: 'database1' })
cherryPicker = new CherryPicker({ redis: cache.remote, checkDebug: false })

// InfluxDB Mocking
influxClient = new InfluxDB({ url: 'https://url.com', token: 'token' })
influxWriteApi = influxClient.getWriteApi('org', 'bucket')

sinon.stub(pgPool)
})

beforeEach('Setting up mock metrics recorder', async () => {
writeInfluxSpy = sinon.spy(influxWriteApi, 'writePoint')
influxWriteApi.writePoint = writeInfluxSpy

// Mocked Metrics Recorder
metricsRecorder = new MetricsRecorder({
redis: cache.remote,
pgPool,
influxWriteAPIs: [influxWriteApi],
cherryPicker,
processUID: '1234',
})
})

afterEach(() => {
sinon.restore()
})

it('Should reduce multi-method calls for metrics/logging purposes', async () => {
await metricsRecorder
.recordMetric({
requestID: '',
applicationID: '',
applicationPublicKey: 'app-pub-key',
blockchain: 'eth-mainnet',
blockchainID: '0021',
serviceNode: 'node-xyz',
relayStart: [0, 1],
result: 500,
bytes: 5,
fallback: false,
method: 'eth_getBlockByNumber,eth_getBlockByNumber,eth_getBlockByNumber',
error: '',
code: String(''),
session: {
blockHeight: 0,
header: {
applicationPubKey: '',
chain: '',
sessionBlockHeight: 2,
},
key: '',
nodes: [],
},
origin: 'my-origin',
sticky: '',
gigastakeAppID: '',
url: '',
})
.then(() => {
sinon.assert.calledTwice(writeInfluxSpy)

const pointRelay = new Point('relay')
.tag('applicationPublicKey', 'app-pub-key')
.tag('nodePublicKey', 'network')
.tag('method', 'multiple')
.tag('result', '500')
.tag('blockchain', '0021') // 0021
.tag('blockchainSubdomain', 'eth-mainnet') // eth-mainnet
.tag('region', process.env.REGION || '')
.floatField('bytes', 5)

sinon.assert.calledWith(writeInfluxSpy.firstCall, sinon.match(pointRelay))
})
})

it('Should not reduce single method call for metrics/logging purposes', async () => {
await metricsRecorder
.recordMetric({
requestID: '',
applicationID: '',
applicationPublicKey: 'app-pub-key',
blockchain: 'eth-mainnet',
blockchainID: '0021',
serviceNode: 'node-xyz',
relayStart: [0, 1],
result: 500,
bytes: 5,
fallback: false,
method: 'eth_getBlockByNumber',
error: '',
code: String(''),
session: {
blockHeight: 0,
header: {
applicationPubKey: '',
chain: '',
sessionBlockHeight: 2,
},
key: '',
nodes: [],
},
origin: 'my-origin',
sticky: '',
gigastakeAppID: '',
url: '',
})
.then(() => {
sinon.assert.calledTwice(writeInfluxSpy)

const pointRelay = new Point('relay')
.tag('applicationPublicKey', 'app-pub-key')
.tag('nodePublicKey', 'network')
.tag('method', 'eth_getBlockByNumber')
.tag('result', '500')
.tag('blockchain', '0021') // 0021
.tag('blockchainSubdomain', 'eth-mainnet') // eth-mainnet
.tag('region', process.env.REGION || '')
.floatField('bytes', 5)

sinon.assert.calledWith(writeInfluxSpy.firstCall, sinon.match(pointRelay))
})
})
})