use crate::sdk::resource::Resource;
use crate::{
attributes,
metrics::{Descriptor, InstrumentKind, Number, Result},
};
use std::any::Any;
use std::fmt;
use std::sync::Arc;
use std::time::SystemTime;
mod aggregation;
pub mod stdout;
pub use aggregation::{
Buckets, Count, Histogram, LastValue, Max, Min, MinMaxSumCount, Points, Sum,
};
pub use stdout::stdout;
pub trait Processor: fmt::Debug {
fn aggregation_selector(&self) -> &dyn AggregatorSelector;
}
pub trait LockedProcessor {
fn process(&mut self, accumulation: Accumulation<'_>) -> Result<()>;
}
pub trait AggregatorSelector: fmt::Debug {
fn aggregator_for(&self, descriptor: &Descriptor) -> Option<Arc<dyn Aggregator + Send + Sync>>;
}
pub trait Checkpointer: LockedProcessor {
fn checkpoint_set(&mut self) -> &mut dyn CheckpointSet;
fn start_collection(&mut self);
fn finish_collection(&mut self) -> Result<()>;
}
pub trait Aggregator: fmt::Debug {
fn update(&self, number: &Number, descriptor: &Descriptor) -> Result<()>;
fn synchronized_move(
&self,
destination: &Arc<dyn Aggregator + Send + Sync>,
descriptor: &Descriptor,
) -> Result<()>;
fn merge(&self, other: &(dyn Aggregator + Send + Sync), descriptor: &Descriptor) -> Result<()>;
fn as_any(&self) -> &dyn Any;
}
pub trait Subtractor {
fn subtract(
&self,
operand: &(dyn Aggregator + Send + Sync),
result: &(dyn Aggregator + Send + Sync),
descriptor: &Descriptor,
) -> Result<()>;
}
pub trait Exporter: ExportKindFor {
fn export(&self, checkpoint_set: &mut dyn CheckpointSet) -> Result<()>;
}
pub trait ExportKindFor: fmt::Debug {
fn export_kind_for(&self, descriptor: &Descriptor) -> ExportKind;
}
pub trait CheckpointSet: fmt::Debug {
fn try_for_each(
&mut self,
export_selector: &dyn ExportKindFor,
f: &mut dyn FnMut(&Record<'_>) -> Result<()>,
) -> Result<()>;
}
pub fn accumulation<'a>(
descriptor: &'a Descriptor,
attributes: &'a attributes::AttributeSet,
resource: &'a Resource,
aggregator: &'a Arc<dyn Aggregator + Send + Sync>,
) -> Accumulation<'a> {
Accumulation::new(descriptor, attributes, resource, aggregator)
}
pub fn record<'a>(
descriptor: &'a Descriptor,
attributes: &'a attributes::AttributeSet,
resource: &'a Resource,
aggregator: Option<&'a Arc<dyn Aggregator + Send + Sync>>,
start: SystemTime,
end: SystemTime,
) -> Record<'a> {
Record {
metadata: Metadata::new(descriptor, attributes, resource),
aggregator,
start,
end,
}
}
impl Record<'_> {
pub fn aggregator(&self) -> Option<&Arc<dyn Aggregator + Send + Sync>> {
self.aggregator
}
}
#[derive(Debug)]
pub struct Metadata<'a> {
descriptor: &'a Descriptor,
attributes: &'a attributes::AttributeSet,
resource: &'a Resource,
}
impl<'a> Metadata<'a> {
pub fn new(
descriptor: &'a Descriptor,
attributes: &'a attributes::AttributeSet,
resource: &'a Resource,
) -> Self {
{
Metadata {
descriptor,
attributes,
resource,
}
}
}
pub fn descriptor(&self) -> &Descriptor {
self.descriptor
}
pub fn attributes(&self) -> &attributes::AttributeSet {
self.attributes
}
pub fn resource(&self) -> &Resource {
self.resource
}
}
#[derive(Debug)]
pub struct Record<'a> {
metadata: Metadata<'a>,
aggregator: Option<&'a Arc<dyn Aggregator + Send + Sync>>,
start: SystemTime,
end: SystemTime,
}
impl Record<'_> {
pub fn descriptor(&self) -> &Descriptor {
self.metadata.descriptor
}
pub fn attributes(&self) -> &attributes::AttributeSet {
self.metadata.attributes
}
pub fn resource(&self) -> &Resource {
self.metadata.resource
}
pub fn start_time(&self) -> &SystemTime {
&self.start
}
pub fn end_time(&self) -> &SystemTime {
&self.end
}
}
#[derive(Debug)]
pub struct Accumulation<'a> {
metadata: Metadata<'a>,
aggregator: &'a Arc<dyn Aggregator + Send + Sync>,
}
impl<'a> Accumulation<'a> {
pub fn new(
descriptor: &'a Descriptor,
attributes: &'a attributes::AttributeSet,
resource: &'a Resource,
aggregator: &'a Arc<dyn Aggregator + Send + Sync>,
) -> Self {
Accumulation {
metadata: Metadata::new(descriptor, attributes, resource),
aggregator,
}
}
pub fn descriptor(&self) -> &Descriptor {
self.metadata.descriptor
}
pub fn attributes(&self) -> &attributes::AttributeSet {
self.metadata.attributes
}
pub fn resource(&self) -> &Resource {
self.metadata.resource
}
pub fn aggregator(&self) -> &Arc<dyn Aggregator + Send + Sync> {
self.aggregator
}
}
#[derive(Clone, Debug)]
pub enum ExportKind {
Cumulative = 1,
Delta = 2,
}
#[derive(Debug, Clone)]
pub enum ExportKindSelector {
Cumulative,
Delta,
Stateless,
}
impl ExportKind {
pub fn includes(&self, has: &ExportKind) -> bool {
(self.clone() as u32) & (has.clone() as u32) != 0
}
pub fn memory_required(&self, kind: &InstrumentKind) -> bool {
match kind {
InstrumentKind::ValueRecorder
| InstrumentKind::ValueObserver
| InstrumentKind::Counter
| InstrumentKind::UpDownCounter => {
self.includes(&ExportKind::Cumulative)
}
InstrumentKind::SumObserver | InstrumentKind::UpDownSumObserver => {
self.includes(&ExportKind::Delta)
}
}
}
}
impl ExportKindFor for ExportKindSelector {
fn export_kind_for(&self, descriptor: &Descriptor) -> ExportKind {
match self {
ExportKindSelector::Cumulative => ExportKind::Cumulative,
ExportKindSelector::Delta => ExportKind::Delta,
ExportKindSelector::Stateless => {
if descriptor.instrument_kind().precomputed_sum() {
ExportKind::Cumulative
} else {
ExportKind::Delta
}
}
}
}
}