1#![doc(hidden)]
13
14#[doc(hidden)]
15pub mod common_macro_prelude {
16 pub use std::sync::Arc;
17 pub use std::time::Duration;
18
19 pub use once_cell::sync::Lazy;
20 pub use perthread::PerThread;
21 pub use perthread::ThreadMap;
22 pub use stats_traits::dynamic_stat_types::DynamicStat;
23 pub use stats_traits::dynamic_stat_types::DynamicStatSync;
24 pub use stats_traits::field_stat_types::FieldStat;
25 pub use stats_traits::field_stat_types::FieldStatThreadLocal;
26 pub use stats_traits::stat_types::BoxCounter;
27 pub use stats_traits::stat_types::BoxHistogram;
28 pub use stats_traits::stat_types::BoxLocalCounter;
29 pub use stats_traits::stat_types::BoxLocalHistogram;
30 pub use stats_traits::stat_types::BoxLocalTimeseries;
31 pub use stats_traits::stat_types::BoxSingletonCounter;
32 pub use stats_traits::stat_types::BoxTimeseries;
33 pub use stats_traits::stats_manager::AggregationType::*;
34 pub use stats_traits::stats_manager::BoxStatsManager;
35 pub use stats_traits::stats_manager::BucketConfig;
36 pub use stats_traits::stats_manager::StatsManager;
37
38 pub use crate::create_singleton_counter;
39 pub use crate::create_stats_manager;
40 pub use crate::thread_local_aggregator::create_map;
41}
42
43#[macro_export]
193macro_rules! define_stats {
194 ($( $name:ident: $stat_type:tt($( $params:tt )*), )*) =>
197 (define_stats!(prefix = ""; $( $name: $stat_type($( $params )*), )*););
198
199 (prefix = $prefix:expr;
200 $( $name:ident: $stat_type:tt($( $params:tt )*), )*) => (
201 #[allow(non_snake_case, non_upper_case_globals, unused_imports)]
202 pub(crate) mod STATS {
203 use $crate::macros::common_macro_prelude::*;
204
205 static STATS_MAP: Lazy<Arc<ThreadMap<BoxStatsManager>>> = Lazy::new(|| create_map());
206 static STATS_MANAGER: Lazy<BoxStatsManager> = Lazy::new(|| create_stats_manager());
207
208 thread_local! {
209 static TL_STATS: PerThread<BoxStatsManager> =
210 STATS_MAP.register(create_stats_manager());
211 }
212
213 $( $crate::__define_stat!($prefix; $name: $stat_type($( $params )*)); )*
214 }
215 );
216}
217
218#[doc(hidden)]
219#[macro_export]
220macro_rules! __define_key_generator {
221 ($name:ident($prefix:expr, $key:expr; $( $placeholder:ident: $type:ty ),+)) => (
222 fn $name(&($( ref $placeholder, )+): &($( $type, )+)) -> String {
223 let key = format!($key, $( $placeholder ),+);
224 if $prefix.is_empty() {
225 key
226 } else {
227 [$prefix, &key].join(".")
228 }
229 }
230 );
231}
232
233#[doc(hidden)]
234#[macro_export]
235macro_rules! __define_stat {
236 ($prefix:expr; $name:ident: singleton_counter()) => (
237 $crate::__define_stat!($prefix; $name: singleton_counter(stringify!($name)));
238 );
239
240 ($prefix:expr; $name:ident: singleton_counter($key:expr)) => (
241 pub static $name: Lazy<BoxSingletonCounter> = Lazy::new(|| create_singleton_counter($crate::__create_stat_key!($prefix, $key).to_string()));
242 );
243
244 ($prefix:expr; $name:ident: counter()) => (
245 $crate::__define_stat!($prefix; $name: counter(stringify!($name)));
246 );
247
248 ($prefix:expr; $name:ident: counter($key:expr)) => (
249 thread_local! {
250 pub static $name: BoxLocalCounter = TL_STATS.with(|stats| {
251 stats.create_counter(&$crate::__create_stat_key!($prefix, $key))
252 });
253 }
254 );
255
256 ($prefix:expr; $name:ident: timeseries($( $aggregation_type:expr ),*)) => (
261 $crate::__define_stat!($prefix; $name: timeseries(stringify!($name); $( $aggregation_type ),*));
262 );
263 ($prefix:expr; $name:ident: timeseries($key:expr; $( $aggregation_type:expr ),*)) => (
264 $crate::__define_stat!($prefix; $name: timeseries($key; $( $aggregation_type ),* ; ));
265 );
266 ($prefix:expr; $name:ident: timeseries($key:expr; $( $aggregation_type:expr ),* ; $( $interval: expr ),*)) => (
267 thread_local! {
268 pub static $name: BoxLocalTimeseries = TL_STATS.with(|stats| {
269 stats.create_timeseries(
270 &$crate::__create_stat_key!($prefix, $key),
271 &[$( $aggregation_type ),*],
272 &[$( $interval ),*]
273 )
274 });
275 }
276 );
277
278 ($prefix:expr;
279 $name:ident: histogram($bucket_width:expr,
280 $min:expr,
281 $max:expr
282 $(, $aggregation_type:expr )*
283 $(; P $percentile:expr )*)) => (
284 $crate::__define_stat!($prefix;
285 $name: histogram(stringify!($name);
286 $bucket_width,
287 $min,
288 $max
289 $(, $aggregation_type )*
290 $(; P $percentile )*));
291 );
292
293 ($prefix:expr;
294 $name:ident: histogram($key:expr;
295 $bucket_width:expr,
296 $min:expr,
297 $max:expr
298 $(, $aggregation_type:expr )*
299 $(; P $percentile:expr )*)) => (
300 thread_local! {
301 pub static $name: BoxLocalHistogram = TL_STATS.with(|stats| {
302 stats.create_histogram(
303 &$crate::__create_stat_key!($prefix, $key),
304 &[$( $aggregation_type ),*],
305 BucketConfig {
306 width: $bucket_width,
307 min: $min,
308 max: $max,
309 },
310 &[$( $percentile ),*])
311 });
312 }
313 );
314
315 ($prefix:expr;
316 $name:ident: quantile_stat(
317 $( $aggregation_type:expr ),*
318 ; $( P $percentile:expr ),*
319 ; $( $interval:expr ),*
320 )) => (
321 $crate::__define_stat!($prefix;
322 $name: quantile_stat(stringify!($name)
323 ; $( $aggregation_type ),*
324 ; $( P $percentile ),*
325 ; $( $interval ),*));
326 );
327
328 ($prefix:expr;
329 $name:ident: quantile_stat($key:expr
330 ; $( $aggregation_type:expr ),*
331 ; $( P $percentile:expr ),*
332 ; $( $interval:expr ),*
333 )) => (
334 pub static $name: Lazy<BoxHistogram> = Lazy::new(|| {
335 STATS_MANAGER.create_quantile_stat(
336 &$crate::__create_stat_key!($prefix, $key),
337 &[$( $aggregation_type ),*],
338 &[$( $percentile as f32 ),*],
339 &[$( $interval ),*],
340 )
341 });
342
343 );
344
345 ($prefix:expr;
346 $name:ident: dynamic_singleton_counter($key:expr, ($( $placeholder:ident: $type:ty ),+))) => (
347 thread_local! {
348 pub static $name: DynamicStat<($( $type, )+), BoxSingletonCounter> = {
349 $crate::__define_key_generator!(
350 __key_generator($prefix, $key; $( $placeholder: $type ),+)
351 );
352
353 fn __stat_generator(key: &str) -> BoxSingletonCounter {
354 create_singleton_counter(key.to_string())
355 }
356
357 DynamicStat::new(__key_generator, __stat_generator)
358 }
359 }
360 );
361
362 ($prefix:expr;
363 $name:ident: dynamic_counter($key:expr, ($( $placeholder:ident: $type:ty ),+))) => (
364 thread_local! {
365 pub static $name: DynamicStat<($( $type, )+), BoxLocalCounter> = {
366 $crate::__define_key_generator!(
367 __key_generator($prefix, $key; $( $placeholder: $type ),+)
368 );
369
370 fn __stat_generator(key: &str) -> BoxLocalCounter {
371 TL_STATS.with(|stats| {
372 stats.create_counter(key)
373 })
374 }
375
376 DynamicStat::new(__key_generator, __stat_generator)
377 }
378 }
379 );
380
381 ($prefix:expr;
382 $name:ident: dynamic_timeseries($key:expr, ($( $placeholder:ident: $type:ty ),+);
383 $( $aggregation_type:expr ),*)) => (
384 $crate::__define_stat!(
385 $prefix;
386 $name: dynamic_timeseries(
387 $key,
388 ($( $placeholder: $type ),+);
389 $( $aggregation_type ),* ;
390 )
391 );
392 );
393
394 ($prefix:expr;
395 $name:ident: dynamic_timeseries($key:expr, ($( $placeholder:ident: $type:ty ),+);
396 $( $aggregation_type:expr ),* ; $( $interval:expr ),*)) => (
397 thread_local! {
398 pub static $name: DynamicStat<($( $type, )+), BoxLocalTimeseries> = {
399 $crate::__define_key_generator!(
400 __key_generator($prefix, $key; $( $placeholder: $type ),+)
401 );
402
403 fn __stat_generator(key: &str) -> BoxLocalTimeseries {
404 TL_STATS.with(|stats| {
405 stats.create_timeseries(key, &[$( $aggregation_type ),*], &[$( $interval ),*])
406 })
407 }
408
409 DynamicStat::new(__key_generator, __stat_generator)
410 };
411 }
412 );
413
414 ($prefix:expr;
415 $name:ident: dynamic_histogram($key:expr, ($( $placeholder:ident: $type:ty ),+);
416 $bucket_width:expr,
417 $min:expr,
418 $max:expr
419 $(, $aggregation_type:expr )*
420 $(; P $percentile:expr )*)) => (
421 thread_local! {
422 pub static $name: DynamicStat<($( $type, )+), BoxLocalHistogram> = {
423 $crate::__define_key_generator!(
424 __key_generator($prefix, $key; $( $placeholder: $type ),+)
425 );
426
427 fn __stat_generator(key: &str) -> BoxLocalHistogram {
428 TL_STATS.with(|stats| {
429 stats.create_histogram(key,
430 &[$( $aggregation_type ),*],
431 BucketConfig {
432 width: $bucket_width,
433 min: $min,
434 max: $max,
435 },
436 &[$( $percentile ),*])
437 })
438 }
439
440 DynamicStat::new(__key_generator, __stat_generator)
441 };
442 }
443 );
444
445 ($prefix:expr;
446 $name:ident: dynamic_quantile_stat($key:expr, ($( $placeholder:ident: $type:ty ),+) ;
447 $( $aggregation_type:expr ),* ;
448 $( P $percentile:expr ),* ;
449 $( $interval:expr ),*)) => (
450 pub static $name: Lazy<DynamicStatSync<($( $type, )+), BoxHistogram>> = Lazy::new(|| {
451 $crate::__define_key_generator!(
452 __key_generator($prefix, $key; $( $placeholder: $type ),+)
453 );
454
455 fn __stat_generator(key: &str) -> BoxHistogram {
456 STATS_MANAGER.create_quantile_stat(
457 key,
458 &[$( $aggregation_type ),*],
459 &[$( $percentile as f32 ),*],
460 &[$( $interval ),*],
461 )
462 }
463 DynamicStatSync::new(__key_generator, __stat_generator)
464 });
465 );
466}
467
468#[doc(hidden)]
469#[macro_export]
470macro_rules! __create_stat_key {
471 ($prefix:expr, $key:expr) => {{
472 use std::borrow::Cow;
473 if $prefix.is_empty() {
474 Cow::Borrowed($key)
475 } else {
476 Cow::Owned(format!("{}.{}", $prefix, $key))
477 }
478 }};
479}
480
481#[macro_export]
512macro_rules! define_stats_struct {
513 ($name:ident ($key:expr, $($pr_name:ident: $pr_type:ty),*) ,
515 $( $stat_name:ident: $stat_type:tt($( $params:tt )*) , )+) => {
516 define_stats_struct!($name ( $key, $($pr_name: $pr_type),*),
517 $($stat_name: $stat_type($($params)*)),* );
518 };
519
520 ($name:ident ($key:expr) ,
522 $( $stat_name:ident: $stat_type:tt($( $params:tt )*) ),*) => {
523 define_stats_struct!($name ( $key, ),
524 $($stat_name: $stat_type($($params)*)),* );
525 };
526 ($name:ident ($key:expr) ,
527 $( $stat_name:ident: $stat_type:tt($( $params:tt )*) , )+) => {
528 define_stats_struct!($name ( $key, ),
529 $($stat_name: $stat_type($($params)*)),* );
530 };
531
532 ($name:ident ($key:expr, $($pr_name:ident: $pr_type:ty),*) ,
534 $( $stat_name:ident: $stat_type:tt($( $params:tt )*) ),*) => {
535 #[allow(missing_docs)]
536 pub struct $name {
537 $(pub $stat_name: $crate::__struct_field_type!($stat_type), )*
538 }
539 impl $name {
540 #[allow(unused_imports, missing_docs, non_upper_case_globals)]
541 pub fn new($($pr_name: $pr_type),*) -> $name {
542 use $crate::macros::common_macro_prelude::*;
543
544
545 static STATS_MAP: Lazy<Arc<ThreadMap<BoxStatsManager>>> = Lazy::new(|| create_map());
546 static STATS_MANAGER: Lazy<BoxStatsManager> = Lazy::new(|| create_stats_manager());
547
548 thread_local! {
549 static TL_STATS: PerThread<BoxStatsManager> =
550 STATS_MAP.register(create_stats_manager());
551 }
552
553 $(
554 $crate::__struct_thread_local_init! { $stat_name, $stat_type, $($params)* }
555 )*
556
557 let __prefix = format!($key, $($pr_name),*);
558
559 $name {
560 $($stat_name: $crate::__struct_field_init!(__prefix, $stat_name, $stat_type, $($params)*)),*
561 }
562 }
563 }
564 impl std::fmt::Debug for $name {
565 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
566 write!(fmt, "<{}>", stringify!($name))
567 }
568 }
569 }
570}
571
572#[macro_export]
573#[doc(hidden)]
574macro_rules! __struct_field_type {
575 (singleton_counter) => {
576 $crate::macros::common_macro_prelude::BoxSingletonCounter
577 };
578 (counter) => {
579 $crate::macros::common_macro_prelude::BoxCounter
580 };
581 (timeseries) => {
582 $crate::macros::common_macro_prelude::BoxTimeseries
583 };
584 (histogram) => {
585 $crate::macros::common_macro_prelude::BoxHistogram
586 };
587 (quantile_stat) => {
588 $crate::macros::common_macro_prelude::BoxHistogram
589 };
590}
591
592#[macro_export]
593#[doc(hidden)]
594macro_rules! __struct_thread_local_init {
595 ($name:ident, singleton_counter, ) => {
596 $crate::__struct_thread_local_init!($name, singleton_counter, stringify!($name))
597 };
598 ($name:ident, singleton_counter, $key:expr) => {};
599
600 ($name:ident, counter, ) => {
601 $crate::__struct_thread_local_init! { $name, counter, stringify!($name)}
602 };
603 ($name:ident, counter, $key:expr) => {
604 $crate::__struct_thread_local_init! { $name, counter, $key ; }
605 };
606 ($name:ident, counter, $key:expr ; ) => {
607 thread_local! {
608 static $name: FieldStatThreadLocal<BoxLocalCounter> = {
609
610 fn __stat_generator(key: &str) -> BoxLocalCounter {
611 TL_STATS.with(|stats| {
612 stats.create_counter(key)
613 })
614 }
615
616 FieldStatThreadLocal::new(__stat_generator)
617 };
618 }
619 };
620
621 ($name:ident, timeseries, $( $aggregation_type:expr ),+) => {
622 $crate::__struct_thread_local_init! { $name, timeseries, stringify!($name) ; $($aggregation_type),*}
623 };
624 ($name:ident, timeseries, $key:expr ; $( $aggregation_type:expr ),* ) => {
625 $crate::__struct_thread_local_init! { $name, timeseries, $key ; $($aggregation_type),* ;}
626 };
627 ($name:ident, timeseries, $key:expr ; $( $aggregation_type:expr ),* ; $( $interval:expr ),* ) => {
628 thread_local! {
629
630 static $name: FieldStatThreadLocal<BoxLocalTimeseries> = {
631
632 fn __stat_generator(key: &str) -> BoxLocalTimeseries {
633 TL_STATS.with(|stats| {
634 stats.create_timeseries(key, &[$( $aggregation_type ),*], &[$( $interval ),*])
635 })
636 }
637
638 FieldStatThreadLocal::new(__stat_generator)
639 };
640 }
641 };
642
643 ($name:ident, histogram,
644 $bucket_width:expr, $min:expr, $max:expr $(, $aggregation_type:expr)*
645 $(; P $percentile:expr )*) => {
646 $crate::__struct_thread_local_init! { $name, histogram,
647 stringify!($name) ; $bucket_width, $min, $max $(, $aggregation_type)*
648 $(; P $percentile)* }
649 };
650 ($name:ident, histogram, $key:expr ;
651 $bucket_width:expr, $min:expr, $max:expr $(, $aggregation_type:expr)*
652 $(; P $percentile:expr )*) => {
653
654 thread_local! {
655 static $name: FieldStatThreadLocal<BoxLocalHistogram> = {
656
657 fn __stat_generator(key: &str) -> BoxLocalHistogram {
658 TL_STATS.with(|stats| {
659 stats.create_histogram(key,
660 &[$( $aggregation_type ),*],
661 BucketConfig {
662 width: $bucket_width,
663 min: $min,
664 max: $max,
665 },
666 &[$( $percentile ),*])
667 })
668 }
669
670 FieldStatThreadLocal::new(__stat_generator)
671 };
672 }
673 };
674 ($name:ident, quantile_stat,
675 $( $aggregation_type:expr ),*
676 ; $( P $percentile:expr ),*
677 ; $( $interval:expr ),*) => ();
678 ($name:ident, quantile_stat, $key:expr
679 ; $( $aggregation_type:expr ),*
680 ; $( P $percentile:expr ),*
681 ; $( $interval:expr ),*) => ();
682}
683
684#[macro_export]
685#[doc(hidden)]
686macro_rules! __struct_field_init {
687 ($prefix:expr, $name:ident, singleton_counter, ) => {
688 $crate::__struct_field_init!($prefix, $name, singleton_counter, stringify!($name))
689 };
690 ($prefix:expr, $name:ident, singleton_counter, $key:expr) => {{ create_singleton_counter(format!("{}.{}", $prefix, $key)) }};
691
692 ($prefix:expr, $name:ident, counter, ) => {
693 $crate::__struct_field_init!($prefix, $name, counter, stringify!($name) ;)
694 };
695 ($prefix:expr, $name:ident, counter, $key:expr) => {
696 $crate::__struct_field_init!($prefix, $name, counter, $key ;)
697 };
698 ($prefix:expr, $name:ident, counter, $key:expr ; $(params:tt)*) => {{ Box::new(FieldStat::new(&$name, format!("{}.{}", $prefix, $key))) }};
699
700
701 ($prefix:expr, $name:ident, timeseries, $( $aggregation_type:expr ),+) => {
702 $crate::__struct_field_init!($prefix, $name, timeseries, stringify!($name) ; $($aggregation_type),*)
703 };
704 ($prefix:expr, $name:ident, timeseries, $key:expr ; $( $aggregation_type:expr ),* ) => {
705 $crate::__struct_field_init!($prefix, $name, timeseries, $key ; $($aggregation_type),* ;)
706 };
707 ($prefix:expr, $name:ident, timeseries, $key:expr ; $( $aggregation_type:expr ),* ; $( $interval:expr ),* ) => {{
708 Box::new(FieldStat::new(&$name, format!("{}.{}", $prefix, $key)))
709 }};
710
711 ($prefix:expr, $name:ident, histogram,
712 $bucket_width:expr, $min:expr, $max:expr $(, $aggregation_type:expr)*
713 $(; P $percentile:expr )*) => {
714 $crate::__struct_field_init!($prefix, $name, histogram,
715 stringify!($name) ; $bucket_width, $min, $max $(, $aggregation_type)*
716 $(; P $percentile)*)
717 };
718 ($prefix:expr, $name:ident, histogram, $key:expr ;
719 $bucket_width:expr, $min:expr, $max:expr $(, $aggregation_type:expr)*
720 $(; P $percentile:expr )*) => {{ Box::new(FieldStat::new(&$name, format!("{}.{}", $prefix, $key))) }};
721 ($prefix:expr, $name:ident, quantile_stat,
722 $( $aggregation_type:expr ),*
723 ; $( P $percentile:expr ),*
724 ; $( $interval:expr ),*) => {
725 $crate::__struct_field_init!($prefix, $name, quantile_stat,
726 stringify!($name)
727 ; $( $aggregation_type ),*
728 ; $( P $percentile ),*
729 ; $( $interval ),*)
730 };
731 ($prefix:expr, $name:ident, quantile_stat,
732 $key:expr
733 ; $( $aggregation_type:expr ),*
734 ; $( P $percentile:expr ),*
735 ; $( $interval:expr ),*) => {{
736 STATS_MANAGER.create_quantile_stat(
737 &$crate::__create_stat_key!($prefix, $key),
738 &[$( $aggregation_type ),*],
739 &[$( $percentile as f32 ),*],
740 &[$( $interval ),*],
741 )
742
743 }};
744}