summaryrefslogtreecommitdiffstats
path: root/src/transport/stats.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/stats.rs')
-rw-r--r--src/transport/stats.rs141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/transport/stats.rs b/src/transport/stats.rs
new file mode 100644
index 0000000..35238f5
--- /dev/null
+++ b/src/transport/stats.rs
@@ -0,0 +1,141 @@
+//! Figures about the transports themselves (`Transport::stats`), for /admin/stats
+//! (`transports`, `docs/measurements.md`): how they find and reach peers, besides the
+//! messages counted per peer (`traffic`).
+
+use std::collections::BTreeMap;
+
+use serde::Serialize;
+
+#[derive(Debug, Clone, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct TransportStats {
+ /// The identity layer's (`transport::identity`); absent without one.
+ pub(crate) identity: Option<IdentityStats>,
+ /// The libp2p transport's; absent if it isn't one of this node's.
+ pub(crate) libp2p: Option<Libp2pStats>,
+}
+
+impl TransportStats {
+ /// Takes what `other` has.
+ pub(crate) fn merge(&mut self, other: TransportStats) {
+ if other.identity.is_some() {
+ self.identity = other.identity;
+ }
+ if other.libp2p.is_some() {
+ self.libp2p = other.libp2p;
+ }
+ }
+}
+
+/// Who is where (`transport::identity`): the books now, and counts since start.
+#[derive(Debug, Clone, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct IdentityStats {
+ /// Nodes proven at an address, by transport (scheme); a node on several counts on
+ /// each.
+ pub(crate) proven: BTreeMap<String, usize>,
+ /// Nodes known only from hints (the member list, HELLO_REPLYs), proven nowhere.
+ pub(crate) hinted: usize,
+ #[serde(flatten)]
+ pub(crate) counts: IdentityCounts,
+}
+
+#[derive(Debug, Clone, Copy, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct IdentityCounts {
+ /// Proofs that didn't hold (a bad signature, or made for other addresses): normally
+ /// none.
+ pub(crate) proofs_rejected: u64,
+ /// Nodes that proved themselves at another address on a transport than before: a
+ /// node restarted with a new transport identity (a new libp2p key or Mycelium key).
+ pub(crate) address_changes: u64,
+ /// Messages dropped because no node proved itself at their address: some after a
+ /// restart are normal, a steady stream is not.
+ pub(crate) dropped_unproven: u64,
+ /// Sends refused because the peer hadn't proven where it is yet (`NotProven`).
+ pub(crate) refused_unproven: u64,
+ /// Seeds no node answered at in time.
+ pub(crate) seeds_unanswered: u64,
+}
+
+/// Whether others can dial this node, as AutoNAT found out.
+#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) enum Reachability {
+ #[default]
+ Unknown,
+ /// Others can't dial it: it needs a relay.
+ Private,
+ Public,
+}
+
+impl Reachability {
+ pub(crate) const ALL: [Reachability; 3] = [Self::Unknown, Self::Private, Self::Public];
+
+ pub(crate) fn as_str(self) -> &'static str {
+ match self {
+ Self::Unknown => "unknown",
+ Self::Private => "private",
+ Self::Public => "public",
+ }
+ }
+}
+
+#[derive(Debug, Clone, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct Libp2pStats {
+ pub(crate) reachability: Reachability,
+ /// The address AutoNAT confirmed others can dial, while public.
+ pub(crate) public_address: Option<String>,
+ /// Open connections, now.
+ pub(crate) connections: Connections,
+ pub(crate) relay_slots: RelaySlots,
+ /// Direct connections tried over a relayed one (DCUtR), since start.
+ pub(crate) hole_punches: HolePunches,
+ /// Connections that couldn't be made, by cause, since start.
+ pub(crate) dial_failures: DialFailures,
+}
+
+#[derive(Debug, Clone, Copy, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct Connections {
+ pub(crate) direct: usize,
+ /// Through a relay (a circuit).
+ pub(crate) relayed: usize,
+}
+
+/// Slots this node holds on relays, to be reachable through them.
+#[derive(Debug, Clone, Copy, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct RelaySlots {
+ /// Held now.
+ pub(crate) held: usize,
+ /// Relays picked that never granted a slot, not picked again for a while now.
+ pub(crate) paused: usize,
+ /// Since start: slots granted (not counting renewals), lost after being granted, and
+ /// asked for but never granted (a relay unreachable, or another peer at its
+ /// address: a relay restarted without its libp2p key).
+ pub(crate) granted: u64,
+ pub(crate) lost: u64,
+ pub(crate) not_granted: u64,
+}
+
+#[derive(Debug, Clone, Copy, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct HolePunches {
+ pub(crate) succeeded: u64,
+ /// The relay carries on.
+ pub(crate) failed: u64,
+}
+
+#[derive(Debug, Clone, Copy, Default, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct DialFailures {
+ /// No address of the peer could be reached (refused, timed out, no route).
+ pub(crate) unreachable: u64,
+ /// Another peer answered at the address: one restarted without its libp2p key.
+ pub(crate) wrong_peer_id: u64,
+ /// No address known for the peer.
+ pub(crate) no_addresses: u64,
+ pub(crate) other: u64,
+}