Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding network usage information #740

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ println!("NB processors: {}", sys.processors().len());

// Display processes ID, name na disk usage:
for (pid, process) in sys.processes() {
println!("[{}] {} {:?}", pid, process.name(), process.disk_usage());
println!("[{}] {} {:?} {:?}", pid, process.name(), process.disk_usage(), process.network_usage());
}

```
Expand Down
43 changes: 43 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ assert_eq!(r.", stringify!($name), "(), false);
pub struct ProcessRefreshKind {
cpu: bool,
disk_usage: bool,
network_usage: bool,
}

impl ProcessRefreshKind {
Expand All @@ -195,11 +196,13 @@ impl ProcessRefreshKind {
///
/// assert_eq!(r.cpu(), true);
/// assert_eq!(r.disk_usage(), true);
/// assert_eq!(r.network_usage(), true);
/// ```
pub fn everything() -> Self {
Self {
cpu: true,
disk_usage: true,
network_usage: true,
}
}

Expand All @@ -210,6 +213,12 @@ impl ProcessRefreshKind {
with_disk_usage,
without_disk_usage
);
impl_get_set!(
ProcessRefreshKind,
network_usage,
with_network_usage,
without_network_usage
);
}

/// Used to determine what you want to refresh specifically on the [`System`] type.
Expand Down Expand Up @@ -694,6 +703,40 @@ pub struct DiskUsage {
pub read_bytes: u64,
}

/// Type containing received and trasmitted bytes on all interface.
///
/// It is returned by [`ProcessExt::network_usage`][crate::ProcessExt::network_usage].
///
/// ```no_run
/// use sysinfo::{ProcessExt, System, SystemExt};
///
/// let s = System::new_all();
/// for (pid, process) in s.processes() {
/// let network_usage = process.network_usage();
/// println!("[{}] received bytes : new/total => {}/{} B",
/// pid,
/// network_usage.received_bytes,
/// network_usage.total_received_bytes,
/// );
/// println!("[{}] transmitted bytes: new/total => {}/{} B",
/// pid,
/// network_usage.transmitted_bytes,
/// network_usage.total_transmitted_bytes,
/// );
/// }
/// ```
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)]
pub struct NetworkUsage {
/// Total number of transmit bytes.
pub total_transmitted_bytes: u64,
/// Number of transmit bytes since the last refresh.
pub transmitted_bytes: u64,
/// Total number of receive bytes.
pub total_received_bytes: u64,
/// Number of receive bytes since the last refresh.
pub received_bytes: u64,
}

/// Enum describing the different status of a process.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ProcessStatus {
Expand Down
1 change: 1 addition & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl fmt::Debug for Process {
.field("status", &self.status())
.field("root", &self.root())
.field("disk_usage", &self.disk_usage())
.field("network_usage", &self.network_usage())
.finish()
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ cfg_if::cfg_if! {
}

pub use common::{
get_current_pid, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, PidExt,
get_current_pid, DiskType, DiskUsage, Gid, LoadAvg, NetworkUsage, NetworksIter, Pid, PidExt,
ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, Processor, System};
Expand Down
61 changes: 60 additions & 1 deletion src/linux/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use libc::{gid_t, kill, uid_t};
use crate::sys::system::{SystemInfo, REMAINING_FILES};
use crate::sys::utils::{get_all_data, get_all_data_from_file, realpath};
use crate::utils::into_iter;
use crate::{DiskUsage, Pid, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal};
use crate::{DiskUsage, NetworkUsage, Pid, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal};

#[doc(hidden)]
impl From<u32> for ProcessStatus {
Expand Down Expand Up @@ -100,6 +100,10 @@ pub struct Process {
old_written_bytes: u64,
read_bytes: u64,
written_bytes: u64,
transmitted_bytes: u64,
old_transmitted_bytes: u64,
received_bytes: u64,
old_received_bytes: u64,
}

impl Process {
Expand Down Expand Up @@ -142,6 +146,10 @@ impl Process {
old_written_bytes: 0,
read_bytes: 0,
written_bytes: 0,
transmitted_bytes: 0,
old_transmitted_bytes: 0,
received_bytes: 0,
old_received_bytes: 0,
}
}
}
Expand Down Expand Up @@ -216,6 +224,17 @@ impl ProcessExt for Process {
total_read_bytes: self.read_bytes,
}
}

fn network_usage(&self) -> NetworkUsage {
NetworkUsage {
transmitted_bytes: self
.transmitted_bytes
.saturating_sub(self.old_transmitted_bytes),
total_transmitted_bytes: self.transmitted_bytes,
received_bytes: self.received_bytes.saturating_sub(self.old_received_bytes),
total_received_bytes: self.received_bytes,
}
}
}

impl Drop for Process {
Expand Down Expand Up @@ -253,6 +272,40 @@ pub(crate) fn set_time(p: &mut Process, utime: u64, stime: u64) {
p.updated = true;
}

pub(crate) fn update_process_network_activity(p: &mut Process, path: &Path) {
let mut path = PathBuf::from(path);
path.push("net/dev");
let data = match get_all_data(&path, 16_384) {
Ok(d) => d,
Err(_) => return,
};
p.old_received_bytes = p.received_bytes;
p.old_transmitted_bytes = p.transmitted_bytes;

let mut received_bytes = 0;
let mut transmitted_bytes = 0;

let mut lines = data.split('\n');

// Skip headers.
lines.next();
lines.next();

for line in lines {
let values = line.split_whitespace().collect::<Vec<&str>>();
if values.len() < 17 {
continue;
}

// received and transmitted bytes are contained in the first and ninth column.
received_bytes += values[1].parse::<u64>().ok().unwrap();
transmitted_bytes += values[9].parse::<u64>().ok().unwrap();
}

p.received_bytes = received_bytes;
p.transmitted_bytes = transmitted_bytes;
}

pub(crate) fn update_process_disk_activity(p: &mut Process, path: &Path) {
let mut path = PathBuf::from(path);
path.push("io");
Expand Down Expand Up @@ -348,6 +401,9 @@ pub(crate) fn _get_process_data(
if refresh_kind.disk_usage() {
update_process_disk_activity(entry, path);
}
if refresh_kind.network_usage() {
update_process_network_activity(entry, path);
}
return Ok((None, pid));
}

Expand Down Expand Up @@ -435,6 +491,9 @@ pub(crate) fn _get_process_data(
if refresh_kind.disk_usage() {
update_process_disk_activity(&mut p, path);
}
if refresh_kind.network_usage() {
update_process_network_activity(&mut p, path);
}
Ok((Some(p), pid))
}

Expand Down
26 changes: 24 additions & 2 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::{
sys::{Component, Disk, Networks, Process, Processor},
};
use crate::{
DiskType, DiskUsage, LoadAvg, NetworksIter, Pid, ProcessRefreshKind, ProcessStatus,
RefreshKind, Signal, User,
DiskType, DiskUsage, LoadAvg, NetworkUsage, NetworksIter, Pid, ProcessRefreshKind,
ProcessStatus, RefreshKind, Signal, User,
};

use std::collections::HashMap;
Expand Down Expand Up @@ -370,6 +370,28 @@ pub trait ProcessExt: Debug {
/// }
/// ```
fn disk_usage(&self) -> DiskUsage;

/// Returns number of bytes received and transmitted to all network.
///
/// ⚠️ This is currently only implemented on linux.
///
/// ```no_run
/// use sysinfo::{Pid, ProcessExt, System, SystemExt};
///
/// let s = System::new();
/// if let Some(process) = s.process(Pid::from(1337)) {
/// let network_usage = process.network_usage();
/// println!("received bytes : new/total => {}/{}",
/// network_usage.received_bytes,
/// network_usage.total_received_bytes,
/// );
/// println!("transmitted bytes: new/total => {}/{}",
/// network_usage.transmitted_bytes,
/// network_usage.total_transmitted_bytes,
/// );
/// }
/// ```
fn network_usage(&self) -> NetworkUsage;
}

/// Contains all the methods of the [`Processor`][crate::Processor] struct.
Expand Down
6 changes: 5 additions & 1 deletion src/unknown/process.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::{DiskUsage, Pid, ProcessExt, ProcessStatus, Signal};
use crate::{DiskUsage, NetworkUsage, Pid, ProcessExt, ProcessStatus, Signal};

use std::fmt;
use std::path::Path;
Expand Down Expand Up @@ -81,4 +81,8 @@ impl ProcessExt for Process {
fn disk_usage(&self) -> DiskUsage {
DiskUsage::default()
}

fn network_usage(&self) -> NetworkUsage {
NetworkUsage::default()
}
}