2020-11-12 20:23:32 -08:00
|
|
|
use crate::cow::Cow;
|
2020-09-26 19:26:39 -07:00
|
|
|
|
|
|
|
/// An allocation-optimized string.
|
|
|
|
///
|
2020-10-27 05:58:18 -07:00
|
|
|
/// We specify `SharedString` to attempt to get the best of both worlds: flexibility to provide a
|
2020-09-26 19:26:39 -07:00
|
|
|
/// static or dynamic (owned) string, while retaining the performance benefits of being able to
|
|
|
|
/// take ownership of owned strings and borrows of completely static strings.
|
2020-11-15 13:42:43 -08:00
|
|
|
///
|
|
|
|
/// `SharedString` can be converted to from either `&'static str` or `String`, with a method,
|
|
|
|
/// `const_str`, from constructing `SharedString` from `&'static str` in a `const` fashion.
|
2020-10-27 05:58:18 -07:00
|
|
|
pub type SharedString = Cow<'static, str>;
|
2020-09-26 19:26:39 -07:00
|
|
|
|
2020-10-17 10:10:28 -07:00
|
|
|
/// Units for a given metric.
|
|
|
|
///
|
|
|
|
/// While metrics do not necessarily need to be tied to a particular unit to be recorded, some
|
|
|
|
/// downstream systems natively support defining units and so they can be specified during registration.
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum Unit {
|
|
|
|
/// Count.
|
|
|
|
Count,
|
|
|
|
/// Percentage.
|
|
|
|
Percent,
|
|
|
|
/// Seconds.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One second is equal to 1000 milliseconds.
|
2020-10-17 10:10:28 -07:00
|
|
|
Seconds,
|
|
|
|
/// Milliseconds.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One millisecond is equal to 1000 microseconds.
|
2020-10-17 10:10:28 -07:00
|
|
|
Milliseconds,
|
|
|
|
/// Microseconds.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One microsecond is equal to 1000 nanoseconds.
|
2020-10-17 10:10:28 -07:00
|
|
|
Microseconds,
|
|
|
|
/// Nanoseconds.
|
|
|
|
Nanoseconds,
|
2020-11-16 14:53:36 -08:00
|
|
|
/// Tebibytes.
|
|
|
|
///
|
|
|
|
/// One tebibyte is equal to 1024 gigibytes.
|
|
|
|
Tebibytes,
|
|
|
|
/// Gigibytes.
|
|
|
|
///
|
|
|
|
/// One gigibyte is equal to 1024 mebibytes.
|
|
|
|
Gigibytes,
|
|
|
|
/// Mebibytes.
|
|
|
|
///
|
|
|
|
/// One mebibyte is equal to 1024 kibibytes.
|
|
|
|
Mebibytes,
|
|
|
|
/// Kibibytes.
|
|
|
|
///
|
|
|
|
/// One kibibyte is equal to 1024 bytes.
|
|
|
|
Kibibytes,
|
2020-10-17 10:10:28 -07:00
|
|
|
/// Bytes.
|
|
|
|
Bytes,
|
|
|
|
/// Terabits per second.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One terabit is equal to 1000 gigabits.
|
2020-10-17 10:10:28 -07:00
|
|
|
TerabitsPerSecond,
|
|
|
|
/// Gigabits per second.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One gigabit is equal to 1000 megabits.
|
2020-10-17 10:10:28 -07:00
|
|
|
GigabitsPerSecond,
|
|
|
|
/// Megabits per second.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One megabit is equal to 1000 kilobits.
|
2020-10-17 10:10:28 -07:00
|
|
|
MegabitsPerSecond,
|
|
|
|
/// Kilobits per second.
|
2020-11-16 14:53:36 -08:00
|
|
|
///
|
|
|
|
/// One kilobit is equal to 1000 bits.
|
2020-10-17 10:10:28 -07:00
|
|
|
KilobitsPerSecond,
|
|
|
|
/// Bits per second.
|
|
|
|
BitsPerSecond,
|
|
|
|
/// Count per second.
|
|
|
|
CountPerSecond,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Unit {
|
|
|
|
/// Gets the string form of this `Unit`.
|
|
|
|
pub fn as_str(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
Unit::Count => "count",
|
|
|
|
Unit::Percent => "percent",
|
|
|
|
Unit::Seconds => "seconds",
|
|
|
|
Unit::Milliseconds => "milliseconds",
|
|
|
|
Unit::Microseconds => "microseconds",
|
|
|
|
Unit::Nanoseconds => "nanoseconds",
|
2020-11-16 14:53:36 -08:00
|
|
|
Unit::Tebibytes => "tebibytes",
|
|
|
|
Unit::Gigibytes => "gigibytes",
|
|
|
|
Unit::Mebibytes => "mebibytes",
|
|
|
|
Unit::Kibibytes => "kibibytes",
|
2020-10-17 10:10:28 -07:00
|
|
|
Unit::Bytes => "bytes",
|
|
|
|
Unit::TerabitsPerSecond => "terabits_per_second",
|
|
|
|
Unit::GigabitsPerSecond => "gigabits_per_second",
|
|
|
|
Unit::MegabitsPerSecond => "megabits_per_second",
|
|
|
|
Unit::KilobitsPerSecond => "kilobits_per_second",
|
|
|
|
Unit::BitsPerSecond => "bits_per_second",
|
|
|
|
Unit::CountPerSecond => "count_per_second",
|
|
|
|
}
|
|
|
|
}
|
2020-10-18 08:56:12 -07:00
|
|
|
|
|
|
|
/// Gets the canonical string label for the given unit.
|
|
|
|
///
|
2020-10-28 19:43:42 -07:00
|
|
|
/// For example, the canonical label for `Seconds` would be `s`, while for `Nanoseconds`,
|
|
|
|
/// it would be `ns`.
|
2020-10-25 13:59:44 -07:00
|
|
|
///
|
2020-10-28 20:12:06 -07:00
|
|
|
/// Not all units have a meaningful display label and so some may be empty.
|
2020-10-18 08:56:12 -07:00
|
|
|
pub fn as_canonical_label(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
Unit::Count => "",
|
|
|
|
Unit::Percent => "%",
|
|
|
|
Unit::Seconds => "s",
|
|
|
|
Unit::Milliseconds => "ms",
|
|
|
|
Unit::Microseconds => "us",
|
|
|
|
Unit::Nanoseconds => "ns",
|
2020-11-16 14:53:36 -08:00
|
|
|
Unit::Tebibytes => "TiB",
|
|
|
|
Unit::Gigibytes => "GiB",
|
|
|
|
Unit::Mebibytes => "MiB",
|
|
|
|
Unit::Kibibytes => "KiB",
|
2020-10-18 08:56:12 -07:00
|
|
|
Unit::Bytes => "B",
|
|
|
|
Unit::TerabitsPerSecond => "Tbps",
|
|
|
|
Unit::GigabitsPerSecond => "Gbps",
|
|
|
|
Unit::MegabitsPerSecond => "Mbps",
|
2020-11-16 14:53:36 -08:00
|
|
|
Unit::KilobitsPerSecond => "kbps",
|
2020-10-18 08:56:12 -07:00
|
|
|
Unit::BitsPerSecond => "bps",
|
|
|
|
Unit::CountPerSecond => "/s",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the string representation of a unit back into `Unit` if possible.
|
2020-10-25 13:59:44 -07:00
|
|
|
///
|
|
|
|
/// The value passed here should match the output of [`Unit::as_str`].
|
2020-10-18 08:56:12 -07:00
|
|
|
pub fn from_str(s: &str) -> Option<Unit> {
|
|
|
|
match s {
|
|
|
|
"count" => Some(Unit::Count),
|
|
|
|
"percent" => Some(Unit::Percent),
|
|
|
|
"seconds" => Some(Unit::Seconds),
|
|
|
|
"milliseconds" => Some(Unit::Milliseconds),
|
|
|
|
"microseconds" => Some(Unit::Microseconds),
|
|
|
|
"nanoseconds" => Some(Unit::Nanoseconds),
|
2020-11-16 14:53:36 -08:00
|
|
|
"tebibytes" => Some(Unit::Tebibytes),
|
|
|
|
"gigibytes" => Some(Unit::Gigibytes),
|
|
|
|
"mebibytes" => Some(Unit::Mebibytes),
|
|
|
|
"kibibytes" => Some(Unit::Kibibytes),
|
2020-10-18 08:56:12 -07:00
|
|
|
"bytes" => Some(Unit::Bytes),
|
|
|
|
"terabits_per_second" => Some(Unit::TerabitsPerSecond),
|
|
|
|
"gigabits_per_second" => Some(Unit::GigabitsPerSecond),
|
|
|
|
"megabits_per_second" => Some(Unit::MegabitsPerSecond),
|
|
|
|
"kilobits_per_second" => Some(Unit::KilobitsPerSecond),
|
|
|
|
"bits_per_second" => Some(Unit::BitsPerSecond),
|
|
|
|
"count_per_second" => Some(Unit::CountPerSecond),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Whether or not this unit relates to the measurement of time.
|
|
|
|
pub fn is_time_based(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
Unit::Seconds | Unit::Milliseconds | Unit::Microseconds | Unit::Nanoseconds => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Whether or not this unit relates to the measurement of data.
|
|
|
|
pub fn is_data_based(&self) -> bool {
|
|
|
|
match self {
|
2020-11-16 14:53:36 -08:00
|
|
|
Unit::Tebibytes
|
|
|
|
| Unit::Gigibytes
|
|
|
|
| Unit::Mebibytes
|
|
|
|
| Unit::Kibibytes
|
2020-10-25 13:59:44 -07:00
|
|
|
| Unit::Bytes
|
|
|
|
| Unit::TerabitsPerSecond
|
|
|
|
| Unit::GigabitsPerSecond
|
|
|
|
| Unit::MegabitsPerSecond
|
|
|
|
| Unit::KilobitsPerSecond
|
|
|
|
| Unit::BitsPerSecond => true,
|
2020-10-18 08:56:12 -07:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Whether or not this unit relates to the measurement of data rates.
|
|
|
|
pub fn is_data_rate_based(&self) -> bool {
|
|
|
|
match self {
|
2020-11-16 14:53:36 -08:00
|
|
|
Unit::TerabitsPerSecond
|
|
|
|
| Unit::GigabitsPerSecond
|
2020-10-25 13:59:44 -07:00
|
|
|
| Unit::MegabitsPerSecond
|
|
|
|
| Unit::KilobitsPerSecond
|
|
|
|
| Unit::BitsPerSecond => true,
|
2020-10-18 08:56:12 -07:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2020-10-17 10:10:28 -07:00
|
|
|
}
|
|
|
|
|
2020-09-26 19:26:39 -07:00
|
|
|
/// An object which can be converted into a `u64` representation.
|
|
|
|
///
|
|
|
|
/// This trait provides a mechanism for existing types, which have a natural representation
|
|
|
|
/// as an unsigned 64-bit integer, to be transparently passed in when recording a histogram.
|
|
|
|
pub trait IntoU64 {
|
|
|
|
/// Converts this object to its `u64` representation.
|
|
|
|
fn into_u64(self) -> u64;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoU64 for u64 {
|
|
|
|
fn into_u64(self) -> u64 {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-27 05:58:18 -07:00
|
|
|
impl IntoU64 for core::time::Duration {
|
2020-09-26 19:26:39 -07:00
|
|
|
fn into_u64(self) -> u64 {
|
|
|
|
self.as_nanos() as u64
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper method to allow monomorphization of values passed to the `histogram!` macro.
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn __into_u64<V: IntoU64>(value: V) -> u64 {
|
|
|
|
value.into_u64()
|
|
|
|
}
|
2020-11-16 14:53:36 -08:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::Unit;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_unit_conversions() {
|
|
|
|
let all_variants = vec![
|
|
|
|
Unit::Count,
|
|
|
|
Unit::Percent,
|
|
|
|
Unit::Seconds,
|
|
|
|
Unit::Milliseconds,
|
|
|
|
Unit::Microseconds,
|
|
|
|
Unit::Nanoseconds,
|
|
|
|
Unit::Tebibytes,
|
|
|
|
Unit::Gigibytes,
|
|
|
|
Unit::Mebibytes,
|
|
|
|
Unit::Kibibytes,
|
|
|
|
Unit::Bytes,
|
|
|
|
Unit::TerabitsPerSecond,
|
|
|
|
Unit::GigabitsPerSecond,
|
|
|
|
Unit::MegabitsPerSecond,
|
|
|
|
Unit::KilobitsPerSecond,
|
|
|
|
Unit::BitsPerSecond,
|
|
|
|
Unit::CountPerSecond,
|
|
|
|
];
|
|
|
|
|
|
|
|
for variant in all_variants {
|
|
|
|
let s = variant.as_str();
|
|
|
|
let parsed = Unit::from_str(s);
|
|
|
|
assert_eq!(Some(variant), parsed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|