Skip to content

Commit

Permalink
Merge branch 'master' into 2025-01-20-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt authored Jan 28, 2025
2 parents 231a013 + 1d3367a commit 22e88a1
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 183 deletions.
33 changes: 23 additions & 10 deletions src/modes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,24 +117,18 @@ export async function findOpp({
noneNodeError: undefined,
};
if ((allResults[0] as any)?.reason?.spanAttributes) {
extendSpanAttributes(
spanAttributes,
spanAttributes["routeProcessor"] = JSON.stringify(
(allResults[0] as any).reason.spanAttributes,
"routeProcessor",
);
}
if ((allResults[1] as any)?.reason?.spanAttributes) {
extendSpanAttributes(
spanAttributes,
(allResults[1] as any).reason.spanAttributes,
"intraOrderbook",
spanAttributes["intraOrderbook"] = JSON.stringify(
(allResults[1] as any).reason.spanAttributes["intraOrderbook"],
);
}
if ((allResults[2] as any)?.reason?.spanAttributes) {
extendSpanAttributes(
spanAttributes,
spanAttributes["interOrderbook"] = JSON.stringify(
(allResults[2] as any).reason.spanAttributes,
"interOrderbook",
);
}
if ((allResults[0] as any)?.reason?.value?.noneNodeError) {
Expand All @@ -153,3 +147,22 @@ export async function findOpp({
throw result;
}
}

/**
* Records gas estimates for otel span attributes
*/
export function recordGasEstAttrs(
spanAttributes: Record<string, any>,
estimation: any,
config: BotConfig,
headroom: boolean,
) {
const header = headroom ? "headroom" : "final";
spanAttributes[`gasEst.${header}.gasLimit`] = estimation.gas.toString();
spanAttributes[`gasEst.${header}.totalCost`] = estimation.totalGasCost.toString();
spanAttributes[`gasEst.${header}.gasPrice`] = estimation.gasPrice.toString();
if (config.isSpecialL2) {
spanAttributes[`gasEst.${header}.l1Cost`] = estimation.l1Cost.toString();
spanAttributes[`gasEst.${header}.l1GasPrice`] = estimation.l1GasPrice.toString();
}
}
50 changes: 8 additions & 42 deletions src/modes/interOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { recordGasEstAttrs } from ".";
import { orderbookAbi } from "../abis";
import { estimateGasCost } from "../gas";
import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { getBountyEnsureRainlang, parseRainlang } from "../task";
import { BaseError, ExecutionRevertedError, PublicClient } from "viem";
import { ONE18, scale18To, estimateProfit, withBigintSerializer } from "../utils";
import { BotConfig, BundledOrders, ViemClient, DryrunResult, SpanAttrs } from "../types";
import {
ONE18,
scale18To,
estimateProfit,
withBigintSerializer,
extendSpanAttributes,
} from "../utils";

const obInterface = new ethers.utils.Interface(orderbookAbi);

Expand Down Expand Up @@ -128,21 +123,7 @@ export async function dryrun({
gasLimit = ethers.BigNumber.from(estimation.gas).mul(config.gasLimitMultiplier).div(100);

// include dryrun headroom gas estimation in otel logs
extendSpanAttributes(
spanAttributes,
{
gasLimit: estimation.gas.toString(),
totalCost: estimation.totalGasCost.toString(),
gasPrice: estimation.gasPrice.toString(),
...(config.isSpecialL2
? {
l1Cost: estimation.l1Cost.toString(),
l1GasPrice: estimation.l1GasPrice.toString(),
}
: {}),
},
"gasEst.headroom",
);
recordGasEstAttrs(spanAttributes, estimation, config, true);
} catch (e) {
const isNodeError = containsNodeError(e as BaseError);
const errMsg = errorSnapshot("", e);
Expand Down Expand Up @@ -212,21 +193,7 @@ export async function dryrun({
gasCost = gasLimit.mul(gasPrice).add(estimation.l1Cost);

// include dryrun final gas estimation in otel logs
extendSpanAttributes(
spanAttributes,
{
gasLimit: estimation.gas.toString(),
totalCost: estimation.totalGasCost.toString(),
gasPrice: estimation.gasPrice.toString(),
...(config.isSpecialL2
? {
l1Cost: estimation.l1Cost.toString(),
l1GasPrice: estimation.l1GasPrice.toString(),
}
: {}),
},
"gasEst.final",
);
recordGasEstAttrs(spanAttributes, estimation, config, false);
task.evaluable.bytecode = await parseRainlang(
await getBountyEnsureRainlang(
ethers.utils.parseUnits(inputToEthPrice),
Expand Down Expand Up @@ -423,13 +390,12 @@ export async function findOpp({
// } catch {
// /**/
// }
const allOrderbooksAttributes: any = {};
for (let i = 0; i < e.errors.length; i++) {
extendSpanAttributes(
spanAttributes,
e.errors[i].spanAttributes,
"againstOrderbooks." + opposingOrderbookOrders[i].orderbook,
);
allOrderbooksAttributes[opposingOrderbookOrders[i].orderbook] =
e.errors[i].spanAttributes;
}
spanAttributes["againstOrderbooks"] = JSON.stringify(allOrderbooksAttributes);
const noneNodeErrors = allNoneNodeErrors.filter((v) => !!v);
if (allNoneNodeErrors.length && noneNodeErrors.length / allNoneNodeErrors.length > 0.5) {
result.value = {
Expand Down
39 changes: 7 additions & 32 deletions src/modes/intraOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { recordGasEstAttrs } from ".";
import { orderbookAbi } from "../abis";
import { estimateGasCost } from "../gas";
import { BigNumber, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { getWithdrawEnsureRainlang, parseRainlang } from "../task";
import { estimateProfit, scale18, withBigintSerializer } from "../utils";
import { BaseError, erc20Abi, ExecutionRevertedError, PublicClient } from "viem";
import { estimateProfit, scale18, withBigintSerializer, extendSpanAttributes } from "../utils";
import {
SpanAttrs,
BotConfig,
Expand Down Expand Up @@ -120,21 +121,7 @@ export async function dryrun({
gasLimit = ethers.BigNumber.from(estimation.gas).mul(config.gasLimitMultiplier).div(100);

// include dryrun headroom gas estimation in otel logs
extendSpanAttributes(
spanAttributes,
{
gasLimit: estimation.gas.toString(),
totalCost: estimation.totalGasCost.toString(),
gasPrice: estimation.gasPrice.toString(),
...(config.isSpecialL2
? {
l1Cost: estimation.l1Cost.toString(),
l1GasPrice: estimation.l1GasPrice.toString(),
}
: {}),
},
"gasEst.headroom",
);
recordGasEstAttrs(spanAttributes, estimation, config, true);
} catch (e) {
// reason, code, method, transaction, error, stack, message
const isNodeError = containsNodeError(e as BaseError);
Expand Down Expand Up @@ -214,21 +201,7 @@ export async function dryrun({
gasCost = gasLimit.mul(gasPrice).add(estimation.l1Cost);

// include dryrun final gas estimation in otel logs
extendSpanAttributes(
spanAttributes,
{
gasLimit: estimation.gas.toString(),
totalCost: estimation.totalGasCost.toString(),
gasPrice: estimation.gasPrice.toString(),
...(config.isSpecialL2
? {
l1Cost: estimation.l1Cost.toString(),
l1GasPrice: estimation.l1GasPrice.toString(),
}
: {}),
},
"gasEst.final",
);
recordGasEstAttrs(spanAttributes, estimation, config, false);
task.evaluable.bytecode = await parseRainlang(
await getWithdrawEnsureRainlang(
signer.account.address,
Expand Down Expand Up @@ -358,6 +331,7 @@ export async function findOpp({
);
if (!opposingOrders || !opposingOrders.length) throw undefined;

const allErrorAttributes: string[] = [];
const allNoneNodeErrors: (string | undefined)[] = [];
const inputBalance = scale18(
await viemClient.readContract({
Expand Down Expand Up @@ -394,9 +368,10 @@ export async function findOpp({
});
} catch (e: any) {
allNoneNodeErrors.push(e?.value?.noneNodeError);
extendSpanAttributes(spanAttributes, e.spanAttributes, "intraOrderbook." + i);
allErrorAttributes.push(JSON.stringify(e.spanAttributes));
}
}
spanAttributes["intraOrderbook"] = allErrorAttributes;
const noneNodeErrors = allNoneNodeErrors.filter((v) => !!v);
if (allNoneNodeErrors.length && noneNodeErrors.length / allNoneNodeErrors.length > 0.5) {
result.value = {
Expand Down
38 changes: 5 additions & 33 deletions src/modes/routeProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { recordGasEstAttrs } from ".";
import { Token } from "sushi/currency";
import { estimateGasCost } from "../gas";
import { ChainId, DataFetcher, Router } from "sushi";
Expand All @@ -14,7 +15,6 @@ import {
estimateProfit,
visualizeRoute,
withBigintSerializer,
extendSpanAttributes,
} from "../utils";

/**
Expand Down Expand Up @@ -191,21 +191,7 @@ export async function dryrun({
.div(100);

// include dryrun headroom gas estimation in otel logs
extendSpanAttributes(
spanAttributes,
{
gasLimit: estimation.gas.toString(),
totalCost: estimation.totalGasCost.toString(),
gasPrice: estimation.gasPrice.toString(),
...(config.isSpecialL2
? {
l1Cost: estimation.l1Cost.toString(),
l1GasPrice: estimation.l1GasPrice.toString(),
}
: {}),
},
"gasEst.headroom",
);
recordGasEstAttrs(spanAttributes, estimation, config, true);
} catch (e) {
// reason, code, method, transaction, error, stack, message
const isNodeError = containsNodeError(e as BaseError);
Expand Down Expand Up @@ -277,21 +263,7 @@ export async function dryrun({
gasCost = gasLimit.mul(gasPrice).add(estimation.l1Cost);

// include dryrun final gas estimation in otel logs
extendSpanAttributes(
spanAttributes,
{
gasLimit: estimation.gas.toString(),
totalCost: estimation.totalGasCost.toString(),
gasPrice: estimation.gasPrice.toString(),
...(config.isSpecialL2
? {
l1Cost: estimation.l1Cost.toString(),
l1GasPrice: estimation.l1GasPrice.toString(),
}
: {}),
},
"gasEst.final",
);
recordGasEstAttrs(spanAttributes, estimation, config, false);
task.evaluable.bytecode = await parseRainlang(
await getBountyEnsureRainlang(
ethers.utils.parseUnits(ethPrice),
Expand Down Expand Up @@ -430,7 +402,7 @@ export async function findOpp({
// the fail reason can only be no route in case all hops fail reasons are no route
if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false;
allNoneNodeErrors.push(e?.value?.noneNodeError);
extendSpanAttributes(spanAttributes, e.spanAttributes, "full");
spanAttributes["full"] = JSON.stringify(e.spanAttributes);
}
if (!hasPriceMatch.value) {
const maxTradeSize = findMaxInput({
Expand Down Expand Up @@ -463,7 +435,7 @@ export async function findOpp({
// the fail reason can only be no route in case all hops fail reasons are no route
if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false;
allNoneNodeErrors.push(e?.value?.noneNodeError);
extendSpanAttributes(spanAttributes, e.spanAttributes, "partial");
spanAttributes["partial"] = JSON.stringify(e.spanAttributes);
}
}
}
Expand Down
49 changes: 37 additions & 12 deletions src/processOrders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,16 @@ export const processOrders = async (
}

for (const { settle, pair, orderPairObject } of results) {
// instantiate a span for this pair
const span = tracer.startSpan(`order_${pair}`, undefined, ctx);
span.setAttribute("details.owner", orderPairObject.takeOrders[0].takeOrder.order.owner);
try {
// settle the process results
// this will return the report of the operation and in case
// there was a revert tx, it will try to simulate it and find
// the root cause as well
const result = await settle();

// instantiate a span for this pair
const span = tracer.startSpan(`order_${pair}`, undefined, ctx);
span.setAttribute("details.owner", orderPairObject.takeOrders[0].takeOrder.order.owner);

// keep track of avg gas cost
if (result.gasCost) {
txGasCosts.push(result.gasCost);
Expand All @@ -238,12 +237,7 @@ export const processOrders = async (
span.setAttribute("severity", ErrorSeverity.HIGH);
span.setStatus({ code: SpanStatusCode.ERROR, message: "unexpected error" });
}
span.end();
} catch (e: any) {
// instantiate a span for this pair
const span = tracer.startSpan(`order_${pair}`, undefined, ctx);
span.setAttribute("details.owner", orderPairObject.takeOrders[0].takeOrder.order.owner);

// set the span attributes with the values gathered at processPair()
span.setAttributes(e.spanAttributes);

Expand Down Expand Up @@ -366,8 +360,8 @@ export const processOrders = async (
span.setAttribute("severity", ErrorSeverity.HIGH);
span.setStatus({ code: SpanStatusCode.ERROR, message });
}
span.end();
}
span.end();
}
return {
reports,
Expand Down Expand Up @@ -610,9 +604,40 @@ export async function processPair(args: {
}
}
} catch (e: any) {
// record all span attributes
// record all span attributes in their scopes
for (const attrKey in e.spanAttributes) {
spanAttributes["details." + attrKey] = e.spanAttributes[attrKey];
if (attrKey === "routeProcessor") {
const rpAttrs = JSON.parse(e.spanAttributes[attrKey]);
for (const key in rpAttrs) {
const innerAttrs = JSON.parse(rpAttrs[key]);
for (const innerKey in innerAttrs) {
spanAttributes["details.routeProcessor." + key + "." + innerKey] =
innerAttrs[innerKey];
}
}
} else if (attrKey === "intraOrderbook") {
const intraAttrs = JSON.parse(e.spanAttributes[attrKey]);
for (let i = 0; i < intraAttrs.length; i++) {
const innerAttrs = JSON.parse(intraAttrs[i]);
for (const innerKey in innerAttrs) {
spanAttributes["details.intraOrderbook." + i + "." + innerKey] =
innerAttrs[innerKey];
}
}
} else if (attrKey === "interOrderbook") {
const interAttrs = JSON.parse(
JSON.parse(e.spanAttributes[attrKey])["againstOrderbooks"],
);
for (const key in interAttrs) {
for (const innerKey in interAttrs[key]) {
spanAttributes[
"details.interOrderbook.againstOrderbooks." + key + "." + innerKey
] = interAttrs[key][innerKey];
}
}
} else {
spanAttributes["details." + attrKey] = e.spanAttributes[attrKey];
}
}
if (e.noneNodeError) {
spanAttributes["details.noneNodeError"] = true;
Expand Down
Loading

0 comments on commit 22e88a1

Please sign in to comment.