Initial definition of the on-disk format

This commit is contained in:
Olivier 'reivilibre' 2021-11-23 23:07:57 +00:00
commit 696954c631
5 changed files with 105 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea

2
bare-metrics-core/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

View File

@ -0,0 +1,11 @@
[package]
name = "bare-metrics-core"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.130", features = ["derive"] }
serde_bare = "0.5.0"
hdrhistogram = "7.4.0"

View File

@ -0,0 +1 @@
pub mod structures;

View File

@ -0,0 +1,89 @@
use hdrhistogram::serialization::{
Deserializer as HistogramDeserialiser, Serializer as HistogramSerializer, V2Serializer,
};
use hdrhistogram::Histogram;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_bare::Uint;
use std::collections::HashMap;
pub fn get_supported_version() -> String {
format!("bare-metrics:{}", env!("CARGO_PKG_VERSION"))
}
/// Header for a metric log file.
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct LogHeader {
/// String describing the version of this metrics log file.
pub bare_metrics_version: String,
/// Unix timestamp (milliseconds) describing the start of the metrics.
pub start_time_ms: u64,
}
/// A single frame of metrics.
/// Has an end timestamp (the start timestamp should be inferred from the previous frame or the
/// header of the log file.
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct Frame {
/// Unix timestamp (milliseconds) describing the end of this frame of metrics.
pub end_time_ms: u64,
/// Absolute values of updated gauges.
pub gauge_updates: HashMap<MetricId, f64>,
/// Absolute values of updated counters.
/// TODO should this be counts only for this window?
pub counter_updates: HashMap<MetricId, Uint>,
/// Histograms only for this frame (this keeps them compact).
pub histograms: HashMap<MetricId, SerialisableHistogram>,
/// Descriptors of NEW metrics.
pub new_metrics: HashMap<MetricId, MetricDescriptor>,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
pub enum MetricKind {
Histogram,
Gauge,
Counter,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct MetricId(pub u16);
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MetricDescriptor {
pub kind: MetricKind,
pub unit: Option<String>,
pub description: String,
}
#[derive(Clone, Debug)]
pub struct SerialisableHistogram {
pub underlying: Histogram<u64>,
}
impl Serialize for SerialisableHistogram {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut buf = Vec::new();
V2Serializer::new()
.serialize(&self.underlying, &mut buf)
.expect("can't fail writing to buf");
serializer.serialize_bytes(&buf)
}
}
impl<'a> Deserialize<'a> for SerialisableHistogram {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
let bytes = Vec::<u8>::deserialize(deserializer)?;
let histogram = HistogramDeserialiser::new()
.deserialize(&mut &bytes[..])
.map_err(|e| D::Error::custom(format!("{:?}", e)))?;
Ok(SerialisableHistogram {
underlying: histogram,
})
}
}