mirror of https://github.com/fralalonde/dipstick
AppMetrics -> Metrics, fix send_metrics()
This commit is contained in:
parent
0143cea743
commit
2681c7b342
22
README.md
22
README.md
|
@ -38,7 +38,7 @@ dipstick = "0.6.5"
|
|||
Then add it to your code:
|
||||
|
||||
```rust,skt-fail,no_run
|
||||
let metrics = app_metrics(to_graphite("host.com:2003")?);
|
||||
let metrics = metrics(to_graphite("host.com:2003")?);
|
||||
let counter = metrics.counter("my_counter");
|
||||
counter.count(3);
|
||||
```
|
||||
|
@ -46,7 +46,7 @@ counter.count(3);
|
|||
Send metrics to multiple outputs:
|
||||
|
||||
```rust,skt-fail,no_run
|
||||
let _app_metrics = app_metrics((
|
||||
let _app_metrics = metrics((
|
||||
to_stdout(),
|
||||
to_statsd("localhost:8125")?.with_namespace(&["my", "app"])
|
||||
));
|
||||
|
@ -57,7 +57,7 @@ Aggregate metrics and schedule to be periodical publication in the background:
|
|||
```rust,skt-run
|
||||
use std::time::Duration;
|
||||
|
||||
let app_metrics = app_metrics(aggregate(all_stats, to_stdout()));
|
||||
let app_metrics = metrics(aggregate(all_stats, to_stdout()));
|
||||
app_metrics.flush_every(Duration::from_secs(3));
|
||||
```
|
||||
|
||||
|
@ -68,7 +68,7 @@ Published statistics can be selected with presets such as `all_stats` (see previ
|
|||
|
||||
For more control over published statistics, provide your own strategy:
|
||||
```rust,skt-run
|
||||
app_metrics(aggregate(
|
||||
metrics(aggregate(
|
||||
|_kind, name, score|
|
||||
match score {
|
||||
ScoreType::Count(count) =>
|
||||
|
@ -80,14 +80,14 @@ app_metrics(aggregate(
|
|||
|
||||
Apply statistical sampling to metrics:
|
||||
```rust,skt-fail
|
||||
let _app_metrics = app_metrics(to_statsd("server:8125")?.with_sampling_rate(0.01));
|
||||
let _app_metrics = metrics(to_statsd("server:8125")?.with_sampling_rate(0.01));
|
||||
```
|
||||
A fast random algorithm is used to pick samples.
|
||||
Outputs can use sample rate to expand or format published data.
|
||||
|
||||
Metrics can be recorded asynchronously:
|
||||
```rust,skt-run
|
||||
let _app_metrics = app_metrics(to_stdout().with_async_queue(64));
|
||||
let _app_metrics = metrics(to_stdout().with_async_queue(64));
|
||||
```
|
||||
The async queue uses a Rust channel and a standalone thread.
|
||||
The current behavior is to block when full.
|
||||
|
@ -98,12 +98,12 @@ For speed and easier maintenance, metrics are usually defined statically:
|
|||
#[macro_use] extern crate lazy_static;
|
||||
use dipstick::*;
|
||||
|
||||
app_metrics!("my_app" => {
|
||||
metrics!("my_app" => {
|
||||
@Counter COUNTER_A: "counter_a";
|
||||
});
|
||||
|
||||
fn main() {
|
||||
send_app_metrics(to_stdout());
|
||||
send_metrics(to_stdout());
|
||||
COUNTER_A.count(11);
|
||||
}
|
||||
```
|
||||
|
@ -113,14 +113,14 @@ Metric definition macros are just `lazy_static!` wrappers.
|
|||
Where necessary, metrics can be defined _ad-hoc_:
|
||||
```rust,skt-run
|
||||
let user_name = "john_day";
|
||||
let app_metrics = app_metrics(to_log()).with_cache(512);
|
||||
let app_metrics = metrics(to_log()).with_cache(512);
|
||||
app_metrics.gauge(format!("gauge_for_user_{}", user_name)).value(44);
|
||||
```
|
||||
Defining a cache is optional but will speed up re-definition of common ad-hoc metrics.
|
||||
|
||||
Timers can be used multiple ways:
|
||||
```rust,skt-run
|
||||
let app_metrics = app_metrics(to_stdout());
|
||||
let app_metrics = metrics(to_stdout());
|
||||
let timer = app_metrics.timer("my_timer");
|
||||
time!(timer, {/* slow code here */} );
|
||||
timer.time(|| {/* slow code here */} );
|
||||
|
@ -134,7 +134,7 @@ timer.interval_us(123_456);
|
|||
|
||||
Related metrics can share a namespace:
|
||||
```rust,skt-run
|
||||
let app_metrics = app_metrics(to_stdout());
|
||||
let app_metrics = metrics(to_stdout());
|
||||
let db_metrics = app_metrics.with_prefix("database");
|
||||
let _db_timer = db_metrics.timer("db_timer");
|
||||
let _db_counter = db_metrics.counter("db_counter");
|
||||
|
|
|
@ -9,7 +9,7 @@ use dipstick::*;
|
|||
fn main() {
|
||||
let to_aggregate = aggregate(all_stats, to_stdout());
|
||||
|
||||
let app_metrics = app_metrics(to_aggregate);
|
||||
let app_metrics = metrics(to_aggregate);
|
||||
|
||||
app_metrics.flush_every(Duration::from_secs(3));
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::time::Duration;
|
|||
use dipstick::*;
|
||||
|
||||
fn main() {
|
||||
let metrics = app_metrics(to_stdout().with_async_queue(0));
|
||||
let metrics = metrics(to_stdout().with_async_queue(0));
|
||||
|
||||
let counter = metrics.counter("counter_a");
|
||||
let timer = metrics.timer("timer_b");
|
||||
|
|
|
@ -9,7 +9,7 @@ use dipstick::*;
|
|||
|
||||
fn main() {
|
||||
// for this demo, print metric values to the console
|
||||
let app_metrics = app_metrics(to_stdout());
|
||||
let app_metrics = metrics(to_stdout());
|
||||
|
||||
// metrics can be predefined by type and name
|
||||
let counter = app_metrics.counter("counter_a");
|
||||
|
|
|
@ -37,7 +37,7 @@ fn main() {
|
|||
// send application metrics to aggregator
|
||||
let to_aggregate = aggregate(custom_statistics, to_stdout());
|
||||
|
||||
let app_metrics = app_metrics(to_aggregate);
|
||||
let app_metrics = metrics(to_aggregate);
|
||||
|
||||
// schedule aggregated metrics to be printed every 3 seconds
|
||||
app_metrics.flush_every(Duration::from_secs(3));
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::time::Duration;
|
|||
fn main() {
|
||||
// badlog::init(Some("info"));
|
||||
|
||||
let metrics = app_metrics(
|
||||
let metrics = metrics(
|
||||
to_graphite("localhost:2003")
|
||||
.expect("Connecting")
|
||||
.with_namespace(&["my", "app"][..]),
|
||||
|
|
|
@ -8,7 +8,7 @@ use dipstick::*;
|
|||
use std::time::Duration;
|
||||
|
||||
// undeclared root (un-prefixed) metrics
|
||||
app_metrics!( => {
|
||||
metrics!( => {
|
||||
// create counter "some_counter"
|
||||
pub @Counter ROOT_COUNTER: "root_counter";
|
||||
// create counter "root_counter"
|
||||
|
@ -18,7 +18,7 @@ app_metrics!( => {
|
|||
});
|
||||
|
||||
// public source
|
||||
app_metrics!(pub PUB_METRICS ="pub_lib_prefix" => {
|
||||
metrics!(pub PUB_METRICS ="pub_lib_prefix" => {
|
||||
// create counter "lib_prefix.some_counter"
|
||||
pub @Counter PUB_COUNTER: "some_counter";
|
||||
});
|
||||
|
@ -30,19 +30,19 @@ app_metrics!(pub PUB_METRICS ="pub_lib_prefix" => {
|
|||
//});
|
||||
|
||||
// declare mod source
|
||||
app_metrics!(LIB_METRICS ="mod_lib_prefix" => {
|
||||
metrics!(LIB_METRICS ="mod_lib_prefix" => {
|
||||
// create counter "mod_lib_prefix.some_counter"
|
||||
pub @Counter SOME_COUNTER: "some_counter";
|
||||
});
|
||||
|
||||
// reuse declared source
|
||||
app_metrics!(LIB_METRICS => {
|
||||
metrics!(LIB_METRICS => {
|
||||
// create counter "mod_lib_prefix.another_counter"
|
||||
@Counter ANOTHER_COUNTER: "another_counter";
|
||||
});
|
||||
|
||||
fn main() {
|
||||
send_app_metrics(to_stdout());
|
||||
send_metrics(to_stdout());
|
||||
|
||||
loop {
|
||||
ROOT_COUNTER.count(123);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//! A sample application sending ad-hoc counter values both to statsd _and_ to stdout.
|
||||
|
||||
|
||||
extern crate dipstick;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
use dipstick::*;
|
||||
use std::time::Duration;
|
||||
|
||||
#[ignore(deprecated)]
|
||||
app_metrics!((Statsd, String), DIFFERENT_TYPES = (
|
||||
// combine outputs of different types by using a tuple
|
||||
to_statsd("localhost:8125").expect("Connecting"),
|
||||
to_stdout(),
|
||||
));
|
||||
|
||||
#[ignore(deprecated)]
|
||||
app_metrics!(Vec<String>, SAME_TYPE = [
|
||||
// combine multiple outputs of the same type by using an array
|
||||
to_stdout().with_prefix("yeah"),
|
||||
to_stdout().with_prefix("ouch"),
|
||||
to_stdout().with_sampling_rate(0.5),
|
||||
]);
|
||||
|
||||
#[ignore(deprecated)]
|
||||
app_metrics!(Vec<String>, MUTANT_CHILD = SAME_TYPE.with_prefix("super").with_prefix("duper"));
|
||||
|
||||
fn main() {
|
||||
|
||||
loop {
|
||||
DIFFERENT_TYPES.counter("counter_a").count(123);
|
||||
SAME_TYPE.timer("timer_a").interval_us(2000000);
|
||||
MUTANT_CHILD.gauge("gauge_z").value(34534);
|
||||
std::thread::sleep(Duration::from_millis(40));
|
||||
}
|
||||
}
|
||||
|
|
@ -7,20 +7,20 @@ extern crate lazy_static;
|
|||
use dipstick::*;
|
||||
use std::time::Duration;
|
||||
|
||||
app_metrics!(<(Statsd, String)> DIFFERENT_TYPES = (
|
||||
metrics!(<(Statsd, String)> DIFFERENT_TYPES = (
|
||||
// combine outputs of different types by using a tuple
|
||||
to_statsd("localhost:8125").expect("Connecting"),
|
||||
to_stdout(),
|
||||
););
|
||||
|
||||
app_metrics!(<Vec<String>> SAME_TYPE = [
|
||||
metrics!(<Vec<String>> SAME_TYPE = [
|
||||
// combine multiple outputs of the same type by using an array
|
||||
to_stdout().with_prefix("yeah"),
|
||||
to_stdout().with_prefix("ouch"),
|
||||
to_stdout().with_sampling_rate(0.5),
|
||||
][..];);
|
||||
|
||||
app_metrics!(<Vec<String>> MUTANT_CHILD = SAME_TYPE.with_prefix("super").with_prefix("duper"););
|
||||
metrics!(<Vec<String>> MUTANT_CHILD = SAME_TYPE.with_prefix("super").with_prefix("duper"););
|
||||
|
||||
fn main() {
|
||||
loop {
|
||||
|
|
|
@ -7,14 +7,14 @@ use std::time::Duration;
|
|||
|
||||
fn main() {
|
||||
// note that this can also be done using the app_metrics! macro
|
||||
let different_type_metrics = app_metrics((
|
||||
let different_type_metrics = metrics((
|
||||
// combine metrics of different types in a tuple
|
||||
to_statsd("localhost:8125").expect("Connecting"),
|
||||
to_stdout(),
|
||||
));
|
||||
|
||||
// note that this can also be done using the app_metrics! macro
|
||||
let same_type_metrics = app_metrics(
|
||||
let same_type_metrics = metrics(
|
||||
&[
|
||||
// use slices to combine multiple metrics of the same type
|
||||
to_stdout().with_name("yeah"),
|
||||
|
|
|
@ -7,7 +7,7 @@ use dipstick::*;
|
|||
|
||||
fn main() {
|
||||
// print only 1 out of every 10000 metrics recorded
|
||||
let app_metrics: AppMetrics<String> = app_metrics(to_stdout().with_sampling_rate(0.0001));
|
||||
let app_metrics: Metrics<String> = metrics(to_stdout().with_sampling_rate(0.0001));
|
||||
|
||||
let marker = app_metrics.marker("marker_a");
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
//! Use statically defined app metrics & backend.
|
||||
//! This pattern is likely to emerge
|
||||
extern crate dipstick;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
/// The `metric` module should be shared across the crate and contain metrics from all modules.
|
||||
/// Conventions are easier to uphold and document when all metrics are defined in the same place.
|
||||
pub mod metric {
|
||||
|
||||
use dipstick::*;
|
||||
|
||||
// Unfortunately, Rust's `static`s assignments still force us to explicitly declare types.
|
||||
// This makes it uglier than it should be when working with generics...
|
||||
// and is even more work because IDE's such as IntelliJ can not yet see through macro blocks :(
|
||||
lazy_static! {
|
||||
pub static ref METRICS: AppMetrics<String> = app_metrics(to_stdout());
|
||||
pub static ref COUNTER_A: AppCounter<String> = METRICS.counter("counter_a");
|
||||
pub static ref TIMER_B: AppTimer<String> = METRICS.timer("timer_b");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// The resulting application code is lean and clean
|
||||
metric::COUNTER_A.count(11);
|
||||
metric::TIMER_B.interval_us(654654);
|
||||
}
|
|
@ -9,7 +9,7 @@ use dipstick::*;
|
|||
fn main() {
|
||||
let to_aggregate = aggregate(summary, to_stdout());
|
||||
|
||||
let app_metrics = app_metrics(to_aggregate);
|
||||
let app_metrics = metrics(to_aggregate);
|
||||
|
||||
app_metrics.flush_every(Duration::from_secs(3));
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
//! Maintain aggregated metrics for deferred reporting,
|
||||
//!
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use app_metrics::*;
|
||||
use context::*;
|
||||
use metrics::*;
|
||||
use namespace::*;
|
||||
use output::to_void;
|
||||
|
||||
|
@ -22,7 +22,7 @@ use std::sync::{Arc, RwLock};
|
|||
/// metrics.marker("my_event").mark();
|
||||
/// metrics.marker("my_event").mark();
|
||||
/// ```
|
||||
pub fn aggregate<E, M>(stat_fn: E, to_chain: LocalMetrics<M>) -> Aggregator
|
||||
pub fn aggregate<E, M>(stat_fn: E, to_chain: MetricContext<M>) -> Aggregator
|
||||
where
|
||||
E: Fn(Kind, &str, ScoreType) -> Option<(Kind, Vec<&str>, Value)> + Send + Sync + 'static,
|
||||
M: Clone + Send + Sync + Debug + 'static,
|
||||
|
@ -33,10 +33,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Aggregator> for AppMetrics<Aggregate> {
|
||||
fn from(agg: Aggregator) -> AppMetrics<Aggregate> {
|
||||
impl From<Aggregator> for Metrics<Aggregate> {
|
||||
fn from(agg: Aggregator) -> Metrics<Aggregate> {
|
||||
let agg_1 = agg.clone();
|
||||
AppMetrics::new(
|
||||
Metrics::new(
|
||||
Arc::new(move |kind, name, rate| agg.define_metric(kind, name, rate)),
|
||||
control_scope(move |cmd| match cmd {
|
||||
ScopeCmd::Write(metric, value) => {
|
||||
|
@ -49,9 +49,9 @@ impl From<Aggregator> for AppMetrics<Aggregate> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for AppMetrics<Aggregate> {
|
||||
fn from(prefix: &'static str) -> AppMetrics<Aggregate> {
|
||||
let app_metrics: AppMetrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
impl From<&'static str> for Metrics<Aggregate> {
|
||||
fn from(prefix: &'static str) -> Metrics<Aggregate> {
|
||||
let app_metrics: Metrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
app_metrics.with_prefix(prefix)
|
||||
}
|
||||
}
|
||||
|
@ -120,28 +120,28 @@ mod bench {
|
|||
|
||||
#[bench]
|
||||
fn aggregate_marker(b: &mut test::Bencher) {
|
||||
let sink: AppMetrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let sink: Metrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let metric = sink.define_metric(Marker, "event_a", 1.0);
|
||||
b.iter(|| test::black_box(sink.write(&metric, 1)));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn aggregate_counter(b: &mut test::Bencher) {
|
||||
let sink: AppMetrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let sink: Metrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let metric = sink.define_metric(Counter, "count_a", 1.0);
|
||||
b.iter(|| test::black_box(sink.write(&metric, 1)));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reset_marker(b: &mut test::Bencher) {
|
||||
let sink: AppMetrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let sink: Metrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let metric = sink.define_metric(Marker, "marker_a", 1.0);
|
||||
b.iter(|| test::black_box(metric.reset()));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reset_counter(b: &mut test::Bencher) {
|
||||
let sink: AppMetrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let sink: Metrics<Aggregate> = aggregate(summary, to_void()).into();
|
||||
let metric = sink.define_metric(Counter, "count_a", 1.0);
|
||||
b.iter(|| test::black_box(metric.reset()));
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
//! If queue size is exceeded, calling code reverts to blocking.
|
||||
//!
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use context::*;
|
||||
use self_metrics::*;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
app_metrics!{
|
||||
metrics!{
|
||||
<Aggregate> DIPSTICK_METRICS.with_prefix("async_queue") => {
|
||||
@Marker SEND_FAILED: "send_failed";
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ where
|
|||
fn with_async_queue(&self, queue_size: usize) -> Self;
|
||||
}
|
||||
|
||||
impl<M: Send + Sync + Clone + 'static> WithAsyncQueue for LocalMetrics<M> {
|
||||
impl<M: Send + Sync + Clone + 'static> WithAsyncQueue for MetricContext<M> {
|
||||
fn with_async_queue(&self, queue_size: usize) -> Self {
|
||||
self.mod_scope(|next| {
|
||||
// setup channel
|
||||
|
@ -49,7 +49,7 @@ impl<M: Send + Sync + Clone + 'static> WithAsyncQueue for LocalMetrics<M> {
|
|||
|
||||
Arc::new(move || {
|
||||
// open next scope, make it Arc to move across queue
|
||||
let next_scope: ControlScopeFn<M> = next();
|
||||
let next_scope: WriteFn<M> = next();
|
||||
let sender = sender.clone();
|
||||
|
||||
// forward any scope command through the channel
|
||||
|
@ -78,10 +78,10 @@ impl<M: Send + Sync + Clone + 'static> WithAsyncQueue for LocalMetrics<M> {
|
|||
|
||||
/// Enqueue collected metrics for dispatch on background thread.
|
||||
#[deprecated(since = "0.5.0", note = "Use `with_async_queue` instead.")]
|
||||
pub fn async<M, IC>(queue_size: usize, chain: IC) -> LocalMetrics<M>
|
||||
pub fn async<M, IC>(queue_size: usize, chain: IC) -> MetricContext<M>
|
||||
where
|
||||
M: Clone + Send + Sync + 'static,
|
||||
IC: Into<LocalMetrics<M>>,
|
||||
IC: Into<MetricContext<M>>,
|
||||
{
|
||||
let chain = chain.into();
|
||||
chain.with_async_queue(queue_size)
|
||||
|
@ -96,5 +96,5 @@ pub struct QueueCommand<M> {
|
|||
cmd: Option<(M, Value)>,
|
||||
/// The scope to write the metric to
|
||||
#[derivative(Debug = "ignore")]
|
||||
next_scope: ControlScopeFn<M>,
|
||||
next_scope: WriteFn<M>,
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Chain of command for unscoped metrics.
|
||||
|
||||
use core::*;
|
||||
use app_metrics::AppMetrics;
|
||||
use metrics::Metrics;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -11,7 +11,7 @@ use namespace::*;
|
|||
/// This is the building block for the metrics backend.
|
||||
#[derive(Derivative, Clone)]
|
||||
#[derivative(Debug)]
|
||||
pub struct LocalMetrics<M> {
|
||||
pub struct MetricContext<M> {
|
||||
#[derivative(Debug = "ignore")]
|
||||
define_metric_fn: DefineMetricFn<M>,
|
||||
|
||||
|
@ -19,7 +19,7 @@ pub struct LocalMetrics<M> {
|
|||
scope_metric_fn: OpenScopeFn<M>,
|
||||
}
|
||||
|
||||
impl<M> LocalMetrics<M> {
|
||||
impl<M> MetricContext<M> {
|
||||
/// Open a new metric scope.
|
||||
/// Scope metrics allow an application to emit per-operation statistics,
|
||||
/// For example, producing a per-request performance log.
|
||||
|
@ -33,35 +33,35 @@ impl<M> LocalMetrics<M> {
|
|||
/// let request_counter = scope_metrics.counter("scope_counter");
|
||||
/// ```
|
||||
///
|
||||
pub fn open_scope(&self) -> AppMetrics<M> {
|
||||
AppMetrics::new(self.define_metric_fn.clone(), (self.scope_metric_fn)())
|
||||
pub fn open_scope(&self) -> Metrics<M> {
|
||||
Metrics::new(self.define_metric_fn.clone(), (self.scope_metric_fn)())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Create a new metric chain with the provided metric definition and scope creation functions.
|
||||
pub fn metrics_context<MF, WF, M>(make_metric: MF, make_scope: WF) -> LocalMetrics<M>
|
||||
pub fn metrics_context<MF, WF, M>(make_metric: MF, make_scope: WF) -> MetricContext<M>
|
||||
where
|
||||
MF: Fn(Kind, &str, Rate) -> M + Send + Sync + 'static,
|
||||
WF: Fn() -> ControlScopeFn<M> + Send + Sync + 'static,
|
||||
WF: Fn() -> WriteFn<M> + Send + Sync + 'static,
|
||||
{
|
||||
LocalMetrics {
|
||||
MetricContext {
|
||||
define_metric_fn: Arc::new(make_metric),
|
||||
scope_metric_fn: Arc::new(make_scope),
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Send + Sync + Clone + 'static> LocalMetrics<M> {
|
||||
impl<M: Send + Sync + Clone + 'static> MetricContext<M> {
|
||||
|
||||
/// Intercept both metric definition and scope creation, possibly changing the metric type.
|
||||
pub fn mod_both<MF, N>(&self, mod_fn: MF) -> LocalMetrics<N>
|
||||
pub fn mod_both<MF, N>(&self, mod_fn: MF) -> MetricContext<N>
|
||||
where
|
||||
MF: Fn(DefineMetricFn<M>, OpenScopeFn<M>) -> (DefineMetricFn<N>, OpenScopeFn<N>),
|
||||
N: Clone + Send + Sync,
|
||||
{
|
||||
let (metric_fn, scope_fn) =
|
||||
mod_fn(self.define_metric_fn.clone(), self.scope_metric_fn.clone());
|
||||
LocalMetrics {
|
||||
MetricContext {
|
||||
define_metric_fn: metric_fn,
|
||||
scope_metric_fn: scope_fn,
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ impl<M: Send + Sync + Clone + 'static> LocalMetrics<M> {
|
|||
where
|
||||
MF: Fn(OpenScopeFn<M>) -> OpenScopeFn<M>,
|
||||
{
|
||||
LocalMetrics {
|
||||
MetricContext {
|
||||
define_metric_fn: self.define_metric_fn.clone(),
|
||||
scope_metric_fn: mod_fn(self.scope_metric_fn.clone()),
|
||||
}
|
||||
|
@ -80,16 +80,16 @@ impl<M: Send + Sync + Clone + 'static> LocalMetrics<M> {
|
|||
|
||||
}
|
||||
|
||||
impl<M> From<LocalMetrics<M>> for AppMetrics<M> {
|
||||
fn from(metrics: LocalMetrics<M>) -> AppMetrics<M> {
|
||||
impl<M> From<MetricContext<M>> for Metrics<M> {
|
||||
fn from(metrics: MetricContext<M>) -> Metrics<M> {
|
||||
metrics.open_scope()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Send + Sync + Clone + 'static> WithNamespace for LocalMetrics<M> {
|
||||
impl<M: Send + Sync + Clone + 'static> WithNamespace for MetricContext<M> {
|
||||
fn with_name<IN: Into<Namespace>>(&self, names: IN) -> Self {
|
||||
let ref ninto = names.into();
|
||||
LocalMetrics {
|
||||
MetricContext {
|
||||
define_metric_fn: add_namespace(ninto, self.define_metric_fn.clone()),
|
||||
scope_metric_fn: self.scope_metric_fn.clone(),
|
||||
}
|
|
@ -63,10 +63,10 @@ pub enum Kind {
|
|||
pub type DefineMetricFn<M> = Arc<Fn(Kind, &str, Rate) -> M + Send + Sync>;
|
||||
|
||||
/// A function trait that opens a new metric capture scope.
|
||||
pub type OpenScopeFn<M> = Arc<Fn() -> ControlScopeFn<M> + Send + Sync>;
|
||||
pub type OpenScopeFn<M> = Arc<Fn() -> WriteFn<M> + Send + Sync>;
|
||||
|
||||
/// A function trait that writes to or flushes a certain scope.
|
||||
pub type ControlScopeFn<M> = Arc<InnerControlScopeFn<M>>;
|
||||
pub type WriteFn<M> = Arc<InnerControlScopeFn<M>>;
|
||||
|
||||
/// Returns a callback function to send commands to the metric scope.
|
||||
/// Writes can be performed by passing Some((&Metric, Value))
|
||||
|
@ -98,7 +98,7 @@ pub enum ScopeCmd<'a, M: 'a> {
|
|||
}
|
||||
|
||||
/// Create a new metric scope based on the provided scope function.
|
||||
pub fn control_scope<M, F>(scope_fn: F) -> ControlScopeFn<M>
|
||||
pub fn control_scope<M, F>(scope_fn: F) -> WriteFn<M>
|
||||
where
|
||||
F: Fn(ScopeCmd<M>) + 'static,
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Decouple metric definition from configuration with trait objects.
|
||||
|
||||
use core::*;
|
||||
use app_metrics::*;
|
||||
use metrics::*;
|
||||
use namespace::*;
|
||||
use registry;
|
||||
|
||||
|
@ -13,24 +13,24 @@ use atomic_refcell::*;
|
|||
|
||||
/// Create a new dispatch point for metrics.
|
||||
/// All dispatch points are automatically entered in the dispatch registry.
|
||||
pub fn app_delegate() -> AppSend {
|
||||
let send = AppSend {
|
||||
inner: Arc::new(RwLock::new(InnerAppSend {
|
||||
pub fn delegate_metrics() -> MetricsSend {
|
||||
let send = MetricsSend {
|
||||
inner: Arc::new(RwLock::new(InnerMetricsSend {
|
||||
metrics: HashMap::new(),
|
||||
recv: registry::get_default_app_recv(),
|
||||
recv: registry::get_default_metrics_recv(),
|
||||
})),
|
||||
};
|
||||
registry::add_app_send(send.clone());
|
||||
registry::add_metrics_send(send.clone());
|
||||
send
|
||||
}
|
||||
|
||||
/// Dynamic counterpart of a `Dispatcher`.
|
||||
/// Adapter to AppMetrics<_> of unknown type.
|
||||
pub trait AppRecv {
|
||||
pub trait MetricsRecv {
|
||||
/// Register a new metric.
|
||||
/// Only one metric of a certain name will be defined.
|
||||
/// Observer must return a MetricHandle that uniquely identifies the metric.
|
||||
fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box<AppRecvMetric + Send + Sync>;
|
||||
fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box<RecvMetric + Send + Sync>;
|
||||
|
||||
/// Flush the receiver's scope.
|
||||
fn flush(&self);
|
||||
|
@ -38,7 +38,7 @@ pub trait AppRecv {
|
|||
|
||||
/// Dynamic counterpart of the `DispatcherMetric`.
|
||||
/// Adapter to a metric of unknown type.
|
||||
pub trait AppRecvMetric {
|
||||
pub trait RecvMetric {
|
||||
/// Write metric value to a scope.
|
||||
/// Observers only receive previously registered handles.
|
||||
fn write(&self, value: Value);
|
||||
|
@ -46,23 +46,23 @@ pub trait AppRecvMetric {
|
|||
|
||||
/// Shortcut name because `AppMetrics<Dispatch>`
|
||||
/// looks better than `AppMetrics<Arc<DispatcherMetric>>`.
|
||||
pub type Delegate = Arc<AppSendMetric>;
|
||||
pub type Delegate = Arc<SendMetric>;
|
||||
|
||||
/// A dynamically dispatched metric.
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct AppSendMetric {
|
||||
pub struct SendMetric {
|
||||
kind: Kind,
|
||||
name: String,
|
||||
rate: Rate,
|
||||
#[derivative(Debug = "ignore")]
|
||||
recv_metric: AtomicRefCell<Box<AppRecvMetric + Send + Sync>>,
|
||||
recv_metric: AtomicRefCell<Box<RecvMetric + Send + Sync>>,
|
||||
#[derivative(Debug = "ignore")]
|
||||
send: AppSend,
|
||||
send: MetricsSend,
|
||||
}
|
||||
|
||||
/// Dispatcher weak ref does not prevent dropping but still needs to be cleaned out.
|
||||
impl Drop for AppSendMetric {
|
||||
impl Drop for SendMetric {
|
||||
fn drop(&mut self) {
|
||||
self.send.drop_metric(self)
|
||||
}
|
||||
|
@ -73,36 +73,44 @@ impl Drop for AppSendMetric {
|
|||
/// Allows defining metrics before a concrete type has been selected.
|
||||
/// Allows replacing metrics backend on the fly at runtime.
|
||||
#[derive(Clone)]
|
||||
pub struct AppSend {
|
||||
inner: Arc<RwLock<InnerAppSend>>,
|
||||
pub struct MetricsSend {
|
||||
inner: Arc<RwLock<InnerMetricsSend>>,
|
||||
}
|
||||
|
||||
struct InnerAppSend {
|
||||
metrics: HashMap<String, Weak<AppSendMetric>>,
|
||||
recv: Arc<AppRecv + Send + Sync>,
|
||||
struct InnerMetricsSend {
|
||||
metrics: HashMap<String, Weak<SendMetric>>,
|
||||
recv: Arc<MetricsRecv + Send + Sync>,
|
||||
}
|
||||
|
||||
impl From<&'static str> for AppMetrics<Delegate> {
|
||||
fn from(prefix: &'static str) -> AppMetrics<Delegate> {
|
||||
let app_metrics: AppMetrics<Delegate> = app_delegate().into();
|
||||
/// Allow turning a 'static str into a Delegate, where str is the prefix.
|
||||
impl From<&'static str> for Metrics<Delegate> {
|
||||
fn from(prefix: &'static str) -> Metrics<Delegate> {
|
||||
let app_metrics: Metrics<Delegate> = delegate_metrics().into();
|
||||
app_metrics.with_prefix(prefix)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AppSend> for AppMetrics<Delegate> {
|
||||
fn from(send: AppSend) -> AppMetrics<Delegate> {
|
||||
/// Allow turning a 'static str into a Delegate, where str is the prefix.
|
||||
impl From<()> for Metrics<Delegate> {
|
||||
fn from(_: ()) -> Metrics<Delegate> {
|
||||
let app_metrics: Metrics<Delegate> = delegate_metrics().into();
|
||||
app_metrics
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<MetricsSend> for Metrics<Delegate> {
|
||||
fn from(send: MetricsSend) -> Metrics<Delegate> {
|
||||
let send_cmd = send.clone();
|
||||
AppMetrics::new(
|
||||
Metrics::new(
|
||||
// define metric
|
||||
Arc::new(move |kind, name, rate| send.define_metric(kind, name, rate)),
|
||||
|
||||
// write / flush metric
|
||||
control_scope(move |cmd| match cmd {
|
||||
ScopeCmd::Write(metric, value) => {
|
||||
let dispatch: &Arc<AppSendMetric> = metric;
|
||||
let dispatch: &Arc<SendMetric> = metric;
|
||||
dispatch.recv_metric.borrow().write(value);
|
||||
// let recv_metric: AtomicRef<Box<AppRecvMetric + Send + Sync>> = dispatch.recv_metric.borrow();
|
||||
// recv_metric.write(value)
|
||||
}
|
||||
ScopeCmd::Flush => send_cmd.inner.write().expect("Locking Delegate").recv.flush(),
|
||||
}),
|
||||
|
@ -110,25 +118,19 @@ impl From<AppSend> for AppMetrics<Delegate> {
|
|||
}
|
||||
}
|
||||
|
||||
impl AppSend {
|
||||
impl MetricsSend {
|
||||
/// Install a new metric receiver, replacing the previous one.
|
||||
pub fn set_receiver<IS: Into<AppMetrics<T>>, T: Send + Sync + Clone + 'static>(
|
||||
&self,
|
||||
receiver: IS,
|
||||
) {
|
||||
let receiver: Arc<AppRecv + Send + Sync> = Arc::new(receiver.into());
|
||||
let inner: &mut InnerAppSend =
|
||||
&mut *self.inner.write().expect("Lock Metrics Send");
|
||||
pub fn set_receiver<R: MetricsRecv + Send + Sync + 'static>(&self, recv: Arc<R>) {
|
||||
let inner = &mut self.inner.write().expect("Lock Metrics Send");
|
||||
|
||||
for mut metric in inner.metrics.values() {
|
||||
if let Some(metric) = metric.upgrade() {
|
||||
let receiver_metric =
|
||||
receiver.define_metric(metric.kind, metric.name.as_ref(), metric.rate);
|
||||
*metric.recv_metric.borrow_mut() = receiver_metric;
|
||||
let recv_metric = recv.define_metric(metric.kind, metric.name.as_ref(), metric.rate);
|
||||
*metric.recv_metric.borrow_mut() = recv_metric;
|
||||
}
|
||||
}
|
||||
// TODO return old receiver (swap, how?)
|
||||
inner.recv = receiver;
|
||||
inner.recv = recv.clone()
|
||||
}
|
||||
|
||||
fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Delegate {
|
||||
|
@ -137,7 +139,7 @@ impl AppSend {
|
|||
.and_then(|metric_ref| Weak::upgrade(metric_ref))
|
||||
.unwrap_or_else(|| {
|
||||
let recv_metric = inner.recv.define_metric(kind, name, rate);
|
||||
let new_metric = Arc::new(AppSendMetric {
|
||||
let new_metric = Arc::new(SendMetric {
|
||||
kind,
|
||||
name: name.to_string(),
|
||||
rate,
|
||||
|
@ -152,7 +154,7 @@ impl AppSend {
|
|||
})
|
||||
}
|
||||
|
||||
fn drop_metric(&self, metric: &AppSendMetric) {
|
||||
fn drop_metric(&self, metric: &SendMetric) {
|
||||
let mut inner = self.inner.write().expect("Lock Metrics Send");
|
||||
if inner.metrics.remove(&metric.name).is_none() {
|
||||
panic!("Could not remove DelegatingMetric weak ref from delegation point")
|
||||
|
@ -171,8 +173,8 @@ mod bench {
|
|||
|
||||
#[bench]
|
||||
fn dispatch_marker_to_aggregate(b: &mut test::Bencher) {
|
||||
let dispatch = app_delegate();
|
||||
let sink: AppMetrics<Delegate> = dispatch.clone().into();
|
||||
let dispatch = delegate_metrics();
|
||||
let sink: Metrics<Delegate> = dispatch.clone().into();
|
||||
dispatch.set_receiver(aggregate(summary, to_void()));
|
||||
let metric = sink.marker("event_a");
|
||||
b.iter(|| test::black_box(metric.mark()));
|
||||
|
@ -180,8 +182,8 @@ mod bench {
|
|||
|
||||
#[bench]
|
||||
fn dispatch_marker_to_void(b: &mut test::Bencher) {
|
||||
let dispatch = app_delegate();
|
||||
let sink: AppMetrics<Delegate> = dispatch.into();
|
||||
let dispatch = delegate_metrics();
|
||||
let sink: Metrics<Delegate> = dispatch.into();
|
||||
let metric = sink.marker("event_a");
|
||||
b.iter(|| test::black_box(metric.mark()));
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//! Send metrics to a graphite server.
|
||||
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use context::*;
|
||||
use error;
|
||||
use self_metrics::*;
|
||||
|
||||
|
@ -14,7 +14,7 @@ use std::fmt::Debug;
|
|||
|
||||
use socket::RetrySocket;
|
||||
|
||||
app_metrics!{
|
||||
metrics!{
|
||||
<Aggregate> DIPSTICK_METRICS.with_prefix("graphite") => {
|
||||
@Marker SEND_ERR: "send_failed";
|
||||
@Marker TRESHOLD_EXCEEDED: "bufsize_exceeded";
|
||||
|
@ -38,7 +38,7 @@ app_metrics!{
|
|||
//}
|
||||
|
||||
/// Send metrics to a graphite server at the address and port provided.
|
||||
pub fn to_graphite<ADDR>(address: ADDR) -> error::Result<LocalMetrics<Graphite>>
|
||||
pub fn to_graphite<ADDR>(address: ADDR) -> error::Result<MetricContext<Graphite>>
|
||||
where
|
||||
ADDR: ToSocketAddrs + Debug + Clone,
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ where
|
|||
}
|
||||
|
||||
/// Send metrics to a graphite server at the address and port provided.
|
||||
pub fn to_buffered_graphite<ADDR>(address: ADDR) -> error::Result<LocalMetrics<Graphite>>
|
||||
pub fn to_buffered_graphite<ADDR>(address: ADDR) -> error::Result<MetricContext<Graphite>>
|
||||
where
|
||||
ADDR: ToSocketAddrs + Debug + Clone,
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ fn graphite_metric(kind: Kind, name: &str, rate: Rate) -> Graphite {
|
|||
Graphite { prefix, scale }
|
||||
}
|
||||
|
||||
fn graphite_scope(socket: &Arc<RwLock<RetrySocket>>, buffered: bool) -> ControlScopeFn<Graphite> {
|
||||
fn graphite_scope(socket: &Arc<RwLock<RetrySocket>>, buffered: bool) -> WriteFn<Graphite> {
|
||||
let buf = ScopeBuffer {
|
||||
buffer: Arc::new(RwLock::new(String::new())),
|
||||
socket: socket.clone(),
|
||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -30,20 +30,20 @@ pub mod macros;
|
|||
pub mod core;
|
||||
pub use core::*;
|
||||
|
||||
pub mod local_metrics;
|
||||
pub use local_metrics::*;
|
||||
pub mod context;
|
||||
pub use context::*;
|
||||
|
||||
//pub mod local_delegate;
|
||||
//pub use local_delegate::*;
|
||||
|
||||
pub mod app_delegate;
|
||||
pub use app_delegate::*;
|
||||
pub mod delegate;
|
||||
pub use delegate::*;
|
||||
|
||||
mod output;
|
||||
pub use output::*;
|
||||
|
||||
mod app_metrics;
|
||||
pub use app_metrics::*;
|
||||
mod metrics;
|
||||
pub use metrics::*;
|
||||
|
||||
mod sample;
|
||||
pub use sample::*;
|
||||
|
|
136
src/macros.rs
136
src/macros.rs
|
@ -17,27 +17,27 @@ macro_rules! time {
|
|||
}};
|
||||
}
|
||||
|
||||
/// AppMetrics can be used from anywhere (public), does not need to declare metrics in this block.
|
||||
/// Metrics can be used from anywhere (public), does not need to declare metrics in this block.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! app_metrics {
|
||||
macro_rules! metrics {
|
||||
// TYPED
|
||||
// typed, public, no metrics
|
||||
(<$METRIC_TYPE:ty> pub $METRIC_ID:ident = $e:expr;) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<$METRIC_TYPE> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<$METRIC_TYPE> = $e.into(); }
|
||||
};
|
||||
// typed, public, some metrics
|
||||
(<$METRIC_TYPE:ty> pub $METRIC_ID:ident = $e:expr => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<$METRIC_TYPE> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<$METRIC_TYPE> = $e.into(); }
|
||||
__metrics_block!($METRIC_ID: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
// typed, module, no metrics
|
||||
(<$METRIC_TYPE:ty> $METRIC_ID:ident = $e:expr;) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<$METRIC_TYPE> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<$METRIC_TYPE> = $e.into(); }
|
||||
};
|
||||
// typed, module, some metrics
|
||||
(<$METRIC_TYPE:ty> $METRIC_ID:ident = $e:expr => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<$METRIC_TYPE> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<$METRIC_TYPE> = $e.into(); }
|
||||
__metrics_block!($METRIC_ID: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
// typed, reuse predeclared
|
||||
|
@ -46,32 +46,32 @@ macro_rules! app_metrics {
|
|||
};
|
||||
// typed, unidentified, some metrics
|
||||
(<$METRIC_TYPE:ty> $e:expr => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref UNIDENT_METRIC: AppMetrics<$METRIC_TYPE> = $e.into(); }
|
||||
lazy_static! { pub static ref UNIDENT_METRIC: Metrics<$METRIC_TYPE> = $e.into(); }
|
||||
__metrics_block!(UNIDENT_METRIC: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
// typed, root, some metrics
|
||||
(<$METRIC_TYPE:ty> { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref ROOT_METRICS: AppMetrics<$METRIC_TYPE> = "".into(); }
|
||||
lazy_static! { pub static ref ROOT_METRICS: Metrics<$METRIC_TYPE> = "".into(); }
|
||||
__metrics_block!(ROOT_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
|
||||
// DELEGATED
|
||||
// delegated, public, no metrics
|
||||
(pub $METRIC_ID:ident = $e:expr;) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<Delegate> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<Delegate> = $e.into(); }
|
||||
};
|
||||
// delegated, public, some metrics
|
||||
(pub $METRIC_ID:ident = $e:expr => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<Delegate> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<Delegate> = $e.into(); }
|
||||
__metrics_block!($METRIC_ID: Delegate; $($REMAINING)*);
|
||||
};
|
||||
// delegated, module, no metrics
|
||||
($METRIC_ID:ident = $e:expr;) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<Delegate> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<Delegate> = $e.into(); }
|
||||
};
|
||||
// delegated, module, some metrics
|
||||
($METRIC_ID:ident = $e:expr => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref $METRIC_ID: AppMetrics<Delegate> = $e.into(); }
|
||||
lazy_static! { pub static ref $METRIC_ID: Metrics<Delegate> = $e.into(); }
|
||||
__metrics_block!($METRIC_ID: Delegate; $($REMAINING)*);
|
||||
};
|
||||
// delegated,reuse predeclared
|
||||
|
@ -80,12 +80,12 @@ macro_rules! app_metrics {
|
|||
};
|
||||
// delegated, unidentified, some metrics
|
||||
($e:expr => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref UNIDENT_METRIC: AppMetrics<Delegate> = $e.into(); }
|
||||
lazy_static! { pub static ref UNIDENT_METRIC: Metrics<Delegate> = $e.into(); }
|
||||
__metrics_block!(UNIDENT_METRIC: Delegate; $($REMAINING)*);
|
||||
};
|
||||
// delegated, root, some metrics
|
||||
( => { $($REMAINING:tt)+ }) => {
|
||||
lazy_static! { pub static ref ROOT_METRICS: AppMetrics<Delegate> = "".into(); }
|
||||
lazy_static! { pub static ref ROOT_METRICS: Metrics<Delegate> = ().into(); }
|
||||
__metrics_block!(ROOT_METRICS: Delegate; $($REMAINING)*);
|
||||
};
|
||||
}
|
||||
|
@ -97,103 +97,177 @@ macro_rules! __metrics_block {
|
|||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* pub @Counter $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* pub static ref $METRIC_ID:
|
||||
AppCounter<$METRIC_TYPE> = $APP_METRICS.counter($METRIC_NAME); }
|
||||
Counter<$METRIC_TYPE> = $APP_METRICS.counter($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* @Counter $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* static ref $METRIC_ID:
|
||||
AppCounter<$METRIC_TYPE> = $APP_METRICS.counter($METRIC_NAME); }
|
||||
Counter<$METRIC_TYPE> = $APP_METRICS.counter($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* pub @Marker $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* pub static ref $METRIC_ID:
|
||||
AppMarker<$METRIC_TYPE> = $APP_METRICS.marker($METRIC_NAME); }
|
||||
Marker<$METRIC_TYPE> = $APP_METRICS.marker($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* @Marker $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* static ref $METRIC_ID:
|
||||
AppMarker<$METRIC_TYPE> = $APP_METRICS.marker($METRIC_NAME); }
|
||||
Marker<$METRIC_TYPE> = $APP_METRICS.marker($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* pub @Gauge $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* pub static ref $METRIC_ID:
|
||||
AppGauge<$METRIC_TYPE> = $APP_METRICS.gauge($METRIC_NAME); }
|
||||
Gauge<$METRIC_TYPE> = $APP_METRICS.gauge($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* @Gauge $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* static ref $METRIC_ID:
|
||||
AppGauge<$METRIC_TYPE> = $APP_METRICS.gauge($METRIC_NAME); }
|
||||
Gauge<$METRIC_TYPE> = $APP_METRICS.gauge($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* pub @Timer $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* pub static ref $METRIC_ID:
|
||||
AppTimer<$METRIC_TYPE> = $APP_METRICS.timer($METRIC_NAME); }
|
||||
Timer<$METRIC_TYPE> = $APP_METRICS.timer($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($APP_METRICS:ident : $METRIC_TYPE:ty;
|
||||
$(#[$attr:meta])* @Timer $METRIC_ID:ident : $METRIC_NAME:expr; $($REMAINING:tt)*) => {
|
||||
lazy_static! { $(#[$attr])* static ref $METRIC_ID:
|
||||
AppTimer<$METRIC_TYPE> = $APP_METRICS.timer($METRIC_NAME); }
|
||||
Timer<$METRIC_TYPE> = $APP_METRICS.timer($METRIC_NAME); }
|
||||
__metrics_block!($APP_METRICS: $METRIC_TYPE; $($REMAINING)*);
|
||||
};
|
||||
($METRIC_ID:ident : $METRIC_TYPE:ty;) => ()
|
||||
}
|
||||
|
||||
/// Define application-scoped metrics.
|
||||
#[macro_export]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
macro_rules! app_metrics {
|
||||
($type_param: ty, $metric_id: ident = ($($app_metrics: expr),+ $(,)*)) => {
|
||||
lazy_static! { pub static ref $metric_id: Metrics<$type_param> = metrics(($($app_metrics),*)); }
|
||||
};
|
||||
($type_param: ty, $metric_id: ident = [$($app_metrics: expr),+ $(,)*]) => {
|
||||
lazy_static! { pub static ref $metric_id: Metrics<$type_param> = metrics(&[$($app_metrics),*][..],); }
|
||||
};
|
||||
($type_param: ty, $metric_id: ident = $app_metrics: expr) => {
|
||||
lazy_static! { pub static ref $metric_id: Metrics<$type_param> = $app_metrics.into(); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// Define application-scoped markers.
|
||||
#[macro_export]
|
||||
#[deprecated]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
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 );)* }
|
||||
Marker<$type_param> = $app_metrics.marker( $metric_name );)* }
|
||||
};
|
||||
}
|
||||
|
||||
/// Define application-scoped counters.
|
||||
#[macro_export]
|
||||
#[deprecated]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
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 );)* }
|
||||
Counter<$type_param> = $app_metrics.counter( $metric_name );)* }
|
||||
};
|
||||
}
|
||||
|
||||
/// Define application-scoped gauges.
|
||||
#[macro_export]
|
||||
#[deprecated]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
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 );)* }
|
||||
Gauge<$type_param> = $app_metrics.gauge( $metric_name );)* }
|
||||
};
|
||||
}
|
||||
|
||||
/// Define application-scoped timers.
|
||||
#[macro_export]
|
||||
#[deprecated]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
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 );)* }
|
||||
Timer<$type_param> = $app_metrics.timer( $metric_name );)* }
|
||||
};
|
||||
}
|
||||
|
||||
/////////////
|
||||
// MOD SCOPE
|
||||
|
||||
/// Define module-scoped metrics.
|
||||
#[macro_export]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
macro_rules! mod_metrics {
|
||||
($type_param: ty, $metric_id: ident = ($($app_metrics: expr),+ $(,)*)) => {
|
||||
lazy_static! { static ref $metric_id: Metrics<$type_param> = metrics(($($app_metrics),*)); }
|
||||
};
|
||||
($type_param: ty, $metric_id: ident = [$($app_metrics: expr),+ $(,)*]) => {
|
||||
lazy_static! { static ref $metric_id: Metrics<$type_param> = metrics(&[$($app_metrics),*][..],); }
|
||||
};
|
||||
($type_param: ty, $metric_id: ident = $mod_metrics: expr) => {
|
||||
lazy_static! { static ref $metric_id: Metrics<$type_param> = $mod_metrics.into(); }
|
||||
};
|
||||
}
|
||||
|
||||
/// Define module-scoped markers.
|
||||
#[macro_export]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
macro_rules! mod_marker {
|
||||
($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
|
||||
lazy_static! { $(static ref $metric_id: Marker<$type_param> = $mod_metrics.marker( $metric_name );)* }
|
||||
};
|
||||
}
|
||||
|
||||
/// Define module-scoped counters.
|
||||
#[macro_export]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
macro_rules! mod_counter {
|
||||
($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
|
||||
lazy_static! { $(static ref $metric_id: Counter<$type_param> = $mod_metrics.counter( $metric_name );)* }
|
||||
};
|
||||
}
|
||||
|
||||
/// Define module-scoped gauges.
|
||||
#[macro_export]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
macro_rules! mod_gauge {
|
||||
($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
|
||||
lazy_static! { $(static ref $metric_id: Gauge<$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: Gauge<$type_param> = $mod_metrics.gauge( $metric_name ); }
|
||||
}
|
||||
}
|
||||
|
||||
/// Define module-scoped timers.
|
||||
#[macro_export]
|
||||
#[deprecated(since="0.7.0", note="Use metrics!() instead")]
|
||||
macro_rules! mod_timer {
|
||||
($type_param: ty, $mod_metrics: expr, { $($metric_id: ident: $metric_name: expr),* $(,)* } ) => {
|
||||
lazy_static! { $(static ref $metric_id: Timer<$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"););
|
||||
metrics!(<Aggregate> TEST_METRICS = DIPSTICK_METRICS.with_prefix("test_prefix"););
|
||||
|
||||
app_marker!(<Aggregate> TEST_METRICS => {
|
||||
M1: "failed",
|
||||
|
|
|
@ -12,7 +12,7 @@ use core::Kind::*;
|
|||
use namespace::*;
|
||||
use cache::*;
|
||||
use schedule::*;
|
||||
use app_delegate::*;
|
||||
use delegate::*;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -21,12 +21,23 @@ pub use num::ToPrimitive;
|
|||
|
||||
/// Wrap the metrics backend to provide an application-friendly interface.
|
||||
/// Open a metric scope to share across the application.
|
||||
pub fn app_metrics<M, AM>(app_metrics: AM) -> AppMetrics<M>
|
||||
#[deprecated(since="0.7.0", note="Use metrics() instead")]
|
||||
pub fn app_metrics<M, AM>(scope: AM) -> Metrics<M>
|
||||
where
|
||||
M: Clone + Send + Sync + 'static,
|
||||
AM: Into<AppMetrics<M>>,
|
||||
AM: Into<Metrics<M>>,
|
||||
{
|
||||
app_metrics.into()
|
||||
scope.into()
|
||||
}
|
||||
|
||||
/// Wrap the metrics backend to provide an application-friendly interface.
|
||||
/// Open a metric scope to share across the application.
|
||||
pub fn metrics<M, AM>(scope: AM) -> Metrics<M>
|
||||
where
|
||||
M: Clone + Send + Sync + 'static,
|
||||
AM: Into<Metrics<M>>,
|
||||
{
|
||||
scope.into()
|
||||
}
|
||||
|
||||
/// A monotonic counter metric.
|
||||
|
@ -34,13 +45,13 @@ where
|
|||
/// preventing programming errors.
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct AppMarker<M> {
|
||||
pub struct Marker<M> {
|
||||
metric: M,
|
||||
#[derivative(Debug = "ignore")]
|
||||
scope: ControlScopeFn<M>,
|
||||
scope: WriteFn<M>,
|
||||
}
|
||||
|
||||
impl<M> AppMarker<M> {
|
||||
impl<M> Marker<M> {
|
||||
/// Record a single event occurence.
|
||||
pub fn mark(&self) {
|
||||
self.scope.write(&self.metric, 1);
|
||||
|
@ -50,13 +61,13 @@ impl<M> AppMarker<M> {
|
|||
/// A counter that sends values to the metrics backend
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct AppCounter<M> {
|
||||
pub struct Counter<M> {
|
||||
metric: M,
|
||||
#[derivative(Debug = "ignore")]
|
||||
scope: ControlScopeFn<M>,
|
||||
scope: WriteFn<M>,
|
||||
}
|
||||
|
||||
impl<M> AppCounter<M> {
|
||||
impl<M> Counter<M> {
|
||||
/// Record a value count.
|
||||
pub fn count<V: ToPrimitive>(&self, count: V) {
|
||||
self.scope.write(&self.metric, count.to_u64().unwrap());
|
||||
|
@ -66,13 +77,13 @@ impl<M> AppCounter<M> {
|
|||
/// A gauge that sends values to the metrics backend
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct AppGauge<M> {
|
||||
pub struct Gauge<M> {
|
||||
metric: M,
|
||||
#[derivative(Debug = "ignore")]
|
||||
scope: ControlScopeFn<M>,
|
||||
scope: WriteFn<M>,
|
||||
}
|
||||
|
||||
impl<M> AppGauge<M> {
|
||||
impl<M> Gauge<M> {
|
||||
/// Record a value point for this gauge.
|
||||
pub fn value<V: ToPrimitive>(&self, value: V) {
|
||||
self.scope.write(&self.metric, value.to_u64().unwrap());
|
||||
|
@ -87,13 +98,13 @@ impl<M> AppGauge<M> {
|
|||
/// - with the interval_us() method, providing an externally determined microsecond interval
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct AppTimer<M> {
|
||||
pub struct Timer<M> {
|
||||
metric: M,
|
||||
#[derivative(Debug = "ignore")]
|
||||
scope: ControlScopeFn<M>,
|
||||
scope: WriteFn<M>,
|
||||
}
|
||||
|
||||
impl<M> AppTimer<M> {
|
||||
impl<M> Timer<M> {
|
||||
/// Record a microsecond interval for this timer
|
||||
/// Can be used in place of start()/stop() if an external time interval source is used
|
||||
pub fn interval_us<V: ToPrimitive>(&self, interval_us: V) -> V {
|
||||
|
@ -132,29 +143,47 @@ impl<M> AppTimer<M> {
|
|||
}
|
||||
}
|
||||
|
||||
//// AppMetrics proper
|
||||
/// Help transition to new syntax
|
||||
#[deprecated(since="0.7.0", note="Use Metrics instead")]
|
||||
pub type AppMetrics<M> = Metrics<M>;
|
||||
|
||||
/// Help transition to new syntax
|
||||
#[deprecated(since="0.7.0", note="Use Marker instead")]
|
||||
pub type AppMarker<M> = Marker<M>;
|
||||
|
||||
/// Help transition to new syntax
|
||||
#[deprecated(since="0.7.0", note="Use Counter instead")]
|
||||
pub type AppCounter<M> = Counter<M>;
|
||||
|
||||
/// Help transition to new syntax
|
||||
#[deprecated(since="0.7.0", note="Use Gauge instead")]
|
||||
pub type AppGauge<M> = Gauge<M>;
|
||||
|
||||
/// Help transition to new syntax
|
||||
#[deprecated(since="0.7.0", note="Use Timer instead")]
|
||||
pub type AppTimer<M> = Timer<M>;
|
||||
|
||||
|
||||
/// Variations of this should also provide control of the metric recording scope.
|
||||
#[derive(Derivative, Clone)]
|
||||
#[derivative(Debug)]
|
||||
pub struct AppMetrics<M> {
|
||||
pub struct Metrics<M> {
|
||||
#[derivative(Debug = "ignore")]
|
||||
define_metric_fn: DefineMetricFn<M>,
|
||||
#[derivative(Debug = "ignore")]
|
||||
single_scope: ControlScopeFn<M>,
|
||||
single_scope: WriteFn<M>,
|
||||
}
|
||||
|
||||
impl<M> AppMetrics<M> {
|
||||
impl<M> Metrics<M> {
|
||||
/// Create new application metrics instance.
|
||||
pub fn new(define_metric_fn: DefineMetricFn<M>, scope: ControlScopeFn<M>) -> Self {
|
||||
AppMetrics {
|
||||
pub fn new(define_metric_fn: DefineMetricFn<M>, scope: WriteFn<M>) -> Self {
|
||||
Metrics {
|
||||
define_metric_fn,
|
||||
single_scope: scope,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> AppMetrics<M>
|
||||
impl<M> Metrics<M>
|
||||
where
|
||||
M: Clone + Send + Sync + 'static,
|
||||
{
|
||||
|
@ -164,44 +193,43 @@ where
|
|||
(self.define_metric_fn)(kind, name, rate)
|
||||
}
|
||||
|
||||
/// Get an event counter of the provided name.
|
||||
pub fn marker<AS: AsRef<str>>(&self, name: AS) -> AppMarker<M> {
|
||||
/// Define an event counter of the provided name.
|
||||
pub fn marker<AS: AsRef<str>>(&self, name: AS) -> Marker<M> {
|
||||
let metric = self.define_metric(Marker, name.as_ref(), 1.0);
|
||||
AppMarker {
|
||||
Marker {
|
||||
metric,
|
||||
scope: self.single_scope.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a counter of the provided name.
|
||||
pub fn counter<AS: AsRef<str>>(&self, name: AS) -> AppCounter<M> {
|
||||
/// Define a counter of the provided name.
|
||||
pub fn counter<AS: AsRef<str>>(&self, name: AS) -> Counter<M> {
|
||||
let metric = self.define_metric(Counter, name.as_ref(), 1.0);
|
||||
AppCounter {
|
||||
Counter {
|
||||
metric,
|
||||
scope: self.single_scope.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a timer of the provided name.
|
||||
pub fn timer<AS: AsRef<str>>(&self, name: AS) -> AppTimer<M> {
|
||||
/// Define a timer of the provided name.
|
||||
pub fn timer<AS: AsRef<str>>(&self, name: AS) -> Timer<M> {
|
||||
let metric = self.define_metric(Timer, name.as_ref(), 1.0);
|
||||
AppTimer {
|
||||
Timer {
|
||||
metric,
|
||||
scope: self.single_scope.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a gauge of the provided name.
|
||||
pub fn gauge<AS: AsRef<str>>(&self, name: AS) -> AppGauge<M> {
|
||||
/// Define a gauge of the provided name.
|
||||
pub fn gauge<AS: AsRef<str>>(&self, name: AS) -> Gauge<M> {
|
||||
let metric = self.define_metric(Gauge, name.as_ref(), 1.0);
|
||||
AppGauge {
|
||||
Gauge {
|
||||
metric,
|
||||
scope: self.single_scope.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Forcefully flush the backing metrics scope.
|
||||
/// This is usually not required since static metrics use auto flushing scopes.
|
||||
/// Flush the backing metrics buffer.
|
||||
/// The effect, if any, of this method depends on the selected metrics backend.
|
||||
pub fn flush(&self) {
|
||||
self.single_scope.flush();
|
||||
|
@ -223,17 +251,17 @@ where
|
|||
|
||||
//// Dispatch / Receiver impl
|
||||
|
||||
struct AppRecvMetricImpl<M> {
|
||||
struct RecvMetricImpl<M> {
|
||||
metric: M,
|
||||
scope: ControlScopeFn<M>,
|
||||
scope: WriteFn<M>,
|
||||
}
|
||||
|
||||
impl<M: Send + Sync + Clone + 'static> AppRecv for AppMetrics<M> {
|
||||
fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box<AppRecvMetric + Send + Sync> {
|
||||
let scope: ControlScopeFn<M> = self.single_scope.clone();
|
||||
impl<M: Send + Sync + Clone + 'static> MetricsRecv for Metrics<M> {
|
||||
fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box<RecvMetric + Send + Sync> {
|
||||
let scope: WriteFn<M> = self.single_scope.clone();
|
||||
let metric: M = self.define_metric(kind, name, rate);
|
||||
|
||||
Box::new(AppRecvMetricImpl { metric, scope })
|
||||
Box::new(RecvMetricImpl { metric, scope })
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
|
@ -241,7 +269,7 @@ impl<M: Send + Sync + Clone + 'static> AppRecv for AppMetrics<M> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<M> AppRecvMetric for AppRecvMetricImpl<M> {
|
||||
impl<M> RecvMetric for RecvMetricImpl<M> {
|
||||
fn write(&self, value: Value) {
|
||||
self.scope.write(&self.metric, value);
|
||||
}
|
||||
|
@ -249,19 +277,19 @@ impl<M> AppRecvMetric for AppRecvMetricImpl<M> {
|
|||
|
||||
//// Mutators impl
|
||||
|
||||
impl<M: Send + Sync + Clone + 'static> WithNamespace for AppMetrics<M> {
|
||||
impl<M: Send + Sync + Clone + 'static> WithNamespace for Metrics<M> {
|
||||
fn with_name<IN: Into<Namespace>>(&self, names: IN) -> Self {
|
||||
let ns = &names.into();
|
||||
AppMetrics {
|
||||
Metrics {
|
||||
define_metric_fn: add_namespace(ns, self.define_metric_fn.clone()),
|
||||
single_scope: self.single_scope.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Send + Sync + Clone + 'static> WithCache for AppMetrics<M> {
|
||||
impl<M: Send + Sync + Clone + 'static> WithCache for Metrics<M> {
|
||||
fn with_cache(&self, cache_size: usize) -> Self {
|
||||
AppMetrics {
|
||||
Metrics {
|
||||
define_metric_fn: add_cache(cache_size, self.define_metric_fn.clone()),
|
||||
single_scope: self.single_scope.clone(),
|
||||
}
|
||||
|
@ -277,7 +305,7 @@ mod bench {
|
|||
#[bench]
|
||||
fn time_bench_direct_dispatch_event(b: &mut test::Bencher) {
|
||||
let sink = aggregate(summary, to_void());
|
||||
let metrics = app_metrics(sink);
|
||||
let metrics = metrics(sink);
|
||||
let marker = metrics.marker("aaa");
|
||||
b.iter(|| test::black_box(marker.mark()));
|
||||
}
|
18
src/multi.rs
18
src/multi.rs
|
@ -1,27 +1,27 @@
|
|||
//! Dispatch metrics to multiple sinks.
|
||||
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use app_metrics::*;
|
||||
use context::*;
|
||||
use metrics::*;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Two chains of different types can be combined in a tuple.
|
||||
/// The chains will act as one, each receiving calls in the order the appear in the tuple.
|
||||
/// For more than two types, make tuples of tuples, "Yo Dawg" style.
|
||||
impl<M1, M2> From<(LocalMetrics<M1>, LocalMetrics<M2>)> for AppMetrics<(M1, M2)>
|
||||
impl<M1, M2> From<(MetricContext<M1>, MetricContext<M2>)> for Metrics<(M1, M2)>
|
||||
where
|
||||
M1: 'static + Clone + Send + Sync,
|
||||
M2: 'static + Clone + Send + Sync,
|
||||
{
|
||||
fn from(combo: (LocalMetrics<M1>, LocalMetrics<M2>)) -> AppMetrics<(M1, M2)> {
|
||||
fn from(combo: (MetricContext<M1>, MetricContext<M2>)) -> Metrics<(M1, M2)> {
|
||||
let scope0 = combo.0.open_scope();
|
||||
let scope1 = combo.1.open_scope();
|
||||
|
||||
let scope0a = scope0.clone();
|
||||
let scope1a = scope1.clone();
|
||||
|
||||
AppMetrics::new(
|
||||
Metrics::new(
|
||||
Arc::new(move |kind, name, rate| (
|
||||
scope0.define_metric(kind, name, rate),
|
||||
scope1.define_metric(kind, name, rate),
|
||||
|
@ -41,15 +41,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, M> From<&'a [LocalMetrics<M>]> for AppMetrics<Vec<M>>
|
||||
impl<'a, M> From<&'a [MetricContext<M>]> for Metrics<Vec<M>>
|
||||
where
|
||||
M: 'static + Clone + Send + Sync,
|
||||
{
|
||||
fn from(chains: &'a [LocalMetrics<M>]) -> AppMetrics<Vec<M>> {
|
||||
let scopes: Vec<AppMetrics<M>> = chains.iter().map(|x| x.open_scope()).collect();
|
||||
fn from(chains: &'a [MetricContext<M>]) -> Metrics<Vec<M>> {
|
||||
let scopes: Vec<Metrics<M>> = chains.iter().map(|x| x.open_scope()).collect();
|
||||
let scopes2 = scopes.clone();
|
||||
|
||||
AppMetrics::new(
|
||||
Metrics::new(
|
||||
Arc::new(move |kind, name, rate| {
|
||||
scopes.iter().map(|m| m.define_metric(kind, name, rate)).collect()
|
||||
}),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//! Standard stateless metric outputs.
|
||||
// TODO parameterize templates
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use context::*;
|
||||
use std::sync::RwLock;
|
||||
|
||||
/// Write metric values to stdout using `println!`.
|
||||
pub fn to_stdout() -> LocalMetrics<String> {
|
||||
pub fn to_stdout() -> MetricContext<String> {
|
||||
metrics_context(
|
||||
|_kind, name, _rate| String::from(name),
|
||||
|| control_scope(|cmd|
|
||||
|
@ -19,7 +19,7 @@ pub fn to_stdout() -> LocalMetrics<String> {
|
|||
/// Values are buffered until #flush is called
|
||||
/// Buffered operation requires locking.
|
||||
/// If thread latency is a concern you may wish to also use #with_async_queue.
|
||||
pub fn to_buffered_stdout() -> LocalMetrics<String> {
|
||||
pub fn to_buffered_stdout() -> MetricContext<String> {
|
||||
metrics_context(
|
||||
|_kind, name, _rate| String::from(name),
|
||||
|| {
|
||||
|
@ -42,7 +42,7 @@ pub fn to_buffered_stdout() -> LocalMetrics<String> {
|
|||
|
||||
/// Write metric values to the standard log using `info!`.
|
||||
// TODO parameterize log level
|
||||
pub fn to_log() -> LocalMetrics<String> {
|
||||
pub fn to_log() -> MetricContext<String> {
|
||||
metrics_context(
|
||||
|_kind, name, _rate| String::from(name),
|
||||
|| control_scope(|cmd|
|
||||
|
@ -57,7 +57,7 @@ pub fn to_log() -> LocalMetrics<String> {
|
|||
/// Buffered operation requires locking.
|
||||
/// If thread latency is a concern you may wish to also use #with_async_queue.
|
||||
// TODO parameterize log level
|
||||
pub fn to_buffered_log() -> LocalMetrics<String> {
|
||||
pub fn to_buffered_log() -> MetricContext<String> {
|
||||
metrics_context(
|
||||
|_kind, name, _rate| String::from(name),
|
||||
|| {
|
||||
|
@ -80,7 +80,7 @@ pub fn to_buffered_log() -> LocalMetrics<String> {
|
|||
|
||||
|
||||
/// Discard all metric values sent to it.
|
||||
pub fn to_void() -> LocalMetrics<()> {
|
||||
pub fn to_void() -> MetricContext<()> {
|
||||
metrics_context(
|
||||
move |_kind, _name, _rate| (),
|
||||
|| control_scope(|_cmd| {}),
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
//! ```
|
||||
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use context::*;
|
||||
use core::Kind::*;
|
||||
use scores::{ScoreSnapshot, ScoreType};
|
||||
use scores::ScoreType::*;
|
||||
|
@ -40,7 +40,7 @@ pub trait Publish: Send + Sync + Debug {
|
|||
pub struct Publisher<E, M> {
|
||||
#[derivative(Debug = "ignore")]
|
||||
statistics: Box<E>,
|
||||
output: LocalMetrics<M>,
|
||||
output: MetricContext<M>,
|
||||
}
|
||||
|
||||
impl<E, M> Publisher<E, M>
|
||||
|
@ -50,7 +50,7 @@ where
|
|||
{
|
||||
/// Define a new metrics publishing strategy, from a transformation
|
||||
/// function and a target metric chain.
|
||||
pub fn new(stat_fn: E, output: LocalMetrics<M>) -> Self {
|
||||
pub fn new(stat_fn: E, output: MetricContext<M>) -> Self {
|
||||
Publisher {
|
||||
statistics: Box::new(stat_fn),
|
||||
output,
|
||||
|
|
|
@ -1,39 +1,41 @@
|
|||
use app_metrics::AppMetrics;
|
||||
use metrics::Metrics;
|
||||
use output;
|
||||
use app_delegate::{AppRecv, AppSend};
|
||||
use delegate::{MetricsRecv, MetricsSend};
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
fn no_app_metrics() -> Arc<AppRecv + Send + Sync> {
|
||||
let void_metrics: AppMetrics<_> = output::to_void().into();
|
||||
fn no_metrics() -> Arc<MetricsRecv + Send + Sync> {
|
||||
let void_metrics: Metrics<_> = output::to_void().into();
|
||||
Arc::new(void_metrics)
|
||||
}
|
||||
|
||||
/// The registry contains a list of every metrics dispatch point in the app.
|
||||
lazy_static! {
|
||||
static ref NO_APP_METRICS: Arc<AppRecv + Sync + Send> = no_app_metrics();
|
||||
static ref NO_RECV: Arc<MetricsRecv + Sync + Send> = no_metrics();
|
||||
|
||||
static ref DEFAULT_APP_RECEIVER: RwLock<Arc<AppRecv + Sync + Send>> = RwLock::new(NO_APP_METRICS.clone());
|
||||
static ref DEFAULT_RECV: RwLock<Arc<MetricsRecv + Sync + Send>> = RwLock::new(NO_RECV.clone());
|
||||
|
||||
static ref DELEGATE_REGISTRY: RwLock<Vec<AppSend>> = RwLock::new(vec![]);
|
||||
static ref DELEGATE_REGISTRY: RwLock<Vec<MetricsSend>> = RwLock::new(vec![]);
|
||||
}
|
||||
|
||||
/// Register a new app send.
|
||||
pub fn add_app_send(send: AppSend) {
|
||||
pub fn add_metrics_send(send: MetricsSend) {
|
||||
DELEGATE_REGISTRY.write().unwrap().push(send.clone());
|
||||
}
|
||||
|
||||
/// Get the default app recv.
|
||||
pub fn get_default_app_recv() -> Arc<AppRecv + Send + Sync> {
|
||||
DEFAULT_APP_RECEIVER.read().unwrap().clone()
|
||||
pub fn get_default_metrics_recv() -> Arc<MetricsRecv + Send + Sync> {
|
||||
DEFAULT_RECV.read().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Install a new receiver for all dispatched metrics, replacing any previous receiver.
|
||||
pub fn send_app_metrics<IS: Into<AppMetrics<T>>, T: Send + Sync + Clone + 'static>(
|
||||
pub fn send_metrics<IS: Into<Metrics<T>>, T: Send + Sync + Clone + 'static>(
|
||||
into_recv: IS,
|
||||
) {
|
||||
let recv = into_recv.into();
|
||||
let recv = Arc::new(into_recv.into());
|
||||
for d in DELEGATE_REGISTRY.read().unwrap().iter() {
|
||||
d.set_receiver(recv.clone());
|
||||
}
|
||||
|
||||
*DEFAULT_RECV.write().unwrap() = recv;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//! Reduce the amount of data to process or transfer by statistically dropping some of it.
|
||||
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use context::*;
|
||||
|
||||
use pcg32;
|
||||
|
||||
|
@ -16,7 +16,7 @@ where
|
|||
fn with_sampling_rate(&self, sampling_rate: Rate) -> Self;
|
||||
}
|
||||
|
||||
impl<M: Send + Sync + 'static + Clone> WithSamplingRate for LocalMetrics<M> {
|
||||
impl<M: Send + Sync + 'static + Clone> WithSamplingRate for MetricContext<M> {
|
||||
fn with_sampling_rate(&self, sampling_rate: Rate) -> Self {
|
||||
let int_sampling_rate = pcg32::to_int_rate(sampling_rate);
|
||||
|
||||
|
@ -52,10 +52,10 @@ impl<M: Send + Sync + 'static + Clone> WithSamplingRate for LocalMetrics<M> {
|
|||
|
||||
/// Perform random sampling of values according to the specified rate.
|
||||
#[deprecated(since = "0.5.0", note = "Use `with_sampling_rate` instead.")]
|
||||
pub fn sample<M, IC>(sampling_rate: Rate, chain: IC) -> LocalMetrics<M>
|
||||
pub fn sample<M, IC>(sampling_rate: Rate, chain: IC) -> MetricContext<M>
|
||||
where
|
||||
M: Clone + Send + Sync + 'static,
|
||||
IC: Into<LocalMetrics<M>>,
|
||||
IC: Into<MetricContext<M>>,
|
||||
{
|
||||
let chain = chain.into();
|
||||
chain.with_sampling_rate(sampling_rate)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
pub use core::*;
|
||||
|
||||
pub use app_metrics::*;
|
||||
pub use metrics::*;
|
||||
pub use aggregate::*;
|
||||
pub use publish::*;
|
||||
pub use scores::*;
|
||||
|
@ -18,7 +18,7 @@ lazy_static! {
|
|||
|
||||
/// Application metrics are collected to the aggregator
|
||||
|
||||
app_metrics!(<Aggregate> DIPSTICK_METRICS = build_self_metrics(););
|
||||
metrics!(<Aggregate> DIPSTICK_METRICS = build_self_metrics(););
|
||||
|
||||
fn build_aggregator() -> Aggregator {
|
||||
// TODO make publishable
|
||||
|
@ -30,8 +30,8 @@ pub fn snapshot() -> Vec<ScoreSnapshot> {
|
|||
vec![]
|
||||
}
|
||||
|
||||
fn build_self_metrics() -> AppMetrics<Aggregate> {
|
||||
fn build_self_metrics() -> Metrics<Aggregate> {
|
||||
let mug: &Aggregator = &DIPSTICK_AGGREGATOR;
|
||||
let am: AppMetrics<Aggregate> = mug.clone().into();
|
||||
let am: Metrics<Aggregate> = mug.clone().into();
|
||||
am.with_prefix("dipstick")
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Send metrics to a statsd server.
|
||||
|
||||
use core::*;
|
||||
use local_metrics::*;
|
||||
use context::*;
|
||||
use error;
|
||||
use self_metrics::*;
|
||||
|
||||
|
@ -10,7 +10,7 @@ use std::sync::{Arc, RwLock};
|
|||
|
||||
pub use std::net::ToSocketAddrs;
|
||||
|
||||
app_metrics! {
|
||||
metrics! {
|
||||
<Aggregate> DIPSTICK_METRICS.with_prefix("statsd") => {
|
||||
@Marker SEND_ERR: "send_failed";
|
||||
@Counter SENT_BYTES: "sent_bytes";
|
||||
|
@ -18,7 +18,7 @@ app_metrics! {
|
|||
}
|
||||
|
||||
/// Send metrics to a statsd server at the address and port provided.
|
||||
pub fn to_statsd<ADDR>(address: ADDR) -> error::Result<LocalMetrics<Statsd>>
|
||||
pub fn to_statsd<ADDR>(address: ADDR) -> error::Result<MetricContext<Statsd>>
|
||||
where
|
||||
ADDR: ToSocketAddrs,
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue