use crate::attributes::MetricId;
use crate::clock::TimeHandle;
use crate::label::Labels;
use crate::name::MetricName;
use crate::{Flush, MetricValue};
use std::fmt;
use std::sync::Arc;
pub use num::ToPrimitive;
use std::ops::Deref;
pub trait Input: Send + Sync + 'static + InputDyn {
type SCOPE: InputScope + Send + Sync + 'static;
fn metrics(&self) -> Self::SCOPE;
#[deprecated(since = "0.7.2", note = "Use metrics()")]
fn input(&self) -> Self::SCOPE {
self.metrics()
}
#[deprecated(since = "0.8.0", note = "Use metrics()")]
fn new_scope(&self) -> Self::SCOPE {
self.metrics()
}
}
pub trait InputDyn: Send + Sync + 'static {
fn input_dyn(&self) -> Arc<dyn InputScope + Send + Sync + 'static>;
}
impl<T: Input + Send + Sync + 'static> InputDyn for T {
fn input_dyn(&self) -> Arc<dyn InputScope + Send + Sync + 'static> {
Arc::new(self.metrics())
}
}
pub trait InputScope: Flush {
fn new_metric(&self, name: MetricName, kind: InputKind) -> InputMetric;
fn counter(&self, name: &str) -> Counter {
self.new_metric(name.into(), InputKind::Counter).into()
}
fn marker(&self, name: &str) -> Marker {
self.new_metric(name.into(), InputKind::Marker).into()
}
fn timer(&self, name: &str) -> Timer {
self.new_metric(name.into(), InputKind::Timer).into()
}
fn gauge(&self, name: &str) -> Gauge {
self.new_metric(name.into(), InputKind::Gauge).into()
}
fn level(&self, name: &str) -> Level {
self.new_metric(name.into(), InputKind::Level).into()
}
}
#[derive(Clone)]
pub struct InputMetric {
identifier: MetricId,
inner: Arc<dyn Fn(MetricValue, Labels) + Send + Sync>,
}
impl fmt::Debug for InputMetric {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "InputMetric")
}
}
impl InputMetric {
pub fn new<F: Fn(MetricValue, Labels) + Send + Sync + 'static>(
identifier: MetricId,
metric: F,
) -> InputMetric {
InputMetric {
identifier,
inner: Arc::new(metric),
}
}
#[inline]
pub fn write(&self, value: MetricValue, labels: Labels) {
(self.inner)(value, labels)
}
pub fn metric_id(&self) -> &MetricId {
&self.identifier
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum InputKind {
Marker,
Counter,
Level,
Gauge,
Timer,
}
impl From<&str> for InputKind {
fn from(s: &str) -> InputKind {
match s {
"Marker" => InputKind::Marker,
"Counter" => InputKind::Counter,
"Gauge" => InputKind::Gauge,
"Timer" => InputKind::Timer,
"Level" => InputKind::Level,
_ => panic!("No InputKind '{s}' defined"),
}
}
}
#[derive(Debug, Clone)]
pub struct Marker {
inner: InputMetric,
}
impl Marker {
pub fn mark(&self) {
self.inner.write(1, labels![])
}
}
#[derive(Debug, Clone)]
pub struct Counter {
inner: InputMetric,
}
impl Counter {
pub fn count(&self, count: usize) {
self.inner.write(count as isize, labels![])
}
}
#[derive(Debug, Clone)]
pub struct Level {
inner: InputMetric,
}
impl Level {
pub fn adjust<V: ToPrimitive>(&self, count: V) {
self.inner.write(count.to_isize().unwrap(), labels![])
}
}
#[derive(Debug, Clone)]
pub struct Gauge {
inner: InputMetric,
}
impl Gauge {
pub fn value<V: ToPrimitive>(&self, value: V) {
self.inner.write(value.to_isize().unwrap(), labels![])
}
}
#[derive(Debug, Clone)]
pub struct Timer {
inner: InputMetric,
}
impl Timer {
pub fn interval_us(&self, interval_us: u64) -> u64 {
self.inner.write(interval_us as isize, labels![]);
interval_us
}
pub fn start(&self) -> TimeHandle {
TimeHandle::now()
}
pub fn stop(&self, start_time: TimeHandle) {
let elapsed_us = start_time.elapsed_us();
self.interval_us(elapsed_us);
}
pub fn time<F: FnOnce() -> R, R>(&self, operations: F) -> R {
let start_time = self.start();
let value: R = operations();
self.stop(start_time);
value
}
}
impl From<InputMetric> for Gauge {
fn from(metric: InputMetric) -> Gauge {
Gauge { inner: metric }
}
}
impl From<InputMetric> for Timer {
fn from(metric: InputMetric) -> Timer {
Timer { inner: metric }
}
}
impl From<InputMetric> for Counter {
fn from(metric: InputMetric) -> Counter {
Counter { inner: metric }
}
}
impl From<InputMetric> for Marker {
fn from(metric: InputMetric) -> Marker {
Marker { inner: metric }
}
}
impl From<InputMetric> for Level {
fn from(metric: InputMetric) -> Level {
Level { inner: metric }
}
}
impl Deref for Counter {
type Target = InputMetric;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl Deref for Marker {
type Target = InputMetric;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl Deref for Timer {
type Target = InputMetric;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl Deref for Gauge {
type Target = InputMetric;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl Deref for Level {
type Target = InputMetric;
fn deref(&self) -> &Self::Target {
&self.inner
}
}