use std::{any::Any, borrow::Cow, sync::Arc, time::SystemTime};
mod boxed;
pub use boxed::BoxEntry;
mod map;
mod merged;
pub use merged::{Merged, MergedRef};
use crate::{Descriptors, Value};
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a metric entry",
note = "Entry structs created by the `#[metrics]` macro implement `InflectableEntry` rather than `Entry`, and need to be rooted via `RootEntry`"
)]
pub trait Entry {
fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>);
fn sample_group(&self) -> impl Iterator<Item = SampleGroupElement> {
[].into_iter()
}
fn merge<E>(self, other: E) -> Merged<Self, E>
where
Self: Sized,
{
Merged(self, other)
}
fn merge_by_ref<'a, E: 'a + Entry>(&'a self, other: &'a E) -> MergedRef<'a, Self, E> {
MergedRef(self, other)
}
#[cfg(not(metrique_require_explicit_impls))]
fn descriptors(&self) -> Descriptors<'_> {
Descriptors::Unavailable
}
#[cfg(metrique_require_explicit_impls)]
fn descriptors(&self) -> Descriptors<'_>;
fn boxed(self) -> BoxEntry
where
Self: Sized + Send + 'static,
{
BoxEntry::new(self)
}
}
pub type SampleGroupElement = (Cow<'static, str>, Cow<'static, str>);
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EmptyEntry;
impl Entry for EmptyEntry {
fn write<'a>(&'a self, _writer: &mut impl EntryWriter<'a>) {}
fn descriptors(&self) -> Descriptors<'_> {
Descriptors::available(std::iter::empty())
}
}
pub trait EntryConfig: Any + std::fmt::Debug {}
pub trait EntryWriter<'a> {
fn timestamp(&mut self, timestamp: SystemTime);
fn value(&mut self, name: impl Into<Cow<'a, str>>, value: &(impl Value + ?Sized));
fn config(&mut self, config: &'a dyn EntryConfig);
}
impl<'a, W: EntryWriter<'a>> EntryWriter<'a> for &mut W {
fn timestamp(&mut self, timestamp: SystemTime) {
(**self).timestamp(timestamp)
}
fn value(&mut self, name: impl Into<Cow<'a, str>>, value: &(impl Value + ?Sized)) {
(**self).value(name, value)
}
fn config(&mut self, config: &'a dyn EntryConfig) {
(**self).config(config)
}
}
impl<T: Entry + ?Sized> Entry for &T {
fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) {
(**self).write(writer)
}
fn sample_group(&self) -> impl Iterator<Item = SampleGroupElement> {
(**self).sample_group()
}
fn descriptors(&self) -> Descriptors<'_> {
(**self).descriptors()
}
}
impl<T: Entry> Entry for Option<T> {
fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) {
if let Some(entry) = self.as_ref() {
entry.write(writer)
}
}
fn sample_group(&self) -> impl Iterator<Item = SampleGroupElement> {
self.as_ref().into_iter().flat_map(|e| e.sample_group())
}
fn descriptors(&self) -> Descriptors<'_> {
match self.as_ref() {
Some(entry) => entry.descriptors(),
None => Descriptors::available(std::iter::empty()),
}
}
}
impl<T: Entry + ?Sized> Entry for Box<T> {
fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) {
(**self).write(writer)
}
fn sample_group(&self) -> impl Iterator<Item = SampleGroupElement> {
(**self).sample_group()
}
fn descriptors(&self) -> Descriptors<'_> {
(**self).descriptors()
}
}
impl<T: Entry + ?Sized> Entry for Arc<T> {
fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) {
(**self).write(writer)
}
fn sample_group(&self) -> impl Iterator<Item = SampleGroupElement> {
(**self).sample_group()
}
fn descriptors(&self) -> Descriptors<'_> {
(**self).descriptors()
}
}
impl<T: Entry + ToOwned + ?Sized> Entry for Cow<'_, T> {
fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) {
(**self).write(writer)
}
fn sample_group(&self) -> impl Iterator<Item = SampleGroupElement> {
(**self).sample_group()
}
fn descriptors(&self) -> Descriptors<'_> {
(**self).descriptors()
}
}