1use std::time::SystemTime;
25
26use crate::{CacheMeta, CachePhase, HitStatus};
27
28#[cfg(feature = "trace")]
32mod real {
33 pub use cf_rustracing::tag::Tag;
34
35 use cf_rustracing_jaeger::span::SpanContextState;
36
37 pub type Span = cf_rustracing::span::Span<SpanContextState>;
38 pub type SpanHandle = cf_rustracing::span::SpanHandle<SpanContextState>;
39}
40
41#[cfg(feature = "trace")]
42pub use real::*;
43
44#[cfg(not(feature = "trace"))]
48mod noop {
49 #[derive(Debug)]
51 pub struct Tag {
52 _priv: (),
53 }
54
55 impl Tag {
56 #[inline]
58 pub fn new<N, V>(_name: N, _value: V) -> Self {
59 Tag { _priv: () }
60 }
61 }
62
63 #[derive(Debug)]
65 pub struct Span {
66 _priv: (),
67 }
68
69 impl Span {
70 #[inline]
72 pub fn inactive() -> Self {
73 Span { _priv: () }
74 }
75
76 #[inline]
78 pub fn handle(&self) -> SpanHandle {
79 SpanHandle { _priv: () }
80 }
81
82 #[inline]
84 pub fn child<F>(&self, _name: &'static str, _f: F) -> Span
85 where
86 F: FnOnce(SpanOptionsPlaceholder) -> SpanOptionsPlaceholder,
87 {
88 Span::inactive()
89 }
90
91 #[inline]
93 pub fn set_tag<F: FnOnce() -> Tag>(&self, _f: F) {}
94
95 #[inline]
97 pub fn set_tags<F, I>(&self, _f: F)
98 where
99 F: FnOnce() -> I,
100 I: IntoIterator<Item = Tag>,
101 {
102 }
103
104 #[inline]
106 pub fn set_finish_time<F: Fn() -> std::time::SystemTime>(&self, _f: F) {}
107 }
108
109 #[doc(hidden)]
112 pub struct SpanOptionsPlaceholder {
113 _priv: (),
114 }
115
116 impl SpanOptionsPlaceholder {
117 #[inline]
119 pub fn start(self) -> Self {
120 self
121 }
122 }
123
124 #[derive(Debug)]
126 pub struct SpanHandle {
127 _priv: (),
128 }
129}
130
131#[cfg(not(feature = "trace"))]
132pub use noop::*;
133
134pub fn tag_span_with_meta(span: &mut Span, meta: &CacheMeta) {
140 fn ts2epoch(ts: SystemTime) -> f64 {
141 ts.duration_since(SystemTime::UNIX_EPOCH)
142 .unwrap_or_default() .as_secs_f64()
144 }
145 let internal = &meta.0.internal;
146 span.set_tags(|| {
147 [
148 Tag::new("created", ts2epoch(internal.created)),
149 Tag::new("fresh_until", ts2epoch(internal.fresh_until)),
150 Tag::new("updated", ts2epoch(internal.updated)),
151 Tag::new("stale_if_error_sec", internal.stale_if_error_sec as i64),
152 Tag::new(
153 "stale_while_revalidate_sec",
154 internal.stale_while_revalidate_sec as i64,
155 ),
156 Tag::new("variance", internal.variance.is_some()),
157 ]
158 });
159}
160
161#[derive(Debug)]
162pub(crate) struct CacheTraceCTX {
163 pub cache_span: Span,
165 pub miss_span: Span,
167 pub hit_span: Span,
168}
169
170impl CacheTraceCTX {
171 pub fn new() -> Self {
172 CacheTraceCTX {
173 cache_span: Span::inactive(),
174 miss_span: Span::inactive(),
175 hit_span: Span::inactive(),
176 }
177 }
178
179 pub fn enable(&mut self, cache_span: Span) {
180 self.cache_span = cache_span;
181 }
182
183 pub fn get_cache_span(&self) -> SpanHandle {
184 self.cache_span.handle()
185 }
186
187 #[inline]
188 pub fn child(&self, name: &'static str) -> Span {
189 self.cache_span.child(name, |o| o.start())
190 }
191
192 pub fn start_miss_span(&mut self) {
193 self.miss_span = self.child("miss");
194 }
195
196 pub fn get_miss_span(&self) -> SpanHandle {
197 self.miss_span.handle()
198 }
199
200 pub fn finish_miss_span(&mut self) {
201 self.miss_span.set_finish_time(SystemTime::now);
202 }
203
204 pub fn start_hit_span(&mut self, phase: CachePhase, hit_status: HitStatus) {
205 self.hit_span = self.child("hit");
206 self.hit_span.set_tag(|| Tag::new("phase", phase.as_str()));
207 self.hit_span
208 .set_tag(|| Tag::new("status", hit_status.as_str()));
209 }
210
211 pub fn get_hit_span(&self) -> SpanHandle {
212 self.hit_span.handle()
213 }
214
215 pub fn finish_hit_span(&mut self) {
216 self.hit_span.set_finish_time(SystemTime::now);
217 }
218
219 pub fn log_meta_in_hit_span(&mut self, meta: &CacheMeta) {
220 tag_span_with_meta(&mut self.hit_span, meta);
221 }
222
223 pub fn log_meta_in_miss_span(&mut self, meta: &CacheMeta) {
224 tag_span_with_meta(&mut self.miss_span, meta);
225 }
226}