Skip to content

Commit

Permalink
Add support for publishing kernel statistics to oximeter
Browse files Browse the repository at this point in the history
  • Loading branch information
bnaecker committed Oct 17, 2023
1 parent 7d88789 commit 32bb1ca
Show file tree
Hide file tree
Showing 8 changed files with 523 additions and 3 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ ipcc-key-value = { path = "ipcc-key-value" }
ipnetwork = { version = "0.20", features = ["schemars"] }
itertools = "0.11.0"
key-manager = { path = "key-manager" }
kstat-rs = { path = "/home/bnaecker/kstat-rs" }
lazy_static = "1.4.0"
libc = "0.2.149"
linear-map = "1.2.0"
Expand Down
8 changes: 6 additions & 2 deletions oximeter/instruments/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ license = "MPL-2.0"
chrono.workspace = true
dropshot.workspace = true
futures.workspace = true
http = { workspace = true, optional = true }
kstat-rs = { workspace = true, optional = true }
oximeter.workspace = true
serde = { workspace = true, optional = true }
tokio.workspace = true
http = { workspace = true, optional = true }
thiserror.workspace = true
uuid.workspace = true
omicron-workspace-hack.workspace = true

[features]
default = ["http-instruments"]
default = ["http-instruments", "kstat"]
http-instruments = ["http"]
kstat = ["kstat-rs", "serde"]
151 changes: 151 additions & 0 deletions oximeter/instruments/src/kstat/link.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Report metrics about Ethernet data links on the host system
use crate::kstat::kstat_snapshot_time;
use crate::kstat::ConvertNamedData;
use crate::kstat::Error;
use crate::kstat::KstatList;
use crate::kstat::KstatTarget;
use kstat_rs::Data;
use kstat_rs::Kstat;
use kstat_rs::Named;
use oximeter::types::Cumulative;
use oximeter::Metric;
use oximeter::Sample;
use oximeter::Target;
use uuid::Uuid;

/// Information about a single physical Ethernet link on a host.
#[derive(Debug, Target)]
pub struct PhysicalDataLink {
/// The ID of the rack (cluster) containing this host.
rack_id: Uuid,
/// The ID of the sled itself.
sled_id: Uuid,
/// The name of the host.
hostname: String,
/// The name of the link.
link_name: String,
}

/// Information about a virtual Ethernet link on a host.
///
/// Note that this is specifically for a VNIC in on the host system, not a guest
/// data link.
#[derive(Debug, Target)]
pub struct VirtualDataLink {
/// The ID of the rack (cluster) containing this host.
rack_id: Uuid,
/// The ID of the sled itself.
sled_id: Uuid,
/// The name of the host.
hostname: String,
/// The name of the link.
link_name: String,
}

/// Information about a guest virtual Ethernet link.
#[derive(Debug, Target)]
pub struct GuestDataLink {
/// The ID of the rack (cluster) containing this host.
rack_id: Uuid,
/// The ID of the sled itself.
sled_id: Uuid,
/// The name of the host.
hostname: String,
/// The ID of the project containing the instance.
project_id: Uuid,
/// The ID of the instance.
instance_id: Uuid,
/// The name of the link.
link_name: String,
}

/// The number of packets received on the link.
#[derive(Clone, Copy, Metric)]
pub struct PacketsReceived {
datum: Cumulative<u64>,
}

/// The number of packets sent on the link.
#[derive(Clone, Copy, Metric)]
pub struct PacketsSent {
datum: Cumulative<u64>,
}

/// The number of bytes sent on the link.
#[derive(Clone, Copy, Metric)]
pub struct BytesSent {
datum: Cumulative<u64>,
}

/// The number of bytes received on the link.
#[derive(Clone, Copy, Metric)]
pub struct BytesReceived {
datum: Cumulative<u64>,
}

/// The number of errors received on the link.
#[derive(Clone, Copy, Metric)]
pub struct ErrorsReceived {
datum: Cumulative<u64>,
}

/// The number of errors sent on the link.
#[derive(Clone, Copy, Metric)]
pub struct ErrorsSent {
datum: Cumulative<u64>,
}

impl KstatTarget for PhysicalDataLink {
fn interested<'a>(&self, kstat: &Kstat<'a>) -> bool {
kstat.ks_module == "link"
&& kstat.ks_instance == 0
&& kstat.ks_name == &self.link_name
}

fn to_samples<'k>(
&self,
kstats: KstatList<'_, 'k>,
) -> Result<Vec<Sample>, Error> {
let (creation_time, kstat, data) = kstats.first().unwrap();
let snapshot_time = kstat_snapshot_time(&kstat)?;
let Data::Named(named) = data else {
return Err(Error::ExpectedNamedKstat);
};
named
.iter()
.filter_map(|nd| {
let Named { name, value } = nd;
if *name == "rbytes64" {
Some(value.as_u64().and_then(|x| {
let metric = BytesReceived {
datum: Cumulative::with_start_time(
*creation_time,
x,
),
};
Sample::new_with_timestamp(snapshot_time, self, &metric)
.map_err(Error::Sample)
}))
} else if *name == "obytes64" {
Some(value.as_u64().and_then(|x| {
let metric = BytesSent {
datum: Cumulative::with_start_time(
*creation_time,
x,
),
};
Sample::new_with_timestamp(snapshot_time, self, &metric)
.map_err(Error::Sample)
}))
} else {
None
}
})
.collect()
}
}
Loading

0 comments on commit 32bb1ca

Please sign in to comment.