Skip to content

Commit

Permalink
chore: metrics todo and naming (#95)
Browse files Browse the repository at this point in the history
# Description
This PR addresses issues around naming conventions for the prometheus
metrics. Best efforts have been followed to adhere to [best
practices](https://prometheus.io/docs/practices/naming/).

# Changes

- [x] Revised metric naming and labeling to be in accordance with best
practices.
- [x] Removed custom API prometheus metrics and replaced with
middleware.

## How to test

1. Run a sync from contract genesis.
2. Observe via `http://127.0.0.1:8080/metrics` there respective metrics
changing.

## Related Issues

Related #78, #70
  • Loading branch information
mfw78 authored Oct 10, 2023
1 parent 5e3c760 commit 412192a
Show file tree
Hide file tree
Showing 10 changed files with 669 additions and 195 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@commitlint/config-conventional": "^17.6.7",
"@typechain/ethers-v5": "^11.1.1",
"@types/express": "^4.17.18",
"@types/express-prometheus-middleware": "^1.2.1",
"@types/jest": "^29.5.3",
"@types/node": "^18.16.3",
"@types/node-slack": "^0.0.31",
Expand All @@ -45,6 +46,7 @@
"chalk": "^4.1.2",
"ethers": "^5.7.2",
"express": "^4.18.2",
"express-prometheus-middleware": "^1.2.0",
"graphql-request": "^6.1.0",
"level": "^8.0.0",
"level-ts": "^2.1.0",
Expand Down
51 changes: 32 additions & 19 deletions src/domain/addContract.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { toConditionalOrderParams, getLogger } from "../utils";
import { MetricsService } from "../utils/metrics";
import {
toConditionalOrderParams,
getLogger,
handleExecutionError,
isComposableCowCompatible,
} from "../utils";
import { BytesLike, ethers } from "ethers";

import {
Expand All @@ -14,17 +18,19 @@ import {
Registry,
} from "../types";

import { isComposableCowCompatible, handleExecutionError } from "../utils";
import { ChainContext } from "./chainContext";
import { ConditionalOrderParams } from "@cowprotocol/cow-sdk";

const {
newOwnerCount,
addNewOwnerErrorCount,
addContractSingleOrderCount,
addContractMerkleRootSetCount,
ownersPopulation,
} = MetricsService;
import {
addContractRunsTotal,
addContractsErrorsTotal,
addContractsRunDurationSeconds,
measureTime,
merkleRootTotal,
newContractsTotal,
singleOrdersTotal,
activeOrdersTotal,
activeOwnersTotal,
} from "../utils/metrics";

/**
* Listens to these events on the `ComposableCoW` contract:
Expand All @@ -37,7 +43,15 @@ export async function addContract(
context: ChainContext,
event: ConditionalOrderCreatedEvent
) {
return _addContract(context, event).catch(handleExecutionError);
const { chainId } = context;
await measureTime({
action: () => _addContract(context, event),
labelValues: [chainId.toString()],
durationMetric: addContractsRunDurationSeconds,
totalRunsMetric: addContractRunsTotal,
errorHandler: handleExecutionError,
errorMetric: addContractsErrorsTotal,
});
}

async function _addContract(
Expand Down Expand Up @@ -65,15 +79,12 @@ async function _addContract(
registry
);
if (added) {
newOwnerCount.labels(context.chainId.toString()).inc();
newContractsTotal.labels(context.chainId.toString()).inc();
numContractsAdded++;
} else {
log.error(
`Failed to register Smart Order from tx ${tx} on block ${blockNumber}. Error: ${error}`
);
addNewOwnerErrorCount
.labels(context.chainId.toString(), "_addContract")
.inc();
}
hasErrors ||= error;

Expand Down Expand Up @@ -123,7 +134,7 @@ export async function _registerNewOrder(
registry
);
added = true;
addContractSingleOrderCount.labels(registry.network).inc();
singleOrdersTotal.labels(registry.network).inc();
} else if (
event.topics[0] == composableCow.getEventTopic("MerkleRootSet")
) {
Expand Down Expand Up @@ -164,7 +175,7 @@ export async function _registerNewOrder(
registry
);
added = true;
addContractMerkleRootSetCount.labels(registry.network).inc();
merkleRootTotal.labels(registry.network).inc();
}
}
}
Expand Down Expand Up @@ -223,6 +234,7 @@ export function add(
orders: new Map(),
composableCow,
});
activeOrdersTotal.labels(registry.network).inc();
}
} else {
log.info(`Adding conditional order to new owner contract ${owner}:`, {
Expand All @@ -235,7 +247,8 @@ export function add(
owner,
new Set([{ tx, params, proof, orders: new Map(), composableCow }])
);
ownersPopulation.labels(registry.network).inc();
activeOwnersTotal.labels(registry.network).inc();
activeOrdersTotal.labels(registry.network).inc();
}
}

Expand Down
43 changes: 19 additions & 24 deletions src/domain/chainContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ import { addContract } from "./addContract";
import { checkForAndPlaceOrder } from "./checkForAndPlaceOrder";
import { ethers } from "ethers";
import { composableCowContract, DBService, getLogger } from "../utils";
import { MetricsService } from "../utils/metrics";
import {
blockHeight,
blockTime,
eventsProcessedTotal,
processBlockDurationSeconds,
reorgDepth,
reorgsTotal,
} from "../utils/metrics";

const WATCHDOG_FREQUENCY = 5 * 1000; // 5 seconds

const MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11";

// Metrics
const {
blockWatcherBlockHeight,
blockWatcherReorgCount,
blockWatcherBlockTime,
blockWatcherNumEventsProcessed,
processBlockDuration,
} = MetricsService;

/**
* The chain context handles watching a single chain for new conditional orders
* and executing them.
Expand Down Expand Up @@ -102,9 +100,7 @@ export class ChainContext {
const { pageSize } = this;

// Set the block height metric
blockWatcherBlockHeight
.labels(chainId.toString())
.set(lastProcessedBlock ?? 0);
blockHeight.labels(chainId.toString()).set(lastProcessedBlock ?? 0);

// Start watching from (not including) the last processed block (if any)
let fromBlock = lastProcessedBlock
Expand Down Expand Up @@ -181,9 +177,7 @@ export class ChainContext {
await this.registry.write();

// Set the block height metric
blockWatcherBlockHeight
.labels(chainId.toString())
.set(Number(blockNumber));
blockHeight.labels(chainId.toString()).set(Number(blockNumber));
} catch (err) {
log.error(`Error processing block ${blockNumber}`, err);
}
Expand Down Expand Up @@ -246,16 +240,19 @@ export class ChainContext {
log.debug(`New block ${blockNumber}`);
// Set the block time metric
const now = new Date().getTime();
const blockTime = now - timeLastBlockProcessed;
const _blockTime = (now - timeLastBlockProcessed) / 1000;
timeLastBlockProcessed = now;

// Set the block time metric
blockWatcherBlockTime.labels(chainId.toString()).set(blockTime);
blockTime.labels(chainId.toString()).set(_blockTime);

if (blockNumber <= lastBlockReceived) {
// This may be a re-org, so process the block again
blockWatcherReorgCount.labels(chainId.toString()).inc();
reorgsTotal.labels(chainId.toString()).inc();
log.info(`Re-org detected, re-processing block ${blockNumber}`);
reorgDepth
.labels(chainId.toString())
.set(lastBlockReceived - blockNumber + 1);
}
lastBlockReceived = blockNumber;

Expand All @@ -269,9 +266,7 @@ export class ChainContext {
await processBlock(this, Number(blockNumber), events);

// Block height metric
blockWatcherBlockHeight
.labels(chainId.toString())
.set(Number(blockNumber));
blockHeight.labels(chainId.toString()).set(Number(blockNumber));
} catch {
log.error(`Error processing block ${blockNumber}`);
}
Expand Down Expand Up @@ -322,7 +317,7 @@ async function processBlock(
blockTimestampOverride?: number
) {
const { provider, chainId } = context;
const timer = processBlockDuration
const timer = processBlockDurationSeconds
.labels(context.chainId.toString())
.startTimer();
const log = getLogger(`chainContext:processBlock:${chainId}:${blockNumber}`);
Expand All @@ -343,7 +338,7 @@ async function processBlock(
return false;
});
log.info(`Result of "addContract": ${_formatResult(result)}`);
blockWatcherNumEventsProcessed.labels(chainId.toString()).inc();
eventsProcessedTotal.labels(chainId.toString()).inc();
}
}

Expand Down
Loading

0 comments on commit 412192a

Please sign in to comment.