mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-30 11:11:21 +00:00
252 lines
8.6 KiB
Rust
252 lines
8.6 KiB
Rust
/*
|
|
* Copyright 2020 Fluence Labs Limited
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#![deny(dead_code)]
|
|
|
|
use prometheus::{IntCounterVec, IntGauge, Opts, Registry};
|
|
|
|
use libp2p_core::PeerId;
|
|
use libp2p_swarm::NetworkBehaviourAction;
|
|
|
|
use crate::handler::{KademliaHandlerEvent, KademliaHandlerIn};
|
|
use crate::{KademliaEvent, QueryId};
|
|
|
|
pub(super) enum Kind {
|
|
Request,
|
|
Response,
|
|
Error,
|
|
}
|
|
|
|
struct InnerMetrics {
|
|
// Requests sent via NotifyHandler (KademliaHandlerIn)
|
|
sent_requests: IntCounterVec,
|
|
// Responses sent via NotifyHandler (KademliaHandlerIn)
|
|
sent_responses: IntCounterVec,
|
|
// Requests received via inject_event
|
|
received_requests: IntCounterVec,
|
|
// Responses received via inject_event
|
|
received_responses: IntCounterVec,
|
|
errors: IntCounterVec,
|
|
records_stored: IntGauge,
|
|
connected_nodes: IntGauge,
|
|
routing_table_size: IntGauge,
|
|
// Kademlia events (except NotifyHandler)
|
|
kademlia_events: IntCounterVec,
|
|
// TODO: nodes received in queries?
|
|
}
|
|
|
|
enum Inner {
|
|
Disabled,
|
|
Enabled(InnerMetrics),
|
|
}
|
|
|
|
pub(super) struct Metrics {
|
|
inner: Inner,
|
|
}
|
|
|
|
impl Metrics {
|
|
pub(super) fn disabled() -> Self {
|
|
Self {
|
|
inner: Inner::Disabled,
|
|
}
|
|
}
|
|
|
|
pub(super) fn enabled(registry: &Registry, peer_id: &PeerId) -> Self {
|
|
let peer_id = bs58::encode(peer_id).into_string();
|
|
let opts = |name: &str| -> Opts {
|
|
let mut opts = Opts::new(name, name)
|
|
.namespace("libp2p")
|
|
.subsystem("kad")
|
|
.const_label("peer_id", peer_id.as_str());
|
|
opts.name = name.into();
|
|
opts.help = name.into(); // TODO: better help?
|
|
opts
|
|
};
|
|
|
|
// Creates and registers counter in registry
|
|
let counter = |name: &str, label_names: &[&str]| -> IntCounterVec {
|
|
let counter = IntCounterVec::new(opts(name), label_names)
|
|
.expect(format!("create {}", name).as_str());
|
|
|
|
registry
|
|
.register(Box::new(counter.clone()))
|
|
.expect(format!("register {}", name).as_str());
|
|
counter
|
|
};
|
|
|
|
let gauge = |name: &str| -> IntGauge {
|
|
let gauge = IntGauge::with_opts(opts(name)).expect(format!("create {}", name).as_str());
|
|
registry
|
|
.register(Box::new(gauge.clone()))
|
|
.expect(format!("register {}", name).as_str());
|
|
gauge
|
|
};
|
|
|
|
// let requests = &["find_node", "get_providers", "add_provider", "get_record", "put_record"];
|
|
// let responses = &["find_node", "get_providers", "get_record", "put_record"];
|
|
// let errors = &["todo"]; // TODO: fill error types
|
|
|
|
let name = &["name"];
|
|
|
|
let sent_requests = counter("sent_requests", name);
|
|
let received_requests = counter("received_requests", name);
|
|
let sent_responses = counter("sent_responses", name);
|
|
let received_responses = counter("received_responses", name);
|
|
let kademlia_events = counter("kademlia_event", name);
|
|
let errors = counter("errors", name);
|
|
let records_stored = gauge("records_stored");
|
|
let connected_nodes = gauge("connected_nodes");
|
|
let routing_table_size = gauge("routing_table_size");
|
|
|
|
Self {
|
|
inner: Inner::Enabled(InnerMetrics {
|
|
sent_requests,
|
|
received_responses,
|
|
received_requests,
|
|
sent_responses,
|
|
errors,
|
|
records_stored,
|
|
connected_nodes,
|
|
kademlia_events,
|
|
routing_table_size,
|
|
}),
|
|
}
|
|
}
|
|
|
|
fn with_metrics<F>(&self, f: F)
|
|
where
|
|
F: FnOnce(&InnerMetrics),
|
|
{
|
|
if let Inner::Enabled(metrics) = &self.inner {
|
|
f(metrics)
|
|
}
|
|
}
|
|
|
|
fn inc_by_name(name: &str, counter: &IntCounterVec) {
|
|
match counter.get_metric_with_label_values(&[name]) {
|
|
Ok(c) => c.inc(),
|
|
Err(e) => log::warn!("failed to increment counter {}: {:?}", name, e),
|
|
}
|
|
}
|
|
|
|
pub(super) fn node_connected(&self) {
|
|
self.with_metrics(|m| m.connected_nodes.inc());
|
|
}
|
|
|
|
pub(super) fn received(&self, event: &KademliaHandlerEvent<QueryId>) {
|
|
use Kind::*;
|
|
|
|
let (name, kind) = match event {
|
|
// requests
|
|
KademliaHandlerEvent::FindNodeReq { .. } => ("find_node_req", Request),
|
|
KademliaHandlerEvent::GetProvidersReq { .. } => ("get_providers_req", Request),
|
|
KademliaHandlerEvent::AddProvider { .. } => ("add_provider", Request),
|
|
KademliaHandlerEvent::GetRecord { .. } => ("get_record", Request),
|
|
KademliaHandlerEvent::PutRecord { .. } => ("put_record", Request),
|
|
|
|
// responses
|
|
KademliaHandlerEvent::FindNodeRes { .. } => ("find_node_res", Response),
|
|
KademliaHandlerEvent::GetProvidersRes { .. } => ("get_providers_res", Response),
|
|
KademliaHandlerEvent::GetRecordRes { .. } => ("get_record_res", Response),
|
|
KademliaHandlerEvent::PutRecordRes { .. } => ("put_record_res", Response),
|
|
|
|
// error
|
|
KademliaHandlerEvent::QueryError { .. } => ("query_error_from_handler", Error),
|
|
};
|
|
|
|
self.with_metrics(|m| {
|
|
let counter = match &kind {
|
|
Request => &m.sent_requests,
|
|
Response => &m.sent_responses,
|
|
Error => &m.errors,
|
|
};
|
|
|
|
Self::inc_by_name(name, counter);
|
|
});
|
|
}
|
|
|
|
pub(super) fn sent(&self, event: &KademliaHandlerIn<QueryId>) {
|
|
use Kind::*;
|
|
|
|
let (name, kind) = match event {
|
|
// requests
|
|
KademliaHandlerIn::FindNodeReq { .. } => ("find_node", Request),
|
|
KademliaHandlerIn::GetProvidersReq { .. } => ("get_providers", Request),
|
|
KademliaHandlerIn::AddProvider { .. } => ("add_provider", Request),
|
|
KademliaHandlerIn::GetRecord { .. } => ("get_record", Request),
|
|
KademliaHandlerIn::PutRecord { .. } => ("put_record", Request),
|
|
|
|
// responses
|
|
KademliaHandlerIn::GetProvidersRes { .. } => ("get_providers", Request),
|
|
KademliaHandlerIn::GetRecordRes { .. } => ("get_record", Request),
|
|
KademliaHandlerIn::PutRecordRes { .. } => ("put_record", Request),
|
|
KademliaHandlerIn::FindNodeRes { .. } => ("find_node", Request),
|
|
|
|
// error
|
|
KademliaHandlerIn::Reset(_) => ("sent_reset", Request),
|
|
};
|
|
|
|
self.with_metrics(|m| {
|
|
let counter = match &kind {
|
|
Request => &m.received_requests,
|
|
Response => &m.received_responses,
|
|
Error => &m.errors,
|
|
};
|
|
|
|
Self::inc_by_name(name, counter);
|
|
});
|
|
}
|
|
|
|
pub(super) fn generated_event_name(event: &KademliaEvent) -> &str {
|
|
match event {
|
|
KademliaEvent::QueryResult { .. } => "query_result",
|
|
KademliaEvent::Discovered { .. } => "discovered",
|
|
KademliaEvent::RoutingUpdated { .. } => "routing_updated",
|
|
KademliaEvent::UnroutablePeer { .. } => "unroutable_peer",
|
|
}
|
|
}
|
|
|
|
pub(super) fn polled_event(
|
|
&self,
|
|
event: &NetworkBehaviourAction<KademliaHandlerIn<QueryId>, KademliaEvent>,
|
|
) {
|
|
let name = match event {
|
|
NetworkBehaviourAction::DialAddress { .. } => "dial_address",
|
|
NetworkBehaviourAction::DialPeer { .. } => "dial_peer",
|
|
NetworkBehaviourAction::ReportObservedAddr { .. } => "report_observed_addr",
|
|
NetworkBehaviourAction::GenerateEvent(e) => Self::generated_event_name(e),
|
|
NetworkBehaviourAction::NotifyHandler { event, .. } => {
|
|
self.sent(event);
|
|
return;
|
|
}
|
|
};
|
|
|
|
self.with_metrics(|m| Self::inc_by_name(name, &m.kademlia_events));
|
|
}
|
|
|
|
pub(super) fn store_put(&self) {
|
|
self.with_metrics(|m| m.records_stored.inc())
|
|
}
|
|
|
|
pub(super) fn record_removed(&self) {
|
|
self.with_metrics(|m| m.records_stored.dec())
|
|
}
|
|
|
|
pub(super) fn report_routing_table_size(&self, size: usize) {
|
|
self.with_metrics(|m| m.routing_table_size.set(size as i64))
|
|
}
|
|
}
|