use std::time::SystemTime;
use crate::{CacheMeta, CachePhase, HitStatus};
#[cfg(feature = "trace")]
mod real {
pub use cf_rustracing::tag::Tag;
use cf_rustracing_jaeger::span::SpanContextState;
pub type Span = cf_rustracing::span::Span<SpanContextState>;
pub type SpanHandle = cf_rustracing::span::SpanHandle<SpanContextState>;
}
#[cfg(feature = "trace")]
pub use real::*;
#[cfg(not(feature = "trace"))]
mod noop {
#[derive(Debug)]
pub struct Tag {
_priv: (),
}
impl Tag {
#[inline]
pub fn new<N, V>(_name: N, _value: V) -> Self {
Tag { _priv: () }
}
}
#[derive(Debug)]
pub struct Span {
_priv: (),
}
impl Span {
#[inline]
pub fn inactive() -> Self {
Span { _priv: () }
}
#[inline]
pub fn handle(&self) -> SpanHandle {
SpanHandle { _priv: () }
}
#[inline]
pub fn child<F>(&self, _name: &'static str, _f: F) -> Span
where
F: FnOnce(SpanOptionsPlaceholder) -> SpanOptionsPlaceholder,
{
Span::inactive()
}
#[inline]
pub fn set_tag<F: FnOnce() -> Tag>(&self, _f: F) {}
#[inline]
pub fn set_tags<F, I>(&self, _f: F)
where
F: FnOnce() -> I,
I: IntoIterator<Item = Tag>,
{
}
#[inline]
pub fn set_finish_time<F: Fn() -> std::time::SystemTime>(&self, _f: F) {}
}
#[doc(hidden)]
pub struct SpanOptionsPlaceholder {
_priv: (),
}
impl SpanOptionsPlaceholder {
#[inline]
pub fn start(self) -> Self {
self
}
}
#[derive(Debug)]
pub struct SpanHandle {
_priv: (),
}
}
#[cfg(not(feature = "trace"))]
pub use noop::*;
pub fn tag_span_with_meta(span: &mut Span, meta: &CacheMeta) {
fn ts2epoch(ts: SystemTime) -> f64 {
ts.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default() .as_secs_f64()
}
let internal = &meta.0.internal;
span.set_tags(|| {
[
Tag::new("created", ts2epoch(internal.created)),
Tag::new("fresh_until", ts2epoch(internal.fresh_until)),
Tag::new("updated", ts2epoch(internal.updated)),
Tag::new("stale_if_error_sec", internal.stale_if_error_sec as i64),
Tag::new(
"stale_while_revalidate_sec",
internal.stale_while_revalidate_sec as i64,
),
Tag::new("variance", internal.variance.is_some()),
]
});
}
#[derive(Debug)]
pub(crate) struct CacheTraceCTX {
pub cache_span: Span,
pub miss_span: Span,
pub hit_span: Span,
}
impl CacheTraceCTX {
pub fn new() -> Self {
CacheTraceCTX {
cache_span: Span::inactive(),
miss_span: Span::inactive(),
hit_span: Span::inactive(),
}
}
pub fn enable(&mut self, cache_span: Span) {
self.cache_span = cache_span;
}
pub fn get_cache_span(&self) -> SpanHandle {
self.cache_span.handle()
}
#[inline]
pub fn child(&self, name: &'static str) -> Span {
self.cache_span.child(name, |o| o.start())
}
pub fn start_miss_span(&mut self) {
self.miss_span = self.child("miss");
}
pub fn get_miss_span(&self) -> SpanHandle {
self.miss_span.handle()
}
pub fn finish_miss_span(&mut self) {
self.miss_span.set_finish_time(SystemTime::now);
}
pub fn start_hit_span(&mut self, phase: CachePhase, hit_status: HitStatus) {
self.hit_span = self.child("hit");
self.hit_span.set_tag(|| Tag::new("phase", phase.as_str()));
self.hit_span
.set_tag(|| Tag::new("status", hit_status.as_str()));
}
pub fn get_hit_span(&self) -> SpanHandle {
self.hit_span.handle()
}
pub fn finish_hit_span(&mut self) {
self.hit_span.set_finish_time(SystemTime::now);
}
pub fn log_meta_in_hit_span(&mut self, meta: &CacheMeta) {
tag_span_with_meta(&mut self.hit_span, meta);
}
pub fn log_meta_in_miss_span(&mut self, meta: &CacheMeta) {
tag_span_with_meta(&mut self.miss_span, meta);
}
}