-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
877 additions
and
2 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
oximeter/oximeter/schema/physical_data_link_bytes_received.ron
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
[ | ||
( | ||
name: "physical_data_link", | ||
description: "A physical link", | ||
versions: { | ||
1: ( | ||
) | ||
}, | ||
embed_fields: [], | ||
fields_by_version: { | ||
0: { | ||
"sled_model": string, | ||
"sled_revision": u32, | ||
"sled_serial": string, | ||
"link_name": string, | ||
}, | ||
} | ||
metrics: [ | ||
( | ||
name: "bytes_received", | ||
description: "count of bytes received", | ||
fields_by_version: {0: {}}, | ||
datum_type: cumulative_u64, | ||
units: bytes, | ||
), | ||
( | ||
name: "bytes_sent", | ||
description: "count of bytes sent", | ||
fields_by_version: {0: {}}, | ||
datum_type: cumulative_u64, | ||
units: bytes, | ||
) | ||
] | ||
), | ||
( | ||
name: "http_service", | ||
description: "An Oxide HTTP service", | ||
embed_fields: [], | ||
fields: { | ||
0: { | ||
"name": string, | ||
"id": uuid, | ||
}, | ||
}, | ||
metrics: [ | ||
( | ||
name: "request_latency_histogram", | ||
description: "Distribution of request latencies", | ||
fields: { | ||
0: { | ||
"route": string, | ||
"method": string, | ||
"status_code": u16, | ||
}, | ||
} | ||
datum_type: histogram_f64, | ||
units: seconds, | ||
) | ||
] | ||
) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
use oximeter::Datum; | ||
use oximeter::DatumType; | ||
use oximeter::FieldType; | ||
use oximeter::FieldValue; | ||
use std::collections::BTreeMap; | ||
|
||
#[derive(Clone, Debug)] | ||
struct TimeseriesSchema { | ||
target: TargetSchema, | ||
metric: MetricSchema, | ||
} | ||
|
||
impl TimeseriesSchema { | ||
fn new(target: TargetSchema, metric: MetricSchema) -> Result<Self, ()> { | ||
for tf in target.fields.keys() { | ||
if metric.fields.contains_key(tf) { | ||
return Err(()); | ||
} | ||
} | ||
Ok(Self { target, metric }) | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
struct FieldBuilder { | ||
name: String, | ||
fields: BTreeMap<String, FieldType>, | ||
} | ||
|
||
impl FieldBuilder { | ||
fn new(name: &str) -> Result<Self, ()> { | ||
// validate name | ||
Ok(Self { name: name.to_string(), fields: BTreeMap::new() }) | ||
} | ||
|
||
fn field(mut self, field_name: &str, field_type: FieldType) -> Self { | ||
let _ = self.fields.insert(field_name.to_string(), field_type); | ||
self | ||
} | ||
|
||
fn build_target(self) -> TargetSchema { | ||
TargetSchema { name: self.name, fields: self.fields } | ||
} | ||
|
||
fn build_metric(self, datum_type: DatumType) -> MetricSchema { | ||
MetricSchema { name: self.name, fields: self.fields, datum_type } | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
struct TargetSchema { | ||
name: String, | ||
fields: BTreeMap<String, FieldType>, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
struct MetricSchema { | ||
name: String, | ||
fields: BTreeMap<String, FieldType>, | ||
datum_type: DatumType, | ||
} | ||
|
||
#[derive(Clone, Debug, Default)] | ||
struct Target { | ||
name: String, | ||
fields: BTreeMap<String, FieldValue>, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
struct Metric { | ||
name: String, | ||
fields: BTreeMap<String, FieldValue>, | ||
datum_type: DatumType, | ||
datum: Option<Datum>, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
struct Timeseries { | ||
target: Target, | ||
metric: Metric, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
struct TimeseriesBuilder<'a> { | ||
schema: &'a TimeseriesSchema, | ||
target_fields: BTreeMap<String, FieldValue>, | ||
metric_fields: BTreeMap<String, FieldValue>, | ||
} | ||
|
||
impl<'a> TimeseriesBuilder<'a> { | ||
fn field<V: Into<FieldValue>>( | ||
mut self, | ||
field_name: &str, | ||
field_value: V, | ||
) -> Result<Self, ()> { | ||
// Find the field in either the target or metric fields. | ||
let (map, ty) = { | ||
if let Some(ty) = self.schema.target.fields.get(field_name) { | ||
(&mut self.target_fields, ty) | ||
} else if let Some(ty) = self.schema.metric.fields.get(field_name) { | ||
(&mut self.metric_fields, ty) | ||
} else { | ||
return Err(()); | ||
} | ||
}; | ||
let field_value = field_value.into(); | ||
if field_value.field_type() != *ty { | ||
return Err(()); | ||
} | ||
map.insert(field_name.to_string(), field_value); | ||
Ok(self) | ||
} | ||
|
||
fn build(self) -> Result<Timeseries, ()> { | ||
for tf in self.schema.target.fields.keys() { | ||
if !self.target_fields.contains_key(tf) { | ||
return Err(()); | ||
} | ||
} | ||
for tf in self.schema.metric.fields.keys() { | ||
if !self.metric_fields.contains_key(tf) { | ||
return Err(()); | ||
} | ||
} | ||
let target = Target { | ||
name: self.schema.target.name.clone(), | ||
fields: self.target_fields, | ||
}; | ||
let metric = Metric { | ||
name: self.schema.metric.name.clone(), | ||
fields: self.metric_fields, | ||
datum_type: self.schema.metric.datum_type, | ||
datum: None, | ||
}; | ||
Ok(Timeseries { target, metric }) | ||
} | ||
} | ||
|
||
impl TimeseriesSchema { | ||
pub fn builder(&self) -> TimeseriesBuilder { | ||
TimeseriesBuilder { | ||
schema: self, | ||
target_fields: BTreeMap::new(), | ||
metric_fields: BTreeMap::new(), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_foo() { | ||
FieldBuilder::new("oxide.rack.switch.transceiver") | ||
.field("part", FieldType::String) | ||
.field("vendor", FieldType::String) | ||
.field("serial", FieldType::String) | ||
.build_metric("temperature", DatumType::F64) | ||
.unwrap(); | ||
let target = FieldBuilder::new("target") | ||
.unwrap() | ||
.field("first", FieldType::U8) | ||
.field("second", FieldType::IpAddr) | ||
.build_target(); | ||
|
||
let metric = FieldBuilder::new("metric") | ||
.unwrap() | ||
.field("third", FieldType::U8) | ||
.field("fourth", FieldType::IpAddr) | ||
.build_metric(DatumType::I32); | ||
|
||
let timeseries_schema = TimeseriesSchema::new(target, metric).unwrap(); | ||
let mut timeseries = timeseries_schema | ||
.builder() | ||
.field::<u8>("first", 0) | ||
.unwrap() | ||
.field( | ||
"second", | ||
std::net::IpAddr::from(std::net::Ipv4Addr::LOCALHOST), | ||
) | ||
.unwrap() | ||
.field("third", 1u8) | ||
.unwrap() | ||
.field( | ||
"fourth", | ||
std::net::IpAddr::from(std::net::Ipv4Addr::LOCALHOST), | ||
) | ||
.unwrap() | ||
.build() | ||
.unwrap(); | ||
|
||
timeseries.metric.datum.replace(0i64.into()); | ||
|
||
println!("{:#?}", timeseries_schema); | ||
println!("{:#?}", timeseries); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.