chore: Add ability to capture sampler metrics (#374)
* chore: Add ability to capture sampler metrics * Added block number metrics
This commit is contained in:
committed by
Noah Khamliche
parent
c4ab263aa1
commit
5d7368fb17
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "16.38.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Capture sampler metrics",
|
||||
"pr": 374
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "16.37.0",
|
||||
"changes": [
|
||||
|
||||
@@ -77,4 +77,19 @@ contract UtilitySampler {
|
||||
assembly { size := extcodesize(account) }
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
function getGasLeft()
|
||||
public
|
||||
returns (uint256)
|
||||
{
|
||||
return gasleft();
|
||||
}
|
||||
|
||||
function getBlockNumber()
|
||||
public
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return block.number;
|
||||
}
|
||||
}
|
||||
@@ -113,6 +113,7 @@ export {
|
||||
SwapQuoterError,
|
||||
SwapQuoterOpts,
|
||||
SwapQuoterRfqOpts,
|
||||
SamplerMetrics,
|
||||
} from './types';
|
||||
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
||||
export {
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
OptimizedMarketOrder,
|
||||
TokenAdjacencyGraph,
|
||||
} from './utils/market_operation_utils/types';
|
||||
export { SamplerMetrics } from './utils/market_operation_utils/types';
|
||||
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator';
|
||||
import { MetricsProxy } from './utils/quote_requestor';
|
||||
|
||||
|
||||
@@ -158,6 +158,8 @@ export class MarketOperationUtils {
|
||||
|
||||
// Call the sampler contract.
|
||||
const samplerPromise = this._sampler.executeAsync(
|
||||
this._sampler.getBlockNumber(),
|
||||
this._sampler.getGasLeft(),
|
||||
this._sampler.getTokenDecimals([makerToken, takerToken]),
|
||||
// Get native order fillable amounts.
|
||||
this._sampler.getLimitOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
||||
@@ -184,6 +186,7 @@ export class MarketOperationUtils {
|
||||
takerAmount,
|
||||
),
|
||||
this._sampler.isAddressContract(txOrigin),
|
||||
this._sampler.getGasLeft(),
|
||||
);
|
||||
|
||||
// Refresh the cached pools asynchronously if required
|
||||
@@ -191,6 +194,8 @@ export class MarketOperationUtils {
|
||||
|
||||
const [
|
||||
[
|
||||
blockNumber,
|
||||
gasBefore,
|
||||
tokenDecimals,
|
||||
orderFillableTakerAmounts,
|
||||
outputAmountPerEth,
|
||||
@@ -198,9 +203,14 @@ export class MarketOperationUtils {
|
||||
dexQuotes,
|
||||
rawTwoHopQuotes,
|
||||
isTxOriginContract,
|
||||
gasAfter,
|
||||
],
|
||||
] = await Promise.all([samplerPromise]);
|
||||
|
||||
// Log the gas metrics
|
||||
_opts.samplerMetrics?.logGasDetails({ gasBefore, gasAfter });
|
||||
_opts.samplerMetrics?.logBlockNumber(blockNumber);
|
||||
|
||||
// Filter out any invalid two hop quotes where we couldn't find a route
|
||||
const twoHopQuotes = rawTwoHopQuotes.filter(
|
||||
q => q && q.fillData && q.fillData.firstHopSource && q.fillData.secondHopSource,
|
||||
|
||||
@@ -130,6 +130,37 @@ export class DexOrderSampler extends SamplerOperations {
|
||||
BatchedOperationResult<T8>
|
||||
]>;
|
||||
|
||||
// prettier-ignore
|
||||
public async executeAsync<
|
||||
T1, T2, T3, T4, T5, T6, T7, T8, T9
|
||||
>(...ops: [T1, T2, T3, T4, T5, T6, T7, T8, T9]): Promise<[
|
||||
BatchedOperationResult<T1>,
|
||||
BatchedOperationResult<T2>,
|
||||
BatchedOperationResult<T3>,
|
||||
BatchedOperationResult<T4>,
|
||||
BatchedOperationResult<T5>,
|
||||
BatchedOperationResult<T6>,
|
||||
BatchedOperationResult<T7>,
|
||||
BatchedOperationResult<T8>,
|
||||
BatchedOperationResult<T9>
|
||||
]>;
|
||||
|
||||
// prettier-ignore
|
||||
public async executeAsync<
|
||||
T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
|
||||
>(...ops: [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]): Promise<[
|
||||
BatchedOperationResult<T1>,
|
||||
BatchedOperationResult<T2>,
|
||||
BatchedOperationResult<T3>,
|
||||
BatchedOperationResult<T4>,
|
||||
BatchedOperationResult<T5>,
|
||||
BatchedOperationResult<T6>,
|
||||
BatchedOperationResult<T7>,
|
||||
BatchedOperationResult<T8>,
|
||||
BatchedOperationResult<T9>,
|
||||
BatchedOperationResult<T10>,
|
||||
]>;
|
||||
|
||||
/**
|
||||
* Run a series of operations from `DexOrderSampler.ops` in a single transaction.
|
||||
*/
|
||||
|
||||
@@ -158,6 +158,30 @@ export class SamplerOperations {
|
||||
};
|
||||
}
|
||||
|
||||
public getGasLeft(): BatchedOperation<BigNumber> {
|
||||
return {
|
||||
encodeCall: () => this._samplerContract.getGasLeft().getABIEncodedTransactionData(),
|
||||
handleCallResults: (callResults: string) =>
|
||||
this._samplerContract.getABIDecodedReturnData<BigNumber>('getGasLeft', callResults),
|
||||
handleRevert: () => {
|
||||
/* should never happen */
|
||||
throw new Error('Invalid result for getGasLeft');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public getBlockNumber(): BatchedOperation<BigNumber> {
|
||||
return {
|
||||
encodeCall: () => this._samplerContract.getBlockNumber().getABIEncodedTransactionData(),
|
||||
handleCallResults: (callResults: string) =>
|
||||
this._samplerContract.getABIDecodedReturnData<BigNumber>('getBlockNumber', callResults),
|
||||
handleRevert: () => {
|
||||
/* should never happen */
|
||||
throw new Error('Invalid result for getBlockNumber');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public getLimitOrderFillableTakerAmounts(
|
||||
orders: SignedNativeOrder[],
|
||||
exchangeAddress: string,
|
||||
|
||||
@@ -469,6 +469,28 @@ export interface GetMarketOrdersOpts {
|
||||
* Gas price to use for quote
|
||||
*/
|
||||
gasPrice: BigNumber;
|
||||
|
||||
/**
|
||||
* Sampler metrics for recording data on the sampler service and operations
|
||||
*/
|
||||
samplerMetrics?: SamplerMetrics;
|
||||
}
|
||||
|
||||
export interface SamplerMetrics {
|
||||
/**
|
||||
* Logs the gas information performed during a sampler call.
|
||||
*
|
||||
* @param data.gasBefore The gas remaining measured before any operations have been performed
|
||||
* @param data.gasAfter The gas remaining measured after all operations have been performed
|
||||
*/
|
||||
logGasDetails(data: { gasBefore: BigNumber; gasAfter: BigNumber }): void;
|
||||
|
||||
/**
|
||||
* Logs the block number
|
||||
*
|
||||
* @param blockNumber block number of the sampler call
|
||||
*/
|
||||
logBlockNumber(blockNumber: BigNumber): void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
POSITIVE_INF,
|
||||
SELL_SOURCE_FILTER_BY_CHAIN_ID,
|
||||
SOURCE_FLAGS,
|
||||
ZERO_AMOUNT,
|
||||
} from '../src/utils/market_operation_utils/constants';
|
||||
import { createFills } from '../src/utils/market_operation_utils/fills';
|
||||
import { PoolsCache } from '../src/utils/market_operation_utils/pools_cache';
|
||||
@@ -427,6 +428,8 @@ describe('MarketOperationUtils tests', () => {
|
||||
getTwoHopSellQuotes: (..._params: any[]) => [],
|
||||
getTwoHopBuyQuotes: (..._params: any[]) => [],
|
||||
isAddressContract: (..._params: any[]) => false,
|
||||
getGasLeft: () => ZERO_AMOUNT,
|
||||
getBlockNumber: () => ZERO_AMOUNT,
|
||||
};
|
||||
|
||||
const MOCK_SAMPLER = ({
|
||||
|
||||
Reference in New Issue
Block a user