diff --git a/README.md b/README.md index 9a1a4c5..1a8f805 100644 --- a/README.md +++ b/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"); diff --git a/examples/aggregate.rs b/examples/aggregate.rs index 6009cd4..d0800de 100644 --- a/examples/aggregate.rs +++ b/examples/aggregate.rs @@ -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)); diff --git a/examples/async.rs b/examples/async.rs index 48853a7..d53bdd8 100644 --- a/examples/async.rs +++ b/examples/async.rs @@ -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"); diff --git a/examples/basics.rs b/examples/basics.rs index f9e4600..334f6e8 100644 --- a/examples/basics.rs +++ b/examples/basics.rs @@ -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"); diff --git a/examples/custom_publish.rs b/examples/custom_publish.rs index ca7eb2a..47f9dff 100644 --- a/examples/custom_publish.rs +++ b/examples/custom_publish.rs @@ -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)); diff --git a/examples/graphite.rs b/examples/graphite.rs index a96433e..dd85373 100644 --- a/examples/graphite.rs +++ b/examples/graphite.rs @@ -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"][..]), diff --git a/examples/macro_delegate.rs b/examples/macro_delegate.rs index b9a0c44..44e0713 100644 --- a/examples/macro_delegate.rs +++ b/examples/macro_delegate.rs @@ -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); diff --git a/examples/macro_deprecated.rs b/examples/macro_deprecated.rs new file mode 100644 index 0000000..c9a0e4e --- /dev/null +++ b/examples/macro_deprecated.rs @@ -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, 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, 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)); + } +} + diff --git a/examples/macro_multi.rs b/examples/macro_multi.rs index f926564..27e24cd 100644 --- a/examples/macro_multi.rs +++ b/examples/macro_multi.rs @@ -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!(> SAME_TYPE = [ +metrics!(> 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!(> MUTANT_CHILD = SAME_TYPE.with_prefix("super").with_prefix("duper");); +metrics!(> MUTANT_CHILD = SAME_TYPE.with_prefix("super").with_prefix("duper");); fn main() { loop { diff --git a/examples/multi_out.rs b/examples/multi_out.rs index 169c87c..31d4209 100644 --- a/examples/multi_out.rs +++ b/examples/multi_out.rs @@ -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"), diff --git a/examples/sampling.rs b/examples/sampling.rs index c145107..73ac097 100644 --- a/examples/sampling.rs +++ b/examples/sampling.rs @@ -7,7 +7,7 @@ use dipstick::*; fn main() { // print only 1 out of every 10000 metrics recorded - let app_metrics: AppMetrics = app_metrics(to_stdout().with_sampling_rate(0.0001)); + let app_metrics: Metrics = metrics(to_stdout().with_sampling_rate(0.0001)); let marker = app_metrics.marker("marker_a"); diff --git a/examples/static_metrics.rs b/examples/static_metrics.rs deleted file mode 100644 index 325ee14..0000000 --- a/examples/static_metrics.rs +++ /dev/null @@ -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 = app_metrics(to_stdout()); - pub static ref COUNTER_A: AppCounter = METRICS.counter("counter_a"); - pub static ref TIMER_B: AppTimer = 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); -} diff --git a/examples/summary.rs b/examples/summary.rs index 99f2e7a..703fa80 100644 --- a/examples/summary.rs +++ b/examples/summary.rs @@ -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)); diff --git a/src/aggregate.rs b/src/aggregate.rs index c4ee4b7..36491c2 100644 --- a/src/aggregate.rs +++ b/src/aggregate.rs @@ -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(stat_fn: E, to_chain: LocalMetrics) -> Aggregator +pub fn aggregate(stat_fn: E, to_chain: MetricContext) -> 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 for AppMetrics { - fn from(agg: Aggregator) -> AppMetrics { +impl From for Metrics { + fn from(agg: Aggregator) -> Metrics { 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 for AppMetrics { } } -impl From<&'static str> for AppMetrics { - fn from(prefix: &'static str) -> AppMetrics { - let app_metrics: AppMetrics = aggregate(summary, to_void()).into(); +impl From<&'static str> for Metrics { + fn from(prefix: &'static str) -> Metrics { + let app_metrics: Metrics = 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(summary, to_void()).into(); + let sink: Metrics = 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(summary, to_void()).into(); + let sink: Metrics = 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(summary, to_void()).into(); + let sink: Metrics = 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(summary, to_void()).into(); + let sink: Metrics = aggregate(summary, to_void()).into(); let metric = sink.define_metric(Counter, "count_a", 1.0); b.iter(|| test::black_box(metric.reset())); } diff --git a/src/async_queue.rs b/src/async_queue.rs index 271c5f7..a7eafae 100644 --- a/src/async_queue.rs +++ b/src/async_queue.rs @@ -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!{ 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 WithAsyncQueue for LocalMetrics { +impl WithAsyncQueue for MetricContext { fn with_async_queue(&self, queue_size: usize) -> Self { self.mod_scope(|next| { // setup channel @@ -49,7 +49,7 @@ impl WithAsyncQueue for LocalMetrics { Arc::new(move || { // open next scope, make it Arc to move across queue - let next_scope: ControlScopeFn = next(); + let next_scope: WriteFn = next(); let sender = sender.clone(); // forward any scope command through the channel @@ -78,10 +78,10 @@ impl WithAsyncQueue for LocalMetrics { /// Enqueue collected metrics for dispatch on background thread. #[deprecated(since = "0.5.0", note = "Use `with_async_queue` instead.")] -pub fn async(queue_size: usize, chain: IC) -> LocalMetrics +pub fn async(queue_size: usize, chain: IC) -> MetricContext where M: Clone + Send + Sync + 'static, - IC: Into>, + IC: Into>, { let chain = chain.into(); chain.with_async_queue(queue_size) @@ -96,5 +96,5 @@ pub struct QueueCommand { cmd: Option<(M, Value)>, /// The scope to write the metric to #[derivative(Debug = "ignore")] - next_scope: ControlScopeFn, + next_scope: WriteFn, } diff --git a/src/local_metrics.rs b/src/context.rs similarity index 77% rename from src/local_metrics.rs rename to src/context.rs index d6e2afc..c182eeb 100755 --- a/src/local_metrics.rs +++ b/src/context.rs @@ -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 { +pub struct MetricContext { #[derivative(Debug = "ignore")] define_metric_fn: DefineMetricFn, @@ -19,7 +19,7 @@ pub struct LocalMetrics { scope_metric_fn: OpenScopeFn, } -impl LocalMetrics { +impl MetricContext { /// 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 LocalMetrics { /// let request_counter = scope_metrics.counter("scope_counter"); /// ``` /// - pub fn open_scope(&self) -> AppMetrics { - AppMetrics::new(self.define_metric_fn.clone(), (self.scope_metric_fn)()) + pub fn open_scope(&self) -> Metrics { + 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(make_metric: MF, make_scope: WF) -> LocalMetrics +pub fn metrics_context(make_metric: MF, make_scope: WF) -> MetricContext where MF: Fn(Kind, &str, Rate) -> M + Send + Sync + 'static, - WF: Fn() -> ControlScopeFn + Send + Sync + 'static, + WF: Fn() -> WriteFn + Send + Sync + 'static, { - LocalMetrics { + MetricContext { define_metric_fn: Arc::new(make_metric), scope_metric_fn: Arc::new(make_scope), } } -impl LocalMetrics { +impl MetricContext { /// Intercept both metric definition and scope creation, possibly changing the metric type. - pub fn mod_both(&self, mod_fn: MF) -> LocalMetrics + pub fn mod_both(&self, mod_fn: MF) -> MetricContext where MF: Fn(DefineMetricFn, OpenScopeFn) -> (DefineMetricFn, OpenScopeFn), 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 LocalMetrics { where MF: Fn(OpenScopeFn) -> OpenScopeFn, { - 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 LocalMetrics { } -impl From> for AppMetrics { - fn from(metrics: LocalMetrics) -> AppMetrics { +impl From> for Metrics { + fn from(metrics: MetricContext) -> Metrics { metrics.open_scope() } } -impl WithNamespace for LocalMetrics { +impl WithNamespace for MetricContext { fn with_name>(&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(), } diff --git a/src/core.rs b/src/core.rs index 2f2d333..341e375 100644 --- a/src/core.rs +++ b/src/core.rs @@ -63,10 +63,10 @@ pub enum Kind { pub type DefineMetricFn = Arc M + Send + Sync>; /// A function trait that opens a new metric capture scope. -pub type OpenScopeFn = Arc ControlScopeFn + Send + Sync>; +pub type OpenScopeFn = Arc WriteFn + Send + Sync>; /// A function trait that writes to or flushes a certain scope. -pub type ControlScopeFn = Arc>; +pub type WriteFn = Arc>; /// 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(scope_fn: F) -> ControlScopeFn +pub fn control_scope(scope_fn: F) -> WriteFn where F: Fn(ScopeCmd) + 'static, { diff --git a/src/app_delegate.rs b/src/delegate.rs similarity index 66% rename from src/app_delegate.rs rename to src/delegate.rs index 55c096c..c34aa48 100755 --- a/src/app_delegate.rs +++ b/src/delegate.rs @@ -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; + fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box; /// 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` /// looks better than `AppMetrics>`. -pub type Delegate = Arc; +pub type Delegate = Arc; /// 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>, + recv_metric: AtomicRefCell>, #[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>, +pub struct MetricsSend { + inner: Arc>, } -struct InnerAppSend { - metrics: HashMap>, - recv: Arc, +struct InnerMetricsSend { + metrics: HashMap>, + recv: Arc, } -impl From<&'static str> for AppMetrics { - fn from(prefix: &'static str) -> AppMetrics { - let app_metrics: AppMetrics = app_delegate().into(); +/// Allow turning a 'static str into a Delegate, where str is the prefix. +impl From<&'static str> for Metrics { + fn from(prefix: &'static str) -> Metrics { + let app_metrics: Metrics = delegate_metrics().into(); app_metrics.with_prefix(prefix) } } -impl From for AppMetrics { - fn from(send: AppSend) -> AppMetrics { +/// Allow turning a 'static str into a Delegate, where str is the prefix. +impl From<()> for Metrics { + fn from(_: ()) -> Metrics { + let app_metrics: Metrics = delegate_metrics().into(); + app_metrics + } +} + + +impl From for Metrics { + fn from(send: MetricsSend) -> Metrics { 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 = metric; + let dispatch: &Arc = metric; dispatch.recv_metric.borrow().write(value); -// let recv_metric: AtomicRef> = 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 for AppMetrics { } } -impl AppSend { +impl MetricsSend { /// Install a new metric receiver, replacing the previous one. - pub fn set_receiver>, T: Send + Sync + Clone + 'static>( - &self, - receiver: IS, - ) { - let receiver: Arc = Arc::new(receiver.into()); - let inner: &mut InnerAppSend = - &mut *self.inner.write().expect("Lock Metrics Send"); + pub fn set_receiver(&self, recv: Arc) { + 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 = dispatch.clone().into(); + let dispatch = delegate_metrics(); + let sink: Metrics = 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 = dispatch.into(); + let dispatch = delegate_metrics(); + let sink: Metrics = dispatch.into(); let metric = sink.marker("event_a"); b.iter(|| test::black_box(metric.mark())); } diff --git a/src/graphite.rs b/src/graphite.rs index 013cab8..66e0053 100644 --- a/src/graphite.rs +++ b/src/graphite.rs @@ -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!{ 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(address: ADDR) -> error::Result> +pub fn to_graphite(address: ADDR) -> error::Result> 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(address: ADDR) -> error::Result> +pub fn to_buffered_graphite(address: ADDR) -> error::Result> 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>, buffered: bool) -> ControlScopeFn { +fn graphite_scope(socket: &Arc>, buffered: bool) -> WriteFn { let buf = ScopeBuffer { buffer: Arc::new(RwLock::new(String::new())), socket: socket.clone(), diff --git a/src/lib.rs b/src/lib.rs index 0b98474..50dcfc8 100644 --- a/src/lib.rs +++ b/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::*; diff --git a/src/macros.rs b/src/macros.rs index b6cc2cc..40bf447 100755 --- a/src/macros.rs +++ b/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 = $e.into(); } + lazy_static! { pub static ref $METRIC_ID: Metrics = $e.into(); } }; // delegated, public, some metrics (pub $METRIC_ID:ident = $e:expr => { $($REMAINING:tt)+ }) => { - lazy_static! { pub static ref $METRIC_ID: AppMetrics = $e.into(); } + lazy_static! { pub static ref $METRIC_ID: Metrics = $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 = $e.into(); } + lazy_static! { pub static ref $METRIC_ID: Metrics = $e.into(); } }; // delegated, module, some metrics ($METRIC_ID:ident = $e:expr => { $($REMAINING:tt)+ }) => { - lazy_static! { pub static ref $METRIC_ID: AppMetrics = $e.into(); } + lazy_static! { pub static ref $METRIC_ID: Metrics = $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 = $e.into(); } + lazy_static! { pub static ref UNIDENT_METRIC: Metrics = $e.into(); } __metrics_block!(UNIDENT_METRIC: Delegate; $($REMAINING)*); }; // delegated, root, some metrics ( => { $($REMAINING:tt)+ }) => { - lazy_static! { pub static ref ROOT_METRICS: AppMetrics = "".into(); } + lazy_static! { pub static ref ROOT_METRICS: Metrics = ().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!( TEST_METRICS = DIPSTICK_METRICS.with_prefix("test_prefix");); + metrics!( TEST_METRICS = DIPSTICK_METRICS.with_prefix("test_prefix");); app_marker!( TEST_METRICS => { M1: "failed", diff --git a/src/app_metrics.rs b/src/metrics.rs similarity index 72% rename from src/app_metrics.rs rename to src/metrics.rs index 4c650ca..87e818c 100644 --- a/src/app_metrics.rs +++ b/src/metrics.rs @@ -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(app_metrics: AM) -> AppMetrics +#[deprecated(since="0.7.0", note="Use metrics() instead")] +pub fn app_metrics(scope: AM) -> Metrics where M: Clone + Send + Sync + 'static, - AM: Into>, + AM: Into>, { - 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(scope: AM) -> Metrics + where + M: Clone + Send + Sync + 'static, + AM: Into>, +{ + scope.into() } /// A monotonic counter metric. @@ -34,13 +45,13 @@ where /// preventing programming errors. #[derive(Derivative)] #[derivative(Debug)] -pub struct AppMarker { +pub struct Marker { metric: M, #[derivative(Debug = "ignore")] - scope: ControlScopeFn, + scope: WriteFn, } -impl AppMarker { +impl Marker { /// Record a single event occurence. pub fn mark(&self) { self.scope.write(&self.metric, 1); @@ -50,13 +61,13 @@ impl AppMarker { /// A counter that sends values to the metrics backend #[derive(Derivative)] #[derivative(Debug)] -pub struct AppCounter { +pub struct Counter { metric: M, #[derivative(Debug = "ignore")] - scope: ControlScopeFn, + scope: WriteFn, } -impl AppCounter { +impl Counter { /// Record a value count. pub fn count(&self, count: V) { self.scope.write(&self.metric, count.to_u64().unwrap()); @@ -66,13 +77,13 @@ impl AppCounter { /// A gauge that sends values to the metrics backend #[derive(Derivative)] #[derivative(Debug)] -pub struct AppGauge { +pub struct Gauge { metric: M, #[derivative(Debug = "ignore")] - scope: ControlScopeFn, + scope: WriteFn, } -impl AppGauge { +impl Gauge { /// Record a value point for this gauge. pub fn value(&self, value: V) { self.scope.write(&self.metric, value.to_u64().unwrap()); @@ -87,13 +98,13 @@ impl AppGauge { /// - with the interval_us() method, providing an externally determined microsecond interval #[derive(Derivative)] #[derivative(Debug)] -pub struct AppTimer { +pub struct Timer { metric: M, #[derivative(Debug = "ignore")] - scope: ControlScopeFn, + scope: WriteFn, } -impl AppTimer { +impl Timer { /// 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(&self, interval_us: V) -> V { @@ -132,29 +143,47 @@ impl AppTimer { } } -//// AppMetrics proper +/// Help transition to new syntax +#[deprecated(since="0.7.0", note="Use Metrics instead")] +pub type AppMetrics = Metrics; + +/// Help transition to new syntax +#[deprecated(since="0.7.0", note="Use Marker instead")] +pub type AppMarker = Marker; + +/// Help transition to new syntax +#[deprecated(since="0.7.0", note="Use Counter instead")] +pub type AppCounter = Counter; + +/// Help transition to new syntax +#[deprecated(since="0.7.0", note="Use Gauge instead")] +pub type AppGauge = Gauge; + +/// Help transition to new syntax +#[deprecated(since="0.7.0", note="Use Timer instead")] +pub type AppTimer = Timer; + /// Variations of this should also provide control of the metric recording scope. #[derive(Derivative, Clone)] -#[derivative(Debug)] -pub struct AppMetrics { +pub struct Metrics { #[derivative(Debug = "ignore")] define_metric_fn: DefineMetricFn, #[derivative(Debug = "ignore")] - single_scope: ControlScopeFn, + single_scope: WriteFn, } -impl AppMetrics { +impl Metrics { /// Create new application metrics instance. - pub fn new(define_metric_fn: DefineMetricFn, scope: ControlScopeFn) -> Self { - AppMetrics { + pub fn new(define_metric_fn: DefineMetricFn, scope: WriteFn) -> Self { + Metrics { define_metric_fn, single_scope: scope, } } } -impl AppMetrics +impl Metrics 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>(&self, name: AS) -> AppMarker { + /// Define an event counter of the provided name. + pub fn marker>(&self, name: AS) -> Marker { 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>(&self, name: AS) -> AppCounter { + /// Define a counter of the provided name. + pub fn counter>(&self, name: AS) -> Counter { 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>(&self, name: AS) -> AppTimer { + /// Define a timer of the provided name. + pub fn timer>(&self, name: AS) -> Timer { 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>(&self, name: AS) -> AppGauge { + /// Define a gauge of the provided name. + pub fn gauge>(&self, name: AS) -> Gauge { 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 { +struct RecvMetricImpl { metric: M, - scope: ControlScopeFn, + scope: WriteFn, } -impl AppRecv for AppMetrics { - fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box { - let scope: ControlScopeFn = self.single_scope.clone(); +impl MetricsRecv for Metrics { + fn define_metric(&self, kind: Kind, name: &str, rate: Rate) -> Box { + let scope: WriteFn = 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 AppRecv for AppMetrics { } } -impl AppRecvMetric for AppRecvMetricImpl { +impl RecvMetric for RecvMetricImpl { fn write(&self, value: Value) { self.scope.write(&self.metric, value); } @@ -249,19 +277,19 @@ impl AppRecvMetric for AppRecvMetricImpl { //// Mutators impl -impl WithNamespace for AppMetrics { +impl WithNamespace for Metrics { fn with_name>(&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 WithCache for AppMetrics { +impl WithCache for Metrics { 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())); } diff --git a/src/multi.rs b/src/multi.rs index 4264422..010075d 100644 --- a/src/multi.rs +++ b/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 From<(LocalMetrics, LocalMetrics)> for AppMetrics<(M1, M2)> +impl From<(MetricContext, MetricContext)> for Metrics<(M1, M2)> where M1: 'static + Clone + Send + Sync, M2: 'static + Clone + Send + Sync, { - fn from(combo: (LocalMetrics, LocalMetrics)) -> AppMetrics<(M1, M2)> { + fn from(combo: (MetricContext, MetricContext)) -> 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]> for AppMetrics> +impl<'a, M> From<&'a [MetricContext]> for Metrics> where M: 'static + Clone + Send + Sync, { - fn from(chains: &'a [LocalMetrics]) -> AppMetrics> { - let scopes: Vec> = chains.iter().map(|x| x.open_scope()).collect(); + fn from(chains: &'a [MetricContext]) -> Metrics> { + let scopes: Vec> = 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() }), diff --git a/src/output.rs b/src/output.rs index c931408..9f1febc 100644 --- a/src/output.rs +++ b/src/output.rs @@ -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 { +pub fn to_stdout() -> MetricContext { metrics_context( |_kind, name, _rate| String::from(name), || control_scope(|cmd| @@ -19,7 +19,7 @@ pub fn to_stdout() -> LocalMetrics { /// 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 { +pub fn to_buffered_stdout() -> MetricContext { metrics_context( |_kind, name, _rate| String::from(name), || { @@ -42,7 +42,7 @@ pub fn to_buffered_stdout() -> LocalMetrics { /// Write metric values to the standard log using `info!`. // TODO parameterize log level -pub fn to_log() -> LocalMetrics { +pub fn to_log() -> MetricContext { metrics_context( |_kind, name, _rate| String::from(name), || control_scope(|cmd| @@ -57,7 +57,7 @@ pub fn to_log() -> LocalMetrics { /// 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 { +pub fn to_buffered_log() -> MetricContext { metrics_context( |_kind, name, _rate| String::from(name), || { @@ -80,7 +80,7 @@ pub fn to_buffered_log() -> LocalMetrics { /// 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| {}), diff --git a/src/publish.rs b/src/publish.rs index 4fbf4e2..748b96c 100644 --- a/src/publish.rs +++ b/src/publish.rs @@ -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 { #[derivative(Debug = "ignore")] statistics: Box, - output: LocalMetrics, + output: MetricContext, } impl Publisher @@ -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) -> Self { + pub fn new(stat_fn: E, output: MetricContext) -> Self { Publisher { statistics: Box::new(stat_fn), output, diff --git a/src/registry.rs b/src/registry.rs index 3d69c27..86294b0 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -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 { - let void_metrics: AppMetrics<_> = output::to_void().into(); +fn no_metrics() -> Arc { + 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 = no_app_metrics(); + static ref NO_RECV: Arc = no_metrics(); - static ref DEFAULT_APP_RECEIVER: RwLock> = RwLock::new(NO_APP_METRICS.clone()); + static ref DEFAULT_RECV: RwLock> = RwLock::new(NO_RECV.clone()); - static ref DELEGATE_REGISTRY: RwLock> = RwLock::new(vec![]); + static ref DELEGATE_REGISTRY: RwLock> = 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 { - DEFAULT_APP_RECEIVER.read().unwrap().clone() +pub fn get_default_metrics_recv() -> Arc { + DEFAULT_RECV.read().unwrap().clone() } /// Install a new receiver for all dispatched metrics, replacing any previous receiver. -pub fn send_app_metrics>, T: Send + Sync + Clone + 'static>( +pub fn send_metrics>, 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; } \ No newline at end of file diff --git a/src/sample.rs b/src/sample.rs index 847787f..d86909b 100644 --- a/src/sample.rs +++ b/src/sample.rs @@ -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 WithSamplingRate for LocalMetrics { +impl WithSamplingRate for MetricContext { fn with_sampling_rate(&self, sampling_rate: Rate) -> Self { let int_sampling_rate = pcg32::to_int_rate(sampling_rate); @@ -52,10 +52,10 @@ impl WithSamplingRate for LocalMetrics { /// Perform random sampling of values according to the specified rate. #[deprecated(since = "0.5.0", note = "Use `with_sampling_rate` instead.")] -pub fn sample(sampling_rate: Rate, chain: IC) -> LocalMetrics +pub fn sample(sampling_rate: Rate, chain: IC) -> MetricContext where M: Clone + Send + Sync + 'static, - IC: Into>, + IC: Into>, { let chain = chain.into(); chain.with_sampling_rate(sampling_rate) diff --git a/src/self_metrics.rs b/src/self_metrics.rs index 60ee3c5..74c4253 100644 --- a/src/self_metrics.rs +++ b/src/self_metrics.rs @@ -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!( DIPSTICK_METRICS = build_self_metrics();); +metrics!( DIPSTICK_METRICS = build_self_metrics();); fn build_aggregator() -> Aggregator { // TODO make publishable @@ -30,8 +30,8 @@ pub fn snapshot() -> Vec { vec![] } -fn build_self_metrics() -> AppMetrics { +fn build_self_metrics() -> Metrics { let mug: &Aggregator = &DIPSTICK_AGGREGATOR; - let am: AppMetrics = mug.clone().into(); + let am: Metrics = mug.clone().into(); am.with_prefix("dipstick") } diff --git a/src/statsd.rs b/src/statsd.rs index 99f71bd..c7d1556 100644 --- a/src/statsd.rs +++ b/src/statsd.rs @@ -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! { 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(address: ADDR) -> error::Result> +pub fn to_statsd(address: ADDR) -> error::Result> where ADDR: ToSocketAddrs, {