Skip to content

Commit

Permalink
[network metrics] instance data link schema
Browse files Browse the repository at this point in the history
This is related to the ongoing work in [plumbing instance/guest
metrics](oxidecomputer/propolis#742) through to an
oximeter producer in propolis.

Includes:
- Rewriting the comment for `trait Target` in Oximeter to not being
  prepped for deprecation, as it does come in handy for custom needs
- The main differentiaing field among link information here is `interface_id`,
  which is exposed to propolis via the client's `NetworkInterfaceRequest`.
  We currently match the nic.slot to the port.slot to pass which of
  the requested nics `interface_id` uuids are part of the request.
  • Loading branch information
zeeshanlakhani committed Aug 21, 2024
1 parent d24003b commit 73ad0e2
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 19 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -778,9 +778,9 @@ opt-level = 3
#dropshot = { path = "../dropshot/dropshot" }
#[patch.crates-io]
#steno = { path = "../steno" }
#[patch."https://github.com/oxidecomputer/propolis"]
#propolis-client = { path = "../propolis/lib/propolis-client" }
#propolis-mock-server = { path = "../propolis/bin/mock-server" }
# [patch."https://github.com/oxidecomputer/propolis"]
# propolis-client = { path = "../propolis/lib/propolis-client" }
# propolis-mock-server = { path = "../propolis/bin/mock-server" }
#[patch."https://github.com/oxidecomputer/crucible"]
#crucible-agent-client = { path = "../crucible/agent-client" }
#crucible-pantry-client = { path = "../crucible/pantry-client" }
Expand Down
2 changes: 1 addition & 1 deletion oximeter/instruments/src/kstat/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use oximeter::Sample;

oximeter::use_timeseries!("sled-data-link.toml");

// Helper function to extract the same kstat metrics from all link targets.
/// Helper function to extract the same kstat metrics from all link targets.
fn extract_link_kstats<T>(
target: &T,
named_data: &Named,
Expand Down
1 change: 0 additions & 1 deletion oximeter/instruments/src/kstat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ pub trait KstatTarget:
) -> Result<Vec<Sample>, Error>;
}

/// Convert from a high-res timestamp into UTC, if possible.
pub fn hrtime_to_utc(hrtime: i64) -> Result<DateTime<Utc>, Error> {
let utc_now = Utc::now();
let hrtime_now = get_hires_time();
Expand Down
90 changes: 90 additions & 0 deletions oximeter/oximeter/schema/instance-data-link.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
format_version = 1

[target]
name = "instance_data_link"
description = "A network data link related to a guest/instance"
authz_scope = "fleet"
versions = [
{ version = 1, fields = [ "kind", "interface_id", "instance_id", "project_id", "silo_id", "sled_id", "sled_model", "sled_revision", "sled_serial" ] },
]

[[metrics]]
name = "bytes_sent"
description = "Total number of bytes sent on the data link"
units = "bytes"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[[metrics]]
name = "bytes_received"
description = "Total number of bytes received on the data link"
units = "bytes"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[[metrics]]
name = "packets_sent"
description = "Total number of packets sent on the data link"
units = "count"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[[metrics]]
name = "packets_received"
description = "Total number of packets received on the data link"
units = "count"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[[metrics]]
name = "packets_dropped"
description = "Number of packets dropped on the RX queue of the data link"
units = "count"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[fields.kind]
type = "string"
description = "The kind or class of the data link"

[fields.interface_id]
type = "uuid"
description = "ID of the associated virtual network interface"

[fields.instance_id]
type = "uuid"
description = "ID of the virtual machine instance"

[fields.project_id]
type = "uuid"
description = "ID of the virtual machine instance's project"

[fields.silo_id]
type = "uuid"
description = "ID of the virtual machine instance's silo"

[fields.sled_id]
type = "uuid"
description = "ID of the sled managing the link's switch"

[fields.sled_model]
type = "string"
description = "Model number of the sled managing the link's switch"

[fields.sled_revision]
type = "u32"
description = "Revision number of the sled managing the link's switch"

[fields.sled_serial]
type = "string"
description = "Serial number of the sled managing the link's switch"
24 changes: 14 additions & 10 deletions oximeter/types/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ use std::num::NonZeroU8;
use std::ops::Add;
use std::ops::AddAssign;

/// The `Target` trait identifies a source of metric data by a sequence of fields.
///
/// A target is a single source of metric data, identified by a sequence of named and typed field
/// values. Users can write a single struct definition and derive this trait. The methods here
/// provide some introspection into the struct, listing its fields and their values. The struct
/// definition can be thought of as a schema, and an instance of that struct as identifying an
/// The `Target` trait identifies a source of metric data by a sequence of
/// fields.
///
/// A target is a single source of metric data, identified by a sequence of
/// named and typed field values. Users can write a single struct definition and
/// derive this trait. The methods here provide some introspection into the
/// struct, listing its fields and their values. The struct definition can be
/// thought of as a schema, and an instance of that struct as identifying an
/// individual target.
///
/// Target fields may have one of a set of supported types:
Expand Down Expand Up @@ -85,10 +87,12 @@ use std::ops::AddAssign;
/// }
/// ```
///
/// **Important:** Deriving this trait is deprecated, and will be removed in the
/// future. Instead, define your timeseries schema through the TOML format
/// described in [the crate documentation](crate), and use the code
/// generated by the `use_timeseries` macro.
/// **Important:** Typically, you should define your timeseries schema through
/// the TOML format described in [the crate documentation](crate), and use the
/// code generated by the `use_timeseries` macro. However, if you need to handle
/// custom sampling logic and must define custom field definitions not published
/// as part of the target schema, you can implement this trait as long as you
/// define the target as one of the field(s) in the struct.
pub trait Target {
/// Return the name of the target, which is the snake_case form of the struct's name.
fn name(&self) -> &'static str;
Expand Down
19 changes: 15 additions & 4 deletions sled-agent/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,22 @@ impl InstanceRunner {
) -> Result<(), Error> {
let nics = running_zone
.opte_ports()
.map(|port| propolis_client::types::NetworkInterfaceRequest {
name: port.name().to_string(),
slot: propolis_client::types::Slot(port.slot()),
.filter_map(|port| {
let interface_id = self
.requested_nics
.iter()
// We expect to match NIC slots to OPTE port slots.
.find(|nic| nic.slot == port.slot())
.map(|nic| nic.id);
interface_id.map(|id| {
propolis_client::types::NetworkInterfaceRequest {
interface_id: id,
name: port.name().to_string(),
slot: propolis_client::types::Slot(port.slot()),
}
})
})
.collect();
.collect::<Vec<_>>();

let migrate = match migrate {
Some(params) => {
Expand Down

0 comments on commit 73ad0e2

Please sign in to comment.