From ca4865d8f252fb165a92a870e84b94535b860f92 Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 18 Sep 2023 17:14:50 +0200 Subject: [PATCH] adding cloudwatch metrics --- modules/metrics/sor.metric.ts | 11 +++++++++ modules/sor/sor.service.ts | 42 +++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 modules/metrics/sor.metric.ts diff --git a/modules/metrics/sor.metric.ts b/modules/metrics/sor.metric.ts new file mode 100644 index 000000000..a066293a4 --- /dev/null +++ b/modules/metrics/sor.metric.ts @@ -0,0 +1,11 @@ +import { CloudwatchMetricsPublisher } from './metrics.client'; + +const publishers: Record = {}; + +export function getSorMetricsPublisher(chainId: string): CloudwatchMetricsPublisher { + if (!publishers[`${chainId}`]) { + console.log(`Creating new SOR publisher for ${chainId}`); + publishers[`${chainId}`] = new CloudwatchMetricsPublisher(`Backend-${chainId}/Sor`); + } + return publishers[`${chainId}`]; +} diff --git a/modules/sor/sor.service.ts b/modules/sor/sor.service.ts index d28f8309e..b6673474b 100644 --- a/modules/sor/sor.service.ts +++ b/modules/sor/sor.service.ts @@ -5,6 +5,8 @@ import { sorV1BeetsService } from './sorV1Beets/sorV1Beets.service'; import { sorV2Service } from './sorV2/sorV2.service'; import { GetSwapsInput, SwapResult } from './types'; import { EMPTY_COWSWAP_RESPONSE } from './constants'; +import { getSorMetricsPublisher } from '../metrics/sor.metric'; +import moment from 'moment'; export class SorService { public async getCowSwaps({ @@ -32,7 +34,7 @@ export class SorService { if (!swapV1.isValid && !swapV2.isValid) return EMPTY_COWSWAP_RESPONSE(tokenIn, tokenOut, swapAmount); - const bestSwap = this.getBestSwap(swapV1, swapV2, swapType, tokenIn, tokenOut); + const bestSwap = await this.getBestSwap(swapV1, swapV2, swapType, tokenIn, tokenOut); try { // Updates with latest onchain data before returning @@ -48,20 +50,33 @@ export class SorService { input: GetSwapsInput & { swapOptions: GqlSorSwapOptionsInput }, ): Promise { console.time(`sorV1-${networkContext.chain}`); + const v1Start = moment().unix(); const swapV1 = await sorV1BeetsService.getSwapResult(input); + const v1End = moment().unix(); console.timeEnd(`sorV1-${networkContext.chain}`); + console.time(`sorV2-${networkContext.chain}`); + const v2Start = moment().unix(); const swapV2 = await sorV2Service.getSwapResult(input); + const v2End = moment().unix(); console.timeEnd(`sorV2-${networkContext.chain}`); + const sorMetricsPublisher = await getSorMetricsPublisher(networkContext.chain); + + sorMetricsPublisher.publish(`SOR_TIME_V1_${input.tokenIn}_${input.tokenOut}`, v1End - v1Start); + sorMetricsPublisher.publish(`SOR_TIME_V2_${input.tokenIn}_${input.tokenOut}`, v2End - v2Start); + + sorMetricsPublisher.publish(`SOR_VALID_V1_${input.tokenIn}_${input.tokenOut}`, swapV1.isValid ? 1 : 0); + sorMetricsPublisher.publish(`SOR_VALID_V2_${input.tokenIn}_${input.tokenOut}`, swapV2.isValid ? 1 : 0); + if (!swapV1.isValid && !swapV2.isValid) return sorV1BeetsService.zeroResponse(input.swapType, input.tokenIn, input.tokenOut, input.swapAmount); - const bestSwap = this.getBestSwap(swapV1, swapV2, input.swapType, input.tokenIn, input.tokenOut); + const bestSwap = await this.getBestSwap(swapV1, swapV2, input.swapType, input.tokenIn, input.tokenOut); try { // Updates with latest onchain data before returning - return await bestSwap.getBeetsSwapResponse(true); + return bestSwap.getBeetsSwapResponse(true); } catch (err) { console.log(`Error Retrieving QuerySwap`); console.log(err); @@ -76,14 +91,14 @@ export class SorService { * @param swapType * @returns */ - private getBestSwap( + private async getBestSwap( v1: SwapResult, v2: SwapResult, swapType: GqlSorSwapType, assetIn: string, assetOut: string, debugOut = false, - ): SwapResult { + ): Promise { // Useful for comparing if (debugOut) { console.log(`------ DEBUG`); @@ -105,15 +120,15 @@ export class SorService { } if (isV1 === true) { - this.logResult(`V1`, v1, v2, swapType, assetIn, assetOut); + await this.logResult(`V1`, v1, v2, swapType, assetIn, assetOut); return v1; } else { - this.logResult(`V2`, v1, v2, swapType, assetIn, assetOut); + await this.logResult(`V2`, v1, v2, swapType, assetIn, assetOut); } return v2; } - private logResult( + private async logResult( logType: string, v1: SwapResult, v2: SwapResult, @@ -122,8 +137,13 @@ export class SorService { assetOut: string, ) { // console.log() will log to cloudwatch + const sorMetricsPublisher = await getSorMetricsPublisher(networkContext.chain); if (swapType === 'EXACT_IN') { - console.log( + sorMetricsPublisher.publish( + `SOR_EXACT_IN_${assetIn}_${assetOut}`, + Number(v1.outputAmount - v2.outputAmount), + ); + await console.log( 'SOR Service', networkContext.chain, logType, @@ -137,6 +157,10 @@ export class SorService { v1.outputAmount - v2.outputAmount, ); } else { + sorMetricsPublisher.publish( + `SOR_EXACT_OUT_${assetIn}_${assetOut}`, + Number(v1.inputAmount - v2.inputAmount), + ); console.log( 'SOR Service', networkContext.chain,