1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//! Publicly exposed metric macros are defined here.
//! Although `dipstick` does not have a macro-based API,
//! in some situations they can make instrumented code simpler.

// TODO add #[timer("name")] method annotation processors

/// A convenience macro to wrap a block or an expression with a start / stop timer.
/// Elapsed time is sent to the supplied statsd client after the computation has been performed.
/// Expression result (if any) is transparently returned.
#[macro_export]
macro_rules! time {
    ($timer: expr, $body: expr) => {{
        let start_time = $timer.start();
        let value = $body;
        $timer.stop(start_time);
        value
    }}
}

/////////////
// APP SCOPE

/// Define application-scoped metrics.
#[macro_export]
macro_rules! app_metrics {
    ($type_param: ty, $metric_id: ident = ($($app_metrics: expr),+ $(,)*)) => {
        lazy_static! { pub static ref $metric_id: AppMetrics<$type_param> = app_metrics(($($app_metrics),*)); }
    };
    ($type_param: ty, $metric_id: ident = [$($app_metrics: expr),+ $(,)*]) => {
        lazy_static! { pub static ref $metric_id: AppMetrics<$type_param> = app_metrics(&[$($app_metrics),*][..],); }
    };
    ($type_param: ty, $metric_id: ident = $app_metrics: expr) => {
        lazy_static! { pub static ref $metric_id: AppMetrics<$type_param> = $app_metrics.into(); }
    };
}

/// Define application-scoped markers.
#[macro_export]
macro_rules! app_marker {
    ($type_param: ty, $app_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(pub static ref $metric_id: AppMarker<$type_param> = $app_metrics.marker( $metric_name );)* }
    };
}

/// Define application-scoped counters.
#[macro_export]
macro_rules! app_counter {
    ($type_param: ty, $app_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(pub static ref $metric_id: AppCounter<$type_param> = $app_metrics.counter( $metric_name );)* }
    };
}

/// Define application-scoped gauges.
#[macro_export]
macro_rules! app_gauge {
    ($type_param: ty, $app_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(pub static ref $metric_id: AppGauge<$type_param> = $app_metrics.gauge( $metric_name );)* }
    };
}

/// Define application-scoped timers.
#[macro_export]
macro_rules! app_timer {
    ($type_param: ty, $app_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(pub static ref $metric_id: AppTimer<$type_param> = $app_metrics.timer( $metric_name );)* }
    };
}


/////////////
// MOD SCOPE

/// Define module-scoped metrics.
#[macro_export]
macro_rules! mod_metrics {
    ($type_param: ty, $metric_id: ident = ($($app_metrics: expr),+ $(,)*)) => {
        lazy_static! { static ref $metric_id: AppMetrics<$type_param> = app_metrics(($($app_metrics),*)); }
    };
    ($type_param: ty, $metric_id: ident = [$($app_metrics: expr),+ $(,)*]) => {
        lazy_static! { static ref $metric_id: AppMetrics<$type_param> = app_metrics(&[$($app_metrics),*][..],); }
    };
    ($type_param: ty, $metric_id: ident = $mod_metrics: expr) => {
        lazy_static! { static ref $metric_id: AppMetrics<$type_param> = $mod_metrics.into(); }
    };
}

/// Define module-scoped markers.
#[macro_export]
macro_rules! mod_marker {
    ($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(static ref $metric_id: AppMarker<$type_param> = $mod_metrics.marker( $metric_name );)* }
    };
}

/// Define module-scoped counters.
#[macro_export]
macro_rules! mod_counter {
    ($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(static ref $metric_id: AppCounter<$type_param> = $mod_metrics.counter( $metric_name );)* }
    };
}

/// Define module-scoped gauges.
#[macro_export]
macro_rules! mod_gauge {
    ($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(static ref $metric_id: AppGauge<$type_param> = $mod_metrics.gauge( $metric_name );)* }
    };
    ($type_param: ty, $mod_metrics: expr, $metric_id: ident: $metric_name: expr) => {
        lazy_static! { static ref $metric_id: AppGauge<$type_param> = $mod_metrics.gauge( $metric_name ); }
    }
}

/// Define module-scoped timers.
#[macro_export]
macro_rules! mod_timer {
    ($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
        lazy_static! { $(static ref $metric_id: AppTimer<$type_param> = $mod_metrics.timer( $metric_name );)* }
    };
}

#[cfg(test)]
mod test_app {
    use self_metrics::*;

    app_metrics!(Aggregate, TEST_METRICS = DIPSTICK_METRICS.with_prefix("test_prefix"));

    app_marker!(Aggregate, TEST_METRICS, {
        M1: "failed",
        M2: "success",
    });

    app_counter!(Aggregate, TEST_METRICS, {
        C1: "failed",
        C2: "success",
    });

    app_gauge!(Aggregate, TEST_METRICS, {
        G1: "failed",
        G2: "success",
    });

    app_timer!(Aggregate, TEST_METRICS, {
        T1: "failed",
        T2: "success",
    });


    #[test]
    fn call_macro_defined_metrics() {
        M1.mark();
        M2.mark();

        C1.count(1);
        C2.count(2);

        G1.value(1);
        G2.value(2);

        T1.interval_us(1);
        T2.interval_us(2);
    }
}

#[cfg(test)]
mod test_mod {
    use self_metrics::*;

    mod_metrics!(Aggregate, TEST_METRICS = DIPSTICK_METRICS.with_prefix("test_prefix"));

    mod_marker!(Aggregate, TEST_METRICS, {
        M1: "failed",
        M2: "success",
    });

    mod_counter!(Aggregate, TEST_METRICS, {
        C1: "failed",
        C2: "success",
    });

    mod_gauge!(Aggregate, TEST_METRICS, {
        G1: "failed",
        G2: "success",
    });

    mod_timer!(Aggregate, TEST_METRICS, {
        T1: "failed",
        T2: "success",
    });

    #[test]
    fn call_macro_defined_metrics() {
        M1.mark();
        M2.mark();

        C1.count(1);
        C2.count(2);

        G1.value(1);
        G2.value(2);

        T1.interval_us(1);
        T2.interval_us(2);
    }
}