Merge pull request #2714 from 0xProject/feat/asset-swapper/rfq-maker-blacklist-logging
asset-swapper: log RFQ maker (un)blacklistings
This commit is contained in:
commit
a35d1b8a9d
@ -1,9 +1,10 @@
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber, logUtils } from '@0x/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ExchangeProxyContractOpts,
|
ExchangeProxyContractOpts,
|
||||||
ExtensionContractType,
|
ExtensionContractType,
|
||||||
ForwarderExtensionContractOpts,
|
ForwarderExtensionContractOpts,
|
||||||
|
LogFunction,
|
||||||
OrderPrunerOpts,
|
OrderPrunerOpts,
|
||||||
OrderPrunerPermittedFeeTypes,
|
OrderPrunerPermittedFeeTypes,
|
||||||
RfqtRequestOpts,
|
RfqtRequestOpts,
|
||||||
@ -89,6 +90,11 @@ const DEFAULT_RFQT_REQUEST_OPTS: Partial<RfqtRequestOpts> = {
|
|||||||
makerEndpointMaxResponseTimeMs: 1000,
|
makerEndpointMaxResponseTimeMs: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_INFO_LOGGER: LogFunction = (obj, msg) =>
|
||||||
|
logUtils.log(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`);
|
||||||
|
export const DEFAULT_WARNING_LOGGER: LogFunction = (obj, msg) =>
|
||||||
|
logUtils.warn(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`);
|
||||||
|
|
||||||
export const constants = {
|
export const constants = {
|
||||||
ETH_GAS_STATION_API_URL,
|
ETH_GAS_STATION_API_URL,
|
||||||
PROTOCOL_FEE_MULTIPLIER,
|
PROTOCOL_FEE_MULTIPLIER,
|
||||||
@ -113,4 +119,6 @@ export const constants = {
|
|||||||
PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS,
|
PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS,
|
||||||
MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE,
|
MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE,
|
||||||
BRIDGE_ASSET_DATA_PREFIX: '0xdc1600f3',
|
BRIDGE_ASSET_DATA_PREFIX: '0xdc1600f3',
|
||||||
|
DEFAULT_INFO_LOGGER,
|
||||||
|
DEFAULT_WARNING_LOGGER,
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
TokenAdjacencyGraph,
|
TokenAdjacencyGraph,
|
||||||
} from './utils/market_operation_utils/types';
|
} from './utils/market_operation_utils/types';
|
||||||
import { QuoteReport } from './utils/quote_report_generator';
|
import { QuoteReport } from './utils/quote_report_generator';
|
||||||
import { LogFunction } from './utils/quote_requestor';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* expiryBufferMs: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
|
* expiryBufferMs: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
|
||||||
@ -273,7 +272,7 @@ export interface RfqtMakerAssetOfferings {
|
|||||||
[endpoint: string]: Array<[string, string]>;
|
[endpoint: string]: Array<[string, string]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { LogFunction } from './utils/quote_requestor';
|
export type LogFunction = (obj: object, msg?: string, ...args: any[]) => void;
|
||||||
|
|
||||||
export interface SwapQuoterRfqtOpts {
|
export interface SwapQuoterRfqtOpts {
|
||||||
takerApiKeyWhitelist: string[];
|
takerApiKeyWhitelist: string[];
|
||||||
|
@ -2,13 +2,13 @@ import { schemas, SchemaValidator } from '@0x/json-schemas';
|
|||||||
import { assetDataUtils, orderCalculationUtils, SignedOrder } from '@0x/order-utils';
|
import { assetDataUtils, orderCalculationUtils, SignedOrder } from '@0x/order-utils';
|
||||||
import { RFQTFirmQuote, RFQTIndicativeQuote, TakerRequest } from '@0x/quote-server';
|
import { RFQTFirmQuote, RFQTIndicativeQuote, TakerRequest } from '@0x/quote-server';
|
||||||
import { ERC20AssetData } from '@0x/types';
|
import { ERC20AssetData } from '@0x/types';
|
||||||
import { BigNumber, logUtils } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import Axios, { AxiosInstance } from 'axios';
|
import Axios, { AxiosInstance } from 'axios';
|
||||||
import { Agent as HttpAgent } from 'http';
|
import { Agent as HttpAgent } from 'http';
|
||||||
import { Agent as HttpsAgent } from 'https';
|
import { Agent as HttpsAgent } from 'https';
|
||||||
|
|
||||||
import { constants } from '../constants';
|
import { constants } from '../constants';
|
||||||
import { MarketOperation, RfqtMakerAssetOfferings, RfqtRequestOpts } from '../types';
|
import { LogFunction, MarketOperation, RfqtMakerAssetOfferings, RfqtRequestOpts } from '../types';
|
||||||
|
|
||||||
import { ONE_SECOND_MS } from './market_operation_utils/constants';
|
import { ONE_SECOND_MS } from './market_operation_utils/constants';
|
||||||
import { RfqMakerBlacklist } from './rfq_maker_blacklist';
|
import { RfqMakerBlacklist } from './rfq_maker_blacklist';
|
||||||
@ -107,20 +107,18 @@ function convertIfAxiosError(error: any): Error | object /* axios' .d.ts has Axi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LogFunction = (obj: object, msg?: string, ...args: any[]) => void;
|
|
||||||
|
|
||||||
export class QuoteRequestor {
|
export class QuoteRequestor {
|
||||||
private readonly _schemaValidator: SchemaValidator = new SchemaValidator();
|
private readonly _schemaValidator: SchemaValidator = new SchemaValidator();
|
||||||
private readonly _orderSignatureToMakerUri: { [orderSignature: string]: string } = {};
|
private readonly _orderSignatureToMakerUri: { [orderSignature: string]: string } = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _rfqtAssetOfferings: RfqtMakerAssetOfferings,
|
private readonly _rfqtAssetOfferings: RfqtMakerAssetOfferings,
|
||||||
private readonly _warningLogger: LogFunction = (obj, msg) =>
|
private readonly _warningLogger: LogFunction = constants.DEFAULT_WARNING_LOGGER,
|
||||||
logUtils.warn(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`),
|
private readonly _infoLogger: LogFunction = constants.DEFAULT_INFO_LOGGER,
|
||||||
private readonly _infoLogger: LogFunction = (obj, msg) =>
|
|
||||||
logUtils.log(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`),
|
|
||||||
private readonly _expiryBufferMs: number = constants.DEFAULT_SWAP_QUOTER_OPTS.expiryBufferMs,
|
private readonly _expiryBufferMs: number = constants.DEFAULT_SWAP_QUOTER_OPTS.expiryBufferMs,
|
||||||
) {}
|
) {
|
||||||
|
rfqMakerBlacklist.infoLogger = this._infoLogger;
|
||||||
|
}
|
||||||
|
|
||||||
public async requestRfqtFirmQuotesAsync(
|
public async requestRfqtFirmQuotesAsync(
|
||||||
makerAssetData: string,
|
makerAssetData: string,
|
||||||
@ -395,7 +393,7 @@ export class QuoteRequestor {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs > maxResponseTimeMs);
|
rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs >= maxResponseTimeMs);
|
||||||
result.push({ response: response.data, makerUri: url });
|
result.push({ response: response.data, makerUri: url });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const latencyMs = Date.now() - timeBeforeAwait;
|
const latencyMs = Date.now() - timeBeforeAwait;
|
||||||
@ -411,7 +409,7 @@ export class QuoteRequestor {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs > maxResponseTimeMs);
|
rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs >= maxResponseTimeMs);
|
||||||
this._warningLogger(
|
this._warningLogger(
|
||||||
convertIfAxiosError(err),
|
convertIfAxiosError(err),
|
||||||
`Failed to get RFQ-T ${quoteType} quote from market maker endpoint ${url} for API key ${
|
`Failed to get RFQ-T ${quoteType} quote from market maker endpoint ${url} for API key ${
|
||||||
|
@ -4,11 +4,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { constants } from '../constants';
|
import { constants } from '../constants';
|
||||||
|
import { LogFunction } from '../types';
|
||||||
|
|
||||||
export class RfqMakerBlacklist {
|
export class RfqMakerBlacklist {
|
||||||
private readonly _makerTimeoutStreakLength: { [makerUrl: string]: number } = {};
|
private readonly _makerTimeoutStreakLength: { [makerUrl: string]: number } = {};
|
||||||
private readonly _makerBlacklistedUntilDate: { [makerUrl: string]: number } = {};
|
private readonly _makerBlacklistedUntilDate: { [makerUrl: string]: number } = {};
|
||||||
constructor(private readonly _blacklistDurationMinutes: number, private readonly _timeoutStreakThreshold: number) {}
|
constructor(
|
||||||
|
private readonly _blacklistDurationMinutes: number,
|
||||||
|
private readonly _timeoutStreakThreshold: number,
|
||||||
|
public infoLogger: LogFunction = constants.DEFAULT_INFO_LOGGER,
|
||||||
|
) {}
|
||||||
public logTimeoutOrLackThereof(makerUrl: string, didTimeout: boolean): void {
|
public logTimeoutOrLackThereof(makerUrl: string, didTimeout: boolean): void {
|
||||||
if (!this._makerTimeoutStreakLength.hasOwnProperty(makerUrl)) {
|
if (!this._makerTimeoutStreakLength.hasOwnProperty(makerUrl)) {
|
||||||
this._makerTimeoutStreakLength[makerUrl] = 0;
|
this._makerTimeoutStreakLength[makerUrl] = 0;
|
||||||
@ -16,8 +21,12 @@ export class RfqMakerBlacklist {
|
|||||||
if (didTimeout) {
|
if (didTimeout) {
|
||||||
this._makerTimeoutStreakLength[makerUrl] += 1;
|
this._makerTimeoutStreakLength[makerUrl] += 1;
|
||||||
if (this._makerTimeoutStreakLength[makerUrl] === this._timeoutStreakThreshold) {
|
if (this._makerTimeoutStreakLength[makerUrl] === this._timeoutStreakThreshold) {
|
||||||
this._makerBlacklistedUntilDate[makerUrl] =
|
const blacklistEnd = Date.now() + this._blacklistDurationMinutes * constants.ONE_MINUTE_MS;
|
||||||
Date.now() + this._blacklistDurationMinutes * constants.ONE_MINUTE_MS;
|
this._makerBlacklistedUntilDate[makerUrl] = blacklistEnd;
|
||||||
|
this.infoLogger(
|
||||||
|
{ makerUrl, blacklistedUntil: new Date(blacklistEnd).toISOString() },
|
||||||
|
'maker blacklisted',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._makerTimeoutStreakLength[makerUrl] = 0;
|
this._makerTimeoutStreakLength[makerUrl] = 0;
|
||||||
@ -27,6 +36,7 @@ export class RfqMakerBlacklist {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now > this._makerBlacklistedUntilDate[makerUrl]) {
|
if (now > this._makerBlacklistedUntilDate[makerUrl]) {
|
||||||
delete this._makerBlacklistedUntilDate[makerUrl];
|
delete this._makerBlacklistedUntilDate[makerUrl];
|
||||||
|
this.infoLogger({ makerUrl }, 'maker unblacklisted');
|
||||||
}
|
}
|
||||||
return this._makerBlacklistedUntilDate[makerUrl] > now;
|
return this._makerBlacklistedUntilDate[makerUrl] > now;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user