iperf3_rs/lib.rs
1#![warn(missing_docs)]
2
3//! Rust frontend APIs for driving upstream libiperf.
4//!
5//! `iperf3-rs` links upstream `esnet/iperf3` through FFI. The high-level
6//! [`IperfCommand`] API accepts ordinary iperf arguments, lets libiperf parse
7//! and run them, and can stream the same live interval metrics used by the CLI's
8//! Pushgateway exporter.
9//! Protocol-specific metrics are optional, so callers can distinguish a real
10//! zero from values that libiperf did not report for a TCP, UDP, or SCTP run.
11//! Metrics callbacks emit one aggregate stream direction per libiperf reporting
12//! interval. In bidirectional mode the client-side aggregate is the sending
13//! direction and the server-side aggregate is the receiving direction; this
14//! crate does not currently emit both bidirectional halves from one process.
15//!
16//! This crate is useful when a Rust program needs to run iperf tests directly,
17//! for example from a bot, controller, or test harness, without spawning an
18//! external `iperf3-rs` process and parsing stdout.
19//! High-level library runs suppress libiperf's ordinary stdout output by
20//! default; use [`IperfCommand::inherit_output`] or [`IperfCommand::logfile`]
21//! when an application intentionally wants upstream text output.
22//!
23//! # Examples
24//!
25//! Run a client and consume live interval metrics:
26//!
27//! ```no_run
28//! use std::time::Duration;
29//!
30//! use iperf3_rs::{IperfCommand, MetricEvent, MetricsMode, Result};
31//!
32//! fn main() -> Result<()> {
33//! let mut command = IperfCommand::client("127.0.0.1");
34//! command
35//! .duration(Duration::from_secs(10))
36//! .report_interval(Duration::from_secs(1));
37//!
38//! let (running, mut metrics) = command.spawn_with_metrics(MetricsMode::Interval)?;
39//!
40//! while let Some(event) = metrics.recv() {
41//! match event {
42//! MetricEvent::Interval(sample) => {
43//! println!("{} bit/s", sample.bandwidth_bits_per_second);
44//! }
45//! MetricEvent::Window(window) => {
46//! println!("{} bytes", window.transferred_bytes);
47//! }
48//! _ => {}
49//! }
50//! }
51//!
52//! running.wait()?;
53//! Ok(())
54//! }
55//! ```
56//!
57//! # Concurrency
58//!
59//! High-level [`IperfCommand`] runs are serialized inside the process. libiperf
60//! has process-global state for errors, signal handling, and output hooks, so
61//! this crate intentionally avoids promising in-process parallelism that
62//! upstream does not clearly guarantee. Server runs must use iperf's one-off
63//! mode (`-s -1`) by default; opt in with
64//! [`IperfCommand::allow_unbounded_server`] only when the process is dedicated
65//! to that long-lived server.
66//!
67//! [`RunningIperf`] observes worker completion; it is not a cancellation or kill
68//! handle. Dropping it detaches the worker, and
69//! [`RunningIperf::wait_timeout`] only stops waiting. It does not stop libiperf.
70//! Use a separate process, container, VM, or another process-backed wrapper for
71//! runs that must be externally terminated, isolated from hangs, or executed in
72//! parallel.
73//!
74//! # Metrics stream ownership
75//!
76//! [`MetricsMode::Interval`] and [`MetricsMode::Window`] are every-sample
77//! library streams. They preserve all events by using unbounded internal queues,
78//! so long-running runs must continuously drain [`MetricsStream`] or disable
79//! metrics. [`IperfCommand::run`] collects emitted events in memory before
80//! returning; do not combine it with metrics for unbounded server runs or other
81//! runs that can produce an unbounded number of samples.
82
83#[cfg(all(feature = "pushgateway", feature = "serde"))]
84mod args;
85#[cfg(all(feature = "pushgateway", feature = "serde"))]
86mod cli;
87mod command;
88mod error;
89#[cfg(all(feature = "pushgateway", feature = "serde"))]
90mod help;
91
92mod iperf;
93mod metrics;
94#[cfg(feature = "serde")]
95mod metrics_file;
96mod prometheus;
97#[cfg(feature = "pushgateway")]
98mod pushgateway;
99#[cfg(all(feature = "pushgateway", feature = "serde"))]
100mod version;
101
102pub use command::{IperfCommand, IperfResult, RunningIperf};
103pub use error::{Error, ErrorKind, Result};
104pub use iperf::{Role, libiperf_version, usage_long};
105pub use metrics::{
106 MetricDirection, MetricEvent, Metrics, MetricsMode, MetricsRecvError, MetricsStream,
107 TransportProtocol, WindowGaugeStats, WindowMetrics, aggregate_window,
108};
109#[cfg(feature = "serde")]
110pub use metrics_file::{MetricsFileFormat, MetricsFileSink};
111pub use prometheus::PrometheusEncoder;
112#[cfg(feature = "pushgateway")]
113pub use pushgateway::{PushGateway, PushGatewayConfig};
114
115#[cfg(all(feature = "pushgateway", feature = "serde"))]
116#[doc(hidden)]
117pub fn __private_cli_main() -> std::process::ExitCode {
118 cli::main()
119}