Skip to content

Commit b43d206

Browse files
committed
feat: add content validation result metrics
1 parent a125a96 commit b43d206

File tree

3 files changed

+68
-11
lines changed

3 files changed

+68
-11
lines changed

portalnet/src/metrics/overlay.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub struct OverlayMetrics {
2626
message_count: IntCounterVec,
2727
utp_outcome_count: IntCounterVec,
2828
utp_active_count: IntGaugeVec,
29+
validation_count: IntCounterVec,
2930
}
3031

3132
impl OverlayMetrics {
@@ -58,11 +59,22 @@ impl OverlayMetrics {
5859
utp_active_count_labels,
5960
);
6061

62+
let validation_count_options = opts!(
63+
"trin_validation_total",
64+
"count all content validations successful and failed"
65+
);
66+
let validation_count_labels = &["protocol", "success"];
67+
let validation_count = OverlayMetrics::register_counter_metric(
68+
validation_count_options,
69+
validation_count_labels,
70+
);
71+
6172
Self {
6273
protocol: protocol.into(),
6374
message_count,
6475
utp_outcome_count,
6576
utp_active_count,
77+
validation_count,
6678
}
6779
}
6880

@@ -131,6 +143,22 @@ impl OverlayMetrics {
131143
self.utp_active_count.with_label_values(&labels).dec();
132144
}
133145

146+
//
147+
// Validations
148+
//
149+
/// Returns the value of the given metric with the specified labels.
150+
pub fn validation_count_by_outcome(&self, outcome: bool) -> u64 {
151+
let outcome = outcome.to_string();
152+
let labels = [self.protocol.into(), outcome.as_str()];
153+
self.validation_count.with_label_values(&labels).get()
154+
}
155+
156+
pub fn report_validation(&self, success: bool) {
157+
let success = success.to_string();
158+
let labels: [&str; 2] = [self.protocol.into(), success.as_str()];
159+
self.validation_count.with_label_values(&labels).inc();
160+
}
161+
134162
fn register_counter_metric(options: Opts, labels: &[&str]) -> IntCounterVec {
135163
// Register the metric with the default registry, or if that fails, register with a
136164
// newly-created registry.
@@ -216,12 +244,16 @@ impl OverlayMetrics {
216244
pub fn get_message_summary(&self) -> String {
217245
// for every offer you made, how many accepts did you receive
218246
// for every offer you received, how many accepts did you make
247+
let successful_validations = self.validation_count_by_outcome(true);
248+
let failed_validations = self.validation_count_by_outcome(false);
219249
format!(
220-
"offers={}/{}, accepts={}/{}",
250+
"offers={}/{}, accepts={}/{}, validations={}/{}",
221251
self.message_count_by_labels(MessageDirectionLabel::Received, MessageLabel::Accept),
222252
self.message_count_by_labels(MessageDirectionLabel::Sent, MessageLabel::Offer),
223253
self.message_count_by_labels(MessageDirectionLabel::Sent, MessageLabel::Accept),
224254
self.message_count_by_labels(MessageDirectionLabel::Received, MessageLabel::Offer),
255+
successful_validations,
256+
successful_validations + failed_validations,
225257
)
226258
}
227259
}

portalnet/src/overlay.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -447,11 +447,7 @@ where
447447
Ok(Response::Content(found_content)) => {
448448
match found_content {
449449
Content::Content(content) => {
450-
match self
451-
.validator
452-
.validate_content(&content_key, &content)
453-
.await
454-
{
450+
match self.validate_content(&content_key, &content).await {
455451
Ok(_) => Ok((Content::Content(content), false)),
456452
Err(msg) => Err(OverlayRequestError::FailedValidation(format!(
457453
"Network: {:?}, Reason: {msg:?}",
@@ -464,11 +460,7 @@ where
464460
Content::ConnectionId(conn_id) => {
465461
let conn_id = u16::from_be(conn_id);
466462
let content = self.init_find_content_stream(enr, conn_id).await?;
467-
match self
468-
.validator
469-
.validate_content(&content_key, &content)
470-
.await
471-
{
463+
match self.validate_content(&content_key, &content).await {
472464
Ok(_) => Ok((Content::Content(content), true)),
473465
Err(msg) => Err(OverlayRequestError::FailedValidation(format!(
474466
"Network: {:?}, Reason: {msg:?}",
@@ -483,6 +475,27 @@ where
483475
}
484476
}
485477

478+
async fn validate_content(
479+
&self,
480+
content_key: &TContentKey,
481+
content: &[u8],
482+
) -> anyhow::Result<()> {
483+
match self.validator.validate_content(content_key, content).await {
484+
Ok(_) => {
485+
self.metrics.report_validation(true);
486+
Ok(())
487+
}
488+
Err(msg) => {
489+
self.metrics.report_validation(false);
490+
Err(anyhow!(
491+
"Content validation failed for content key {:?} with error: {:?}",
492+
content_key,
493+
msg
494+
))
495+
}
496+
}
497+
}
498+
486499
/// Initialize FindContent uTP stream with remote node
487500
async fn init_find_content_stream(
488501
&self,

portalnet/src/overlay_service.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ where
786786
let store = self.store.clone();
787787
let kbuckets = self.kbuckets.clone();
788788
let command_tx = self.command_tx.clone();
789+
let metrics = self.metrics.clone();
789790
tokio::spawn(async move {
790791
Self::process_received_content(
791792
kbuckets,
@@ -798,6 +799,7 @@ where
798799
callback,
799800
query_info.trace,
800801
nodes_to_poke,
802+
metrics,
801803
)
802804
.await;
803805
});
@@ -874,6 +876,7 @@ where
874876
);
875877

876878
let trace = query_info.trace;
879+
let metrics = metrics.clone();
877880
Self::process_received_content(
878881
kbuckets,
879882
command_tx,
@@ -885,6 +888,7 @@ where
885888
callback,
886889
trace,
887890
nodes_to_poke,
891+
metrics,
888892
)
889893
.await;
890894
});
@@ -1258,6 +1262,7 @@ where
12581262
if let Err(err) = Self::process_accept_utp_payload(
12591263
validator,
12601264
store,
1265+
metrics,
12611266
kbuckets,
12621267
command_tx,
12631268
content_keys,
@@ -1572,6 +1577,7 @@ where
15721577
async fn process_accept_utp_payload(
15731578
validator: Arc<TValidator>,
15741579
store: Arc<RwLock<TStore>>,
1580+
metrics: Arc<OverlayMetrics>,
15751581
kbuckets: Arc<RwLock<KBucketsTable<NodeId, Node>>>,
15761582
command_tx: UnboundedSender<OverlayCommand<TContentKey>>,
15771583
content_keys: Vec<TContentKey>,
@@ -1599,20 +1605,23 @@ where
15991605
// - Propagate all validated content
16001606
let validator = Arc::clone(&validator);
16011607
let store = Arc::clone(&store);
1608+
let metrics = Arc::clone(&metrics);
16021609
tokio::spawn(async move {
16031610
// Validated received content
16041611
if let Err(err) = validator
16051612
.validate_content(&key, &content_value.to_vec())
16061613
.await
16071614
{
16081615
// Skip storing & propagating content if it's not valid
1616+
metrics.report_validation(false);
16091617
warn!(
16101618
error = %err,
16111619
content.key = %key.to_hex(),
16121620
"Error validating accepted content"
16131621
);
16141622
return None;
16151623
}
1624+
metrics.report_validation(true);
16161625

16171626
// Check if data should be stored, and store if true.
16181627
let key_desired = store.read().is_key_within_radius_and_unavailable(&key);
@@ -1808,6 +1817,7 @@ where
18081817
responder: Option<oneshot::Sender<RecursiveFindContentResult>>,
18091818
trace: Option<QueryTrace>,
18101819
nodes_to_poke: Vec<NodeId>,
1820+
metrics: Arc<OverlayMetrics>,
18111821
) {
18121822
let mut content = content;
18131823
// Operate under assumption that all content in the store is valid
@@ -1819,6 +1829,7 @@ where
18191829
} else {
18201830
let content_id = content_key.content_id();
18211831
if let Err(err) = validator.validate_content(&content_key, &content).await {
1832+
metrics.report_validation(false);
18221833
warn!(
18231834
error = ?err,
18241835
content.id = %hex_encode_compact(content_id),
@@ -1830,6 +1841,7 @@ where
18301841
}
18311842
return;
18321843
};
1844+
metrics.report_validation(true);
18331845

18341846
// skip storing if the content is already stored
18351847
// or if there's an error reading the store

0 commit comments

Comments
 (0)