1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100

use std::collections::HashMap;
use std::io::Error;
use serde::{Serialize, Serializer};
use sysinfo::{NetworkExt, System, SystemExt, Disk, Process, Component, Processor};
use hostname::get_hostname;


/// `sysinfo` with extended features
pub struct SysinfoExt<'a> {
    process_list: HashMap<i32, Process>,
    processor_list: &'a [Processor],
    components_list: &'a [Component],
    disks: &'a [Disk],
    memory: [u64; 6],
    hostname: String,
    uptime: String,
    pub bandwith: (u64, u64),
}


impl<'a> SysinfoExt<'a> {
    pub fn new(system: &'a System) -> Self {
        let network = system.get_network();
        SysinfoExt {
            process_list: system.get_process_list()
                .iter()
                // filter unnamed kernel threads
                .filter(|p| !p.1.name.is_empty())
                .map(|p| {
                    (*p.0,
                     {
                         let mut t = p.1.clone();
                         // clear tasks to save up some space
                         #[cfg(target_os = "linux")]
                         t.tasks.clear();
                         // clear environment variables
                         t.environ.clear();
                         // clear command line arguments
                         t.cmd.clear();
                         t
                    })
                })
                .collect(),
            processor_list: system.get_processor_list(),
            components_list: system.get_components_list(),
            disks: system.get_disks(),
            memory: [system.get_total_memory(),
                     system.get_used_memory(),
                     system.get_free_memory(),
                     system.get_total_swap(),
                     system.get_used_swap(),
                     system.get_free_swap()],
            hostname: get_hostname().unwrap_or("Unknown".to_owned()),
            uptime: get_uptime().unwrap_or("Unknown".to_owned()),
            bandwith: (network.get_income(), network.get_outcome()),
        }
    }
}



impl<'a> Serialize for SysinfoExt<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        use serde::ser::SerializeMap;
        use sysinfo_serde::Ser;
        let mut map = serializer.serialize_map(None)?;
        map.serialize_entry("processor_list",
                             &self.processor_list
                                 .iter()
                                 .map(|p| Ser::new(p))
                                 .collect::<Vec<Ser<Processor>>>())?;
        map.serialize_entry("process_list", &Ser::new(&self.process_list))?;
        map.serialize_entry("components_list",
                             &self.components_list
                                 .iter()
                                 .map(|c| Ser::new(c))
                                 .collect::<Vec<Ser<Component>>>())?;
        map.serialize_entry("disks",
                             &self.disks
                                 .iter()
                                 .map(|d| Ser::new(d))
                                 .collect::<Vec<Ser<Disk>>>())?;
        map.serialize_entry("memory", &self.memory)?;
        map.serialize_entry("hostname", &self.hostname)?;
        map.serialize_entry("uptime", &self.uptime)?;
        map.serialize_entry("bandwith", &self.bandwith)?;
        map.end()
    }
}


/// Gets uptime from /proc/uptime and converts it to human readable String
fn get_uptime() -> Result<String, Error> {
    use std::process::Command;
    let output = Command::new("uptime").output()?;
    Ok(String::from_utf8(output.stdout).unwrap_or("Unknown".to_owned()))
}