opentelemetry_sdk/metrics/internal/
mod.rsmod aggregate;
mod exponential_histogram;
mod histogram;
mod last_value;
mod sum;
use core::fmt;
use std::ops::{Add, AddAssign, Sub};
use std::sync::atomic::{AtomicI64, AtomicU64, Ordering};
use std::sync::Mutex;
pub(crate) use aggregate::{AggregateBuilder, ComputeAggregation, Measure};
pub(crate) use exponential_histogram::{EXPO_MAX_SCALE, EXPO_MIN_SCALE};
pub(crate) trait AtomicTracker<T>: Sync + Send + 'static {
fn add(&self, value: T);
fn get_value(&self) -> T;
fn get_and_reset_value(&self) -> T;
}
pub(crate) trait AtomicallyUpdate<T> {
type AtomicTracker: AtomicTracker<T>;
fn new_atomic_tracker() -> Self::AtomicTracker;
}
pub(crate) trait Number<T>:
Add<Output = T>
+ AddAssign
+ Sub<Output = T>
+ PartialOrd
+ fmt::Debug
+ Clone
+ Copy
+ PartialEq
+ Default
+ Send
+ Sync
+ 'static
+ AtomicallyUpdate<T>
{
fn min() -> Self;
fn max() -> Self;
fn into_float(self) -> f64;
}
impl Number<i64> for i64 {
fn min() -> Self {
i64::MIN
}
fn max() -> Self {
i64::MAX
}
fn into_float(self) -> f64 {
self as f64
}
}
impl Number<u64> for u64 {
fn min() -> Self {
u64::MIN
}
fn max() -> Self {
u64::MAX
}
fn into_float(self) -> f64 {
self as f64
}
}
impl Number<f64> for f64 {
fn min() -> Self {
f64::MIN
}
fn max() -> Self {
f64::MAX
}
fn into_float(self) -> f64 {
self
}
}
impl AtomicTracker<u64> for AtomicU64 {
fn add(&self, value: u64) {
self.fetch_add(value, Ordering::Relaxed);
}
fn get_value(&self) -> u64 {
self.load(Ordering::Relaxed)
}
fn get_and_reset_value(&self) -> u64 {
self.swap(0, Ordering::Relaxed)
}
}
impl AtomicallyUpdate<u64> for u64 {
type AtomicTracker = AtomicU64;
fn new_atomic_tracker() -> Self::AtomicTracker {
AtomicU64::new(0)
}
}
impl AtomicTracker<i64> for AtomicI64 {
fn add(&self, value: i64) {
self.fetch_add(value, Ordering::Relaxed);
}
fn get_value(&self) -> i64 {
self.load(Ordering::Relaxed)
}
fn get_and_reset_value(&self) -> i64 {
self.swap(0, Ordering::Relaxed)
}
}
impl AtomicallyUpdate<i64> for i64 {
type AtomicTracker = AtomicI64;
fn new_atomic_tracker() -> Self::AtomicTracker {
AtomicI64::new(0)
}
}
pub(crate) struct F64AtomicTracker {
inner: Mutex<f64>, }
impl F64AtomicTracker {
fn new() -> Self {
F64AtomicTracker {
inner: Mutex::new(0.0),
}
}
}
impl AtomicTracker<f64> for F64AtomicTracker {
fn add(&self, value: f64) {
let mut guard = self.inner.lock().expect("F64 mutex was poisoned");
*guard += value;
}
fn get_value(&self) -> f64 {
let guard = self.inner.lock().expect("F64 mutex was poisoned");
*guard
}
fn get_and_reset_value(&self) -> f64 {
let mut guard = self.inner.lock().expect("F64 mutex was poisoned");
let value = *guard;
*guard = 0.0;
value
}
}
impl AtomicallyUpdate<f64> for f64 {
type AtomicTracker = F64AtomicTracker;
fn new_atomic_tracker() -> Self::AtomicTracker {
F64AtomicTracker::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_add_and_get_u64_atomic_value() {
let atomic = u64::new_atomic_tracker();
atomic.add(15);
atomic.add(10);
let value = atomic.get_value();
assert_eq!(value, 25);
}
#[test]
fn can_reset_u64_atomic_value() {
let atomic = u64::new_atomic_tracker();
atomic.add(15);
let value = atomic.get_and_reset_value();
let value2 = atomic.get_value();
assert_eq!(value, 15, "Incorrect first value");
assert_eq!(value2, 0, "Incorrect second value");
}
#[test]
fn can_add_and_get_i64_atomic_value() {
let atomic = i64::new_atomic_tracker();
atomic.add(15);
atomic.add(-10);
let value = atomic.get_value();
assert_eq!(value, 5);
}
#[test]
fn can_reset_i64_atomic_value() {
let atomic = i64::new_atomic_tracker();
atomic.add(15);
let value = atomic.get_and_reset_value();
let value2 = atomic.get_value();
assert_eq!(value, 15, "Incorrect first value");
assert_eq!(value2, 0, "Incorrect second value");
}
#[test]
fn can_add_and_get_f64_atomic_value() {
let atomic = f64::new_atomic_tracker();
atomic.add(15.3);
atomic.add(10.4);
let value = atomic.get_value();
assert!(f64::abs(25.7 - value) < 0.0001);
}
#[test]
fn can_reset_f64_atomic_value() {
let atomic = f64::new_atomic_tracker();
atomic.add(15.5);
let value = atomic.get_and_reset_value();
let value2 = atomic.get_value();
assert!(f64::abs(15.5 - value) < 0.0001, "Incorrect first value");
assert!(f64::abs(0.0 - value2) < 0.0001, "Incorrect second value");
}
}