Skip to content

bug: PathStats seem to be missing/outdated sometimes #3846

@matheus23

Description

@matheus23

This happens on iroh main, (not necessarily the latest release).

Relevant Logs
I'm comparing PathStats from the watcher you get on the iroh connection vs. iterating through a bunch of PathIds and fetching the stats for all of them that we actually get:

Path stats:
  Relay(RelayUrl("https://127.0.0.1:33909/")): RTT 66.865248ms, 7 packets sent
  Ip(127.0.0.1:56796): RTT 4.78022ms, 4 packets sent
  Ip(192.168.160.202:56796): RTT 19.12088ms, 8 packets sent
  Ip([3fff:172:20:20::1]:49108): RTT 6.737371ms, 2 packets sent
Path stats in conn:
  [0]: RTT 58.712621ms, 9 packets sent
  [1]: RTT 8.21914ms, 19 packets sent
  [2]: RTT 9.322508ms, 6 packets sent
  [3]: RTT 8.432184ms, 6 packets sent
  [4]: RTT 9.322508ms, 6 packets sent
  [5]: RTT 9.322508ms, 6 packets sent
  [6]: RTT 9.322508ms, 6 packets sent

The first set is the path stats from iroh, the second set is the path stats from quinn.

PathStats doesn't list paths that are abandoned, but not yet discarded, so it's possible that quinn shows more paths due to that.
But also, the data from the path stats seem to be outdated in general.

Iroh

Version: f2b6026

Additional Context / Screenshots / GIFs
This is the code I use to print the stats:

async fn watch_paths(conn: Connection) -> Result<()> {
    let mut paths = conn.paths();
    let mut stats = BTreeMap::new();
    while conn.close_reason().is_none() {
        tokio::select! {
            _ = conn.closed() => break,
            _ = paths.updated() => {},
        }
        for path in paths.get() {
            stats.insert(path.id(), (path.remote_addr().clone(), path.stats()));
        }
    }
    let mut stats_by_remote = BTreeMap::<TransportAddr, PathStats>::new();
    for (_, (remote_addr, stats)) in stats {
        let value = stats_by_remote.entry(remote_addr).or_default();
        value.rtt += stats.rtt;
        value.sent_packets += stats.sent_packets;
    }
    println!("Path stats:");
    for (remote, stats) in stats_by_remote {
        println!(
            "  {remote:?}: RTT {:?}, {} packets sent",
            stats.rtt, stats.sent_packets
        );
    }

    println!("Path stats in conn:");
    for i in 0..10 {
        let path_id = PathId(i);
        if let Some(stats) = conn.inner.path_stats(path_id) {
            println!(
                "  [{path_id}]: RTT {:?}, {} packets sent",
                stats.rtt, stats.sent_packets
            );
        }
    }
    Ok(())
}

There's some additional changes, (and it needs the PathId constructor in quinn to be made public), so it's only a rough test.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingc-irohFunctionality of the core iroh crate.metricsextracting quantified mesurements from iroh

Type

Projects

Status

✅ Done

Relationships

None yet

Development

No branches or pull requests

Issue actions