Skip to content

Commit 1690dfd

Browse files
authored
feat: p2p gossipsub metrics (#14689)
1 parent 220070a commit 1690dfd

File tree

4 files changed

+85
-15
lines changed

4 files changed

+85
-15
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { Timer } from '@aztec/foundation/timer';
2+
import type { TopicType } from '@aztec/stdlib/p2p';
3+
import {
4+
Attributes,
5+
type Histogram,
6+
Metrics,
7+
type TelemetryClient,
8+
type UpDownCounter,
9+
ValueType,
10+
} from '@aztec/telemetry-client';
11+
12+
export class P2PInstrumentation {
13+
private messageValidationDuration: Histogram;
14+
private messagePrevalidationCount: UpDownCounter;
15+
16+
constructor(client: TelemetryClient, name: string) {
17+
const meter = client.getMeter(name);
18+
19+
this.messageValidationDuration = meter.createHistogram(Metrics.P2P_GOSSIP_MESSAGE_VALIDATION_DURATION, {
20+
unit: 'ms',
21+
description: 'How long validating a gossiped message takes',
22+
valueType: ValueType.INT,
23+
});
24+
25+
this.messagePrevalidationCount = meter.createUpDownCounter(Metrics.P2P_GOSSIP_MESSAGE_PREVALIDATION_COUNT, {
26+
description: 'How many message pass/fail prevalidation',
27+
valueType: ValueType.INT,
28+
});
29+
}
30+
31+
public recordMessageValidation(topicName: TopicType, timerOrMs: Timer | number) {
32+
const ms = typeof timerOrMs === 'number' ? timerOrMs : timerOrMs.ms();
33+
this.messageValidationDuration.record(Math.ceil(ms), { [Attributes.TOPIC_NAME]: topicName });
34+
}
35+
36+
public incMessagePrevalidationStatus(passed: boolean, topicName: TopicType | undefined) {
37+
this.messagePrevalidationCount.add(1, { [Attributes.TOPIC_NAME]: topicName, [Attributes.OK]: passed });
38+
}
39+
}

yarn-project/p2p/src/services/libp2p/libp2p_service.ts

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { EpochCacheInterface } from '@aztec/epoch-cache';
22
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
33
import { SerialQueue } from '@aztec/foundation/queue';
44
import { RunningPromise } from '@aztec/foundation/running-promise';
5+
import { Timer } from '@aztec/foundation/timer';
56
import type { AztecAsyncKVStore } from '@aztec/kv-store';
67
import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
78
import type { L2BlockSource } from '@aztec/stdlib/block';
@@ -65,6 +66,7 @@ import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
6566
import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
6667
import { ReqResp } from '../reqresp/reqresp.js';
6768
import type { P2PBlockReceivedCallback, P2PService, PeerDiscoveryService } from '../service.js';
69+
import { P2PInstrumentation } from './instrumentation.js';
6870

6971
interface ValidationResult {
7072
name: string;
@@ -107,6 +109,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
107109

108110
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
109111

112+
private instrumentation: P2PInstrumentation;
113+
110114
constructor(
111115
private clientType: T,
112116
private config: P2PConfig,
@@ -122,6 +126,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
122126
) {
123127
super(telemetry, 'LibP2PService');
124128

129+
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
130+
125131
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
126132
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
127133
this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
@@ -501,25 +507,33 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
501507
}
502508

503509
protected preValidateReceivedMessage(msg: Message, msgId: string, source: PeerId) {
504-
const getValidator = () => {
505-
if (msg.topic === this.topicStrings[TopicType.tx]) {
506-
return this.msgIdSeenValidators[TopicType.tx];
507-
}
508-
if (msg.topic === this.topicStrings[TopicType.block_attestation]) {
509-
return this.msgIdSeenValidators[TopicType.block_attestation];
510-
}
511-
if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
512-
return this.msgIdSeenValidators[TopicType.block_proposal];
513-
}
514-
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
515-
};
510+
let topicType: TopicType | undefined;
511+
512+
switch (msg.topic) {
513+
case this.topicStrings[TopicType.tx]:
514+
topicType = TopicType.tx;
515+
break;
516+
case this.topicStrings[TopicType.block_attestation]:
517+
topicType = TopicType.block_attestation;
518+
break;
519+
case this.topicStrings[TopicType.block_proposal]:
520+
topicType = TopicType.block_proposal;
521+
break;
522+
default:
523+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
524+
break;
525+
}
516526

517-
const validator = getValidator();
527+
const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
518528

519529
if (!validator || !validator.addMessage(msgId)) {
530+
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
520531
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
521532
return false;
522533
}
534+
535+
this.instrumentation.incMessagePrevalidationStatus(true, topicType);
536+
523537
return true;
524538
}
525539

@@ -559,14 +573,20 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
559573
validationFunc: () => Promise<{ result: boolean; obj: T }>,
560574
msgId: string,
561575
source: PeerId,
576+
topicType: TopicType,
562577
): Promise<{ result: boolean; obj: T | undefined }> {
563578
let resultAndObj: { result: boolean; obj: T | undefined } = { result: false, obj: undefined };
579+
const timer = new Timer();
564580
try {
565581
resultAndObj = await validationFunc();
566582
} catch (err) {
567583
this.logger.error(`Error deserialising and validating message `, err);
568584
}
569585

586+
if (resultAndObj.result) {
587+
this.instrumentation.recordMessageValidation(topicType, timer);
588+
}
589+
570590
this.node.services.pubsub.reportMessageValidationResult(
571591
msgId,
572592
source.toString(),
@@ -582,7 +602,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
582602
return { result, obj: tx };
583603
};
584604

585-
const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source);
605+
const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
586606
if (!result || !tx) {
587607
return;
588608
}
@@ -613,6 +633,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
613633
validationFunc,
614634
msgId,
615635
source,
636+
TopicType.block_attestation,
616637
);
617638
if (!result || !attestation) {
618639
return;
@@ -640,7 +661,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
640661
return { result, obj: block };
641662
};
642663

643-
const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(validationFunc, msgId, source);
664+
const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
665+
validationFunc,
666+
msgId,
667+
source,
668+
TopicType.block_proposal,
669+
);
644670
if (!result || !block) {
645671
return;
646672
}

yarn-project/telemetry-client/src/attributes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,5 @@ export const GAS_DIMENSION = 'aztec.gas_dimension';
110110
export const WORLD_STATE_REQUEST_TYPE = 'aztec.world_state_request';
111111

112112
export const NODEJS_EVENT_LOOP_STATE = 'nodejs.eventloop.state';
113+
114+
export const TOPIC_NAME = 'aztec.gossip.topic_name';

yarn-project/telemetry-client/src/metrics.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ export const P2P_REQ_RESP_RECEIVED_REQUESTS = 'aztec.p2p.req_resp.received_reque
9797
export const P2P_REQ_RESP_FAILED_OUTBOUND_REQUESTS = 'aztec.p2p.req_resp.failed_outbound_requests';
9898
export const P2P_REQ_RESP_FAILED_INBOUND_REQUESTS = 'aztec.p2p.req_resp.failed_inbound_requests';
9999

100+
export const P2P_GOSSIP_MESSAGE_VALIDATION_DURATION = 'aztec.p2p.gossip.message_validation_duration';
101+
export const P2P_GOSSIP_MESSAGE_PREVALIDATION_COUNT = 'aztec.p2p.gossip.message_validation_count';
102+
100103
export const PUBLIC_PROCESSOR_TX_DURATION = 'aztec.public_processor.tx_duration';
101104
export const PUBLIC_PROCESSOR_TX_COUNT = 'aztec.public_processor.tx_count';
102105
export const PUBLIC_PROCESSOR_TX_PHASE_COUNT = 'aztec.public_processor.tx_phase_count';

0 commit comments

Comments
 (0)