Skip to content

Commit

Permalink
[network metrics] instance network interface schema (#6414)
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 differentiating field among instance network 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.

## Dependencies 

- [X] Propolis => oxidecomputer/propolis#747
  • Loading branch information
zeeshanlakhani authored Sep 3, 2024
1 parent 46eb2b4 commit 5bf5f09
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 62 deletions.
53 changes: 35 additions & 18 deletions Cargo.lock

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

28 changes: 15 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ cookie = "0.18"
criterion = { version = "0.5.1", features = [ "async_tokio" ] }
crossbeam = "0.8"
crossterm = { version = "0.28.1", features = ["event-stream"] }
crucible-agent-client = { git = "https://github.com/oxidecomputer/crucible", rev = "e58ca3693cb9ce0438947beba10e97ee38a0966b" }
crucible-pantry-client = { git = "https://github.com/oxidecomputer/crucible", rev = "e58ca3693cb9ce0438947beba10e97ee38a0966b" }
crucible-smf = { git = "https://github.com/oxidecomputer/crucible", rev = "e58ca3693cb9ce0438947beba10e97ee38a0966b" }
crucible-common = { git = "https://github.com/oxidecomputer/crucible", rev = "e58ca3693cb9ce0438947beba10e97ee38a0966b" }
crucible-agent-client = { git = "https://github.com/oxidecomputer/crucible", rev = "eab46702b6a43ff558672462dea3eb5ff7b8a0e6"}
crucible-pantry-client = { git = "https://github.com/oxidecomputer/crucible", rev = "eab46702b6a43ff558672462dea3eb5ff7b8a0e6"}
crucible-smf = { git = "https://github.com/oxidecomputer/crucible", rev = "eab46702b6a43ff558672462dea3eb5ff7b8a0e6"}
crucible-common = { git = "https://github.com/oxidecomputer/crucible", rev = "eab46702b6a43ff558672462dea3eb5ff7b8a0e6"}
csv = "1.3.0"
curve25519-dalek = "4"
datatest-stable = "0.2.9"
Expand Down Expand Up @@ -503,8 +503,8 @@ proc-macro2 = "1.0"
progenitor = { git = "https://github.com/oxidecomputer/progenitor", branch = "main" }
progenitor-client = { git = "https://github.com/oxidecomputer/progenitor", branch = "main" }
bhyve_api = { git = "https://github.com/oxidecomputer/propolis", rev = "24a74d0c76b6a63961ecef76acb1516b6e66c5c9" }
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "24a74d0c76b6a63961ecef76acb1516b6e66c5c9" }
propolis-mock-server = { git = "https://github.com/oxidecomputer/propolis", rev = "24a74d0c76b6a63961ecef76acb1516b6e66c5c9" }
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "d45b4898137762074b7f7435b64fd2ccf41f4138" }
propolis-mock-server = { git = "https://github.com/oxidecomputer/propolis", rev = "d45b4898137762074b7f7435b64fd2ccf41f4138" }
proptest = "1.5.0"
qorb = { git = "https://github.com/oxidecomputer/qorb", branch = "master" }
quote = "1.0"
Expand Down Expand Up @@ -788,17 +788,19 @@ 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/crucible"]
#crucible-agent-client = { path = "../crucible/agent-client" }
#crucible-pantry-client = { path = "../crucible/pantry-client" }
#crucible-smf = { path = "../crucible/smf" }
# [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" }
# crucible-smf = { path = "../crucible/smf" }
#[patch.crates-io]
#diesel = { path = "../../diesel/diesel" }
#[patch."https://github.com/oxidecomputer/diesel-dtrace"]
#diesel-dtrace = { path = "../diesel-dtrace" }
# [patch."https://github.com/oxidecomputer/falcon"]
# libfalcon = { path = "../falcon/lib" }

#
# Local client generation during development.
Expand Down
3 changes: 3 additions & 0 deletions illumos-utils/src/opte/illumos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ pub enum Error {

#[error("Can't attach new ephemeral IP {0}, currently have {1}")]
ImplicitEphemeralIpDetach(IpAddr, IpAddr),

#[error("No matching NIC found for port {0} at slot {1}.")]
NoNicforPort(String, u32),
}

/// Delete all xde devices on the system.
Expand Down
3 changes: 3 additions & 0 deletions illumos-utils/src/opte/non_illumos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub enum Error {

#[error("Can't attach new ephemeral IP {0}, currently have {1}")]
ImplicitEphemeralIpDetach(IpAddr, IpAddr),

#[error("No matching NIC found for port {0} at slot {1}.")]
NoNicforPort(String, u32),
}

pub fn initialize_xde_driver(
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
88 changes: 88 additions & 0 deletions oximeter/oximeter/schema/instance-network-interface.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
format_version = 1

[target]
name = "instance_network_interface"
description = "A network interface attached to a virtual machine instance"
authz_scope = "project"
versions = [
{ version = 1, fields = [ "interface_id", "instance_id", "project_id", "silo_id" ] },
]

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

[fields.instance_id]
type = "uuid"
description = "The ID of the virtual machine instance this network interface is attached to"

[fields.project_id]
type = "uuid"
description = "The ID of the project containing the virtual machine instance this network interface is attached to"

[fields.silo_id]
type = "uuid"
description = "The ID of the silo containing the virtual machine instance this network interface is attached to"

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

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

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

[[metrics]]
name = "packets_received"
description = "Total number of packets received on the network interface"
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 network interface"
units = "count"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[[metrics]]
name = "errors_sent"
description = "Number of errors encountered when sending on the network interface"
units = "count"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]

[[metrics]]
name = "errors_received"
description = "Number of errors encountered when receiving on the network interface"
units = "count"
datum_type = "cumulative_u64"
versions = [
{ added_in = 1, fields = [] }
]
23 changes: 13 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,11 @@ 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.
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
Loading

0 comments on commit 5bf5f09

Please sign in to comment.