Skip to content

Commit 26c53dc

Browse files
authored
feat: add prom metrics for stacks block count at previous burn block (#2200)
* feat: add prom metrics for current and previous tenure block counts * fix: filter canonical * fix: keep only blocks at previous btc block * fix: empty gauge * fix: empty case * fix: update only on collect * style: this
1 parent a5d2a8b commit 26c53dc

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

src/datastore/pg-store.ts

+9
Original file line numberDiff line numberDiff line change
@@ -4524,4 +4524,13 @@ export class PgStore extends BasePgStore {
45244524
`;
45254525
if (result.count) return result[0];
45264526
}
4527+
4528+
async getStacksBlockCountAtPreviousBurnBlock(): Promise<number> {
4529+
const result = await this.sql<{ count: string }[]>`
4530+
SELECT COUNT(*) AS count
4531+
FROM blocks
4532+
WHERE burn_block_height = (SELECT burn_block_height - 1 FROM chain_tip) AND canonical = TRUE
4533+
`;
4534+
return parseInt(result[0]?.count ?? '0');
4535+
}
45274536
}

src/datastore/pg-write-store.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,12 @@ export class PgWriteStore extends PgStore {
17801780
});
17811781
}
17821782

1783+
async updateBurnChainBlockHeight(args: { blockHeight: number }): Promise<void> {
1784+
await this.sql`
1785+
UPDATE chain_tip SET burn_block_height = GREATEST(${args.blockHeight}, burn_block_height)
1786+
`;
1787+
}
1788+
17831789
async insertSlotHoldersBatch(sql: PgSqlClient, slotHolders: DbRewardSlotHolder[]): Promise<void> {
17841790
const slotValues: RewardSlotHolderInsertValues[] = slotHolders.map(slot => ({
17851791
canonical: true,

src/event-stream/event-server.ts

+25-10
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ async function handleBurnBlockMessage(
130130
burnchainBlockHeight: burnBlockMsg.burn_block_height,
131131
slotHolders: slotHolders,
132132
});
133+
await db.updateBurnChainBlockHeight({ blockHeight: burnBlockMsg.burn_block_height });
133134
}
134135

135136
async function handleMempoolTxsMessage(rawTxs: string[], db: PgWriteStore): Promise<void> {
@@ -631,18 +632,32 @@ interface EventMessageHandler {
631632
handleNewAttachment(msg: CoreNodeAttachmentMessage[], db: PgWriteStore): Promise<void> | void;
632633
}
633634

634-
function createMessageProcessorQueue(): EventMessageHandler {
635+
function createMessageProcessorQueue(db: PgWriteStore): EventMessageHandler {
635636
// Create a promise queue so that only one message is handled at a time.
636637
const processorQueue = new PQueue({ concurrency: 1 });
637638

638-
let eventTimer: prom.Histogram<'event'> | undefined;
639+
let metrics:
640+
| {
641+
eventTimer: prom.Histogram;
642+
blocksInPreviousBurnBlock: prom.Gauge;
643+
}
644+
| undefined;
639645
if (isProdEnv) {
640-
eventTimer = new prom.Histogram({
641-
name: 'stacks_event_ingestion_timers',
642-
help: 'Event ingestion timers',
643-
labelNames: ['event'],
644-
buckets: prom.exponentialBuckets(50, 3, 10), // 10 buckets, from 50 ms to 15 minutes
645-
});
646+
metrics = {
647+
eventTimer: new prom.Histogram({
648+
name: 'stacks_event_ingestion_timers',
649+
help: 'Event ingestion timers',
650+
labelNames: ['event'],
651+
buckets: prom.exponentialBuckets(50, 3, 10), // 10 buckets, from 50 ms to 15 minutes
652+
}),
653+
blocksInPreviousBurnBlock: new prom.Gauge({
654+
name: 'stacks_blocks_in_previous_burn_block',
655+
help: 'Number of Stacks blocks produced in the previous burn block',
656+
async collect() {
657+
this.set(await db.getStacksBlockCountAtPreviousBurnBlock());
658+
},
659+
}),
660+
};
646661
}
647662

648663
const observeEvent = async (event: string, fn: () => Promise<void>) => {
@@ -651,7 +666,7 @@ function createMessageProcessorQueue(): EventMessageHandler {
651666
await fn();
652667
} finally {
653668
const elapsedMs = timer.getElapsed();
654-
eventTimer?.observe({ event }, elapsedMs);
669+
metrics?.eventTimer.observe({ event }, elapsedMs);
655670
}
656671
};
657672

@@ -738,7 +753,7 @@ export async function startEventServer(opts: {
738753
serverPort?: number;
739754
}): Promise<EventStreamServer> {
740755
const db = opts.datastore;
741-
const messageHandler = opts.messageHandler ?? createMessageProcessorQueue();
756+
const messageHandler = opts.messageHandler ?? createMessageProcessorQueue(db);
742757

743758
let eventHost = opts.serverHost ?? process.env['STACKS_CORE_EVENT_HOST'];
744759
const eventPort = opts.serverPort ?? parseInt(process.env['STACKS_CORE_EVENT_PORT'] ?? '', 10);

0 commit comments

Comments
 (0)