Skip to content

Commit 0c3b3f1

Browse files
authored
feat: track DataTransform metrics (#8639)
**Motivation** - we usually have to uncompress more messages than needed so it's good to track it in DataTransform **Description** - track `compress` and `uncompress` times by topic type - in this instance, this node only subscribe to 8 column subnets but we usually have to uncompress 9 or up to 10/11 DataColumnSidecars per slot, they will likely be duplicated in the end. See also ChainSafe/js-libp2p-gossipsub#536 part of #8629 <img width="1046" height="485" alt="Screenshot 2025-11-28 at 17 02 42" src="https://github.com/user-attachments/assets/df190b29-6681-48de-a04e-cd79ab82858d" /> Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
1 parent c68bfb2 commit 0c3b3f1

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

packages/beacon-node/src/network/gossip/encoding.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {DataTransform} from "@chainsafe/libp2p-gossipsub/types";
88
import {ForkName} from "@lodestar/params";
99
import {intToBytes} from "@lodestar/utils";
1010
import {MESSAGE_DOMAIN_VALID_SNAPPY} from "./constants.js";
11+
import {Eth2GossipsubMetrics} from "./metrics.js";
1112
import {GossipTopicCache, getGossipSSZType} from "./topic.js";
1213

1314
// Load WASM
@@ -70,7 +71,8 @@ export function msgIdFn(gossipTopicCache: GossipTopicCache, msg: Message): Uint8
7071
export class DataTransformSnappy implements DataTransform {
7172
constructor(
7273
private readonly gossipTopicCache: GossipTopicCache,
73-
private readonly maxSizePerMessage: number
74+
private readonly maxSizePerMessage: number,
75+
private readonly metrics: Eth2GossipsubMetrics | null
7476
) {}
7577

7678
/**
@@ -87,6 +89,7 @@ export class DataTransformSnappy implements DataTransform {
8789
const uncompressedDataLength = uncompressedData.length;
8890
const topic = this.gossipTopicCache.getTopic(topicStr);
8991
const sszType = getGossipSSZType(topic);
92+
this.metrics?.dataTransform.inbound.inc({type: topic.type});
9093

9194
if (uncompressedDataLength < sszType.minSize) {
9295
throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} < ${sszType.minSize}`);
@@ -102,7 +105,9 @@ export class DataTransformSnappy implements DataTransform {
102105
* Takes the data to be published (a topic and associated data) transforms the data. The
103106
* transformed data will then be used to create a `RawGossipsubMessage` to be sent to peers.
104107
*/
105-
outboundTransform(_topicStr: string, data: Uint8Array): Uint8Array {
108+
outboundTransform(topicStr: string, data: Uint8Array): Uint8Array {
109+
const topic = this.gossipTopicCache.getTopic(topicStr);
110+
this.metrics?.dataTransform.outbound.inc({type: topic.type});
106111
if (data.length > this.maxSizePerMessage) {
107112
throw Error(`ssz_snappy encoded data length ${data.length} > ${this.maxSizePerMessage}`);
108113
}

packages/beacon-node/src/network/gossip/gossipsub.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ export class Eth2Gossipsub extends GossipSub {
8989
const gossipTopicCache = new GossipTopicCache(config);
9090

9191
const scoreParams = computeGossipPeerScoreParams({config, eth2Context: modules.eth2Context});
92+
let metrics: Eth2GossipsubMetrics | null = null;
93+
if (metricsRegister) {
94+
metrics = createEth2GossipsubMetrics(metricsRegister);
95+
metrics.gossipMesh.peersByType.addCollect(() =>
96+
this.onScrapeLodestarMetrics(metrics as Eth2GossipsubMetrics, networkConfig)
97+
);
98+
}
9299

93100
// Gossipsub parameters defined here:
94101
// https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub
@@ -116,7 +123,7 @@ export class Eth2Gossipsub extends GossipSub {
116123
fastMsgIdFn: fastMsgIdFn,
117124
msgIdFn: msgIdFn.bind(msgIdFn, gossipTopicCache),
118125
msgIdToStrFn: msgIdToStrFn,
119-
dataTransform: new DataTransformSnappy(gossipTopicCache, config.MAX_PAYLOAD_SIZE),
126+
dataTransform: new DataTransformSnappy(gossipTopicCache, config.MAX_PAYLOAD_SIZE, metrics),
120127
metricsRegister: metricsRegister as MetricsRegister | null,
121128
metricsTopicStrToLabel: metricsRegister
122129
? getMetricsTopicStrToLabel(networkConfig, {disableLightClientServer: opts.disableLightClientServer ?? false})
@@ -141,11 +148,6 @@ export class Eth2Gossipsub extends GossipSub {
141148
this.events = events;
142149
this.gossipTopicCache = gossipTopicCache;
143150

144-
if (metricsRegister) {
145-
const metrics = createEth2GossipsubMetrics(metricsRegister);
146-
metrics.gossipMesh.peersByType.addCollect(() => this.onScrapeLodestarMetrics(metrics, networkConfig));
147-
}
148-
149151
this.addEventListener("gossipsub:message", this.onGossipsubMessage.bind(this));
150152
this.events.on(NetworkEvent.gossipMessageValidationResult, this.onValidationResult.bind(this));
151153

packages/beacon-node/src/network/gossip/metrics.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,17 @@ export function createEth2GossipsubMetrics(register: RegistryMetricCreator) {
6767
labelNames: ["subnet", "boundary"],
6868
}),
6969
},
70+
dataTransform: {
71+
inbound: register.counter<{type: GossipType}>({
72+
name: "lodestar_gossip_data_transform_inbound_total",
73+
help: "Total number of inbound data transforms by gossip type",
74+
labelNames: ["type"],
75+
}),
76+
outbound: register.counter<{type: GossipType}>({
77+
name: "lodestar_gossip_data_transform_outbound_total",
78+
help: "Total number of outbound data transforms by gossip type",
79+
labelNames: ["type"],
80+
}),
81+
},
7082
};
7183
}

0 commit comments

Comments
 (0)