mirror of https://github.com/fralalonde/dipstick
Document observers in handbook
This commit is contained in:
parent
bb9b174d17
commit
6a205337e5
84
HANDBOOK.md
84
HANDBOOK.md
|
@ -57,48 +57,94 @@ Timer's internal precision is microseconds but can be scaled down on output.
|
|||
extern crate dipstick;
|
||||
use dipstick::*;
|
||||
fn main() {
|
||||
let app_metrics = Stream::to_stdout().metrics();
|
||||
let timer = app_metrics.timer("my_timer");
|
||||
time!(timer, {/* slow code here */} );
|
||||
timer.time(|| {/* slow code here */} );
|
||||
let metrics = Stream::to_stdout().metrics();
|
||||
let timer = metrics.timer("my_timer");
|
||||
|
||||
let start = timer.start();
|
||||
/* slow code here */
|
||||
timer.stop(start);
|
||||
// using macro
|
||||
time!(timer, {/* timed code here ... */} );
|
||||
|
||||
// using closure
|
||||
timer.time(|| {/* timed code here ... */} );
|
||||
|
||||
// using start/stop
|
||||
let handle = timer.start();
|
||||
/* timed code here ... */
|
||||
timer.stop(handle);
|
||||
|
||||
// directly reporting microseconds
|
||||
timer.interval_us(123_456);
|
||||
}
|
||||
```
|
||||
|
||||
### Level
|
||||
Relative quantity counter. Accepts positive and negative cumulative values.
|
||||
If aggregated, observed minimum and maximum track the sum of values rather than individual values as for `Counter`.
|
||||
A relative, cumulative quantity counter. Accepts positive and negative values.
|
||||
If aggregated, observed minimum and maximum track the _sum_ of values (as opposed to `Counter` min and max _individual_ values).
|
||||
|
||||
### Gauge
|
||||
An instant observation of a resource's value (positive or negative, but non-cumulative).
|
||||
The observation of Gauges is not automatic and must be performed programmatically as with other metric types.
|
||||
The observation of Gauges can be performed programmatically as with other metric types or
|
||||
it can be triggered automatically, either on schedule or upon flushing the scope:
|
||||
|
||||
````rust
|
||||
extern crate dipstick;
|
||||
use dipstick::*;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let metrics = Stream::to_stdout().metrics();
|
||||
let uptime = metrics.gauge("uptime");
|
||||
|
||||
// report gauge value programmatically
|
||||
uptime.value(2);
|
||||
|
||||
// observe a constant value before each flush
|
||||
let uptime = metrics.gauge("uptime");
|
||||
metrics.observe(uptime, || 6).on_flush();
|
||||
|
||||
// observe a function-provided value periodically
|
||||
metrics
|
||||
.observe(metrics.gauge("threads"), thread_count)
|
||||
.every(Duration::from_secs(1));
|
||||
}
|
||||
|
||||
fn thread_count() -> MetricValue {
|
||||
6
|
||||
}
|
||||
````
|
||||
|
||||
### Names
|
||||
Each metric must be given a name upon creation.
|
||||
Names are opaque to the application and are used only to identify the metrics upon output.
|
||||
|
||||
Names may be prepended with a namespace by each configured backend.
|
||||
Aggregated statistics may also append identifiers to the metric's name.
|
||||
|
||||
Names should exclude characters that can interfere with namespaces, separator and output protocols.
|
||||
A good convention is to stick with lowercase alphanumeric identifiers of less than 12 characters.
|
||||
Names may be prepended with a application-namespace shared across all backends.
|
||||
|
||||
```rust
|
||||
extern crate dipstick;
|
||||
use dipstick::*;
|
||||
fn main() {
|
||||
let app_metrics = Stream::to_stdout().metrics();
|
||||
let db_metrics = app_metrics.named("database");
|
||||
let _db_timer = db_metrics.timer("db_timer");
|
||||
let _db_counter = db_metrics.counter("db_counter");
|
||||
let metrics = Stream::to_stdout().metrics();
|
||||
|
||||
// plainly name "timer"
|
||||
let _timer = metrics.timer("timer");
|
||||
|
||||
// prepend namespace
|
||||
let db_metrics = metrics.named("database");
|
||||
|
||||
// qualified name will be "database.counter"
|
||||
let _db_counter = db_metrics.counter("counter");
|
||||
}
|
||||
```
|
||||
|
||||
Names may be prepended with a namespace by each configured backend.
|
||||
For example, the same metric `request.success` could appear under different qualified names:
|
||||
- logging as `app_module.request.success`
|
||||
- statsd as `environment.hostname.pid.module.request.success`
|
||||
|
||||
Aggregation statistics may also append identifiers to the metric's name, such as `counter_mean` or `marker_rate`.
|
||||
|
||||
Names should exclude characters that can interfere with namespaces, separator and output protocols.
|
||||
A good convention is to stick with lowercase alphanumeric identifiers of less than 12 characters.
|
||||
|
||||
|
||||
### Labels
|
||||
|
||||
|
|
|
@ -20,16 +20,15 @@ use std::time::Duration;
|
|||
use dipstick::*;
|
||||
|
||||
fn main() {
|
||||
let mut metrics = AtomicBucket::new().named("process");
|
||||
let metrics = AtomicBucket::new().named("process");
|
||||
metrics.drain(Stream::to_stdout());
|
||||
metrics.flush_every(Duration::from_secs(3));
|
||||
|
||||
let uptime = metrics.gauge("uptime");
|
||||
metrics.observe(uptime, || 6).on_flush();
|
||||
|
||||
let threads = metrics.gauge("threads");
|
||||
metrics
|
||||
.observe(threads, thread_count)
|
||||
.observe(metrics.gauge("threads"), thread_count)
|
||||
.every(Duration::from_secs(1));
|
||||
|
||||
loop {
|
||||
|
|
|
@ -113,7 +113,7 @@ where
|
|||
}
|
||||
|
||||
pub struct ObserveWhen<'a, T, F> {
|
||||
target: &'a mut T,
|
||||
target: &'a T,
|
||||
gauge: Gauge,
|
||||
operation: Arc<F>,
|
||||
}
|
||||
|
@ -123,34 +123,35 @@ where
|
|||
F: Fn() -> MetricValue + Send + Sync + 'static,
|
||||
T: InputScope + WithAttributes + Send + Sync,
|
||||
{
|
||||
/// Observe the metric's value upon flushing the scope.
|
||||
pub fn on_flush(self) {
|
||||
let gauge = self.gauge;
|
||||
let op = self.operation;
|
||||
write_lock!(self.target.mut_attributes().flush_listeners)
|
||||
write_lock!(self.target.get_attributes().flush_listeners)
|
||||
.push(Arc::new(move || gauge.value(op())));
|
||||
}
|
||||
|
||||
/// Observe the metric's value periodically.
|
||||
pub fn every(self, period: Duration) -> CancelHandle {
|
||||
let gauge = self.gauge;
|
||||
let op = self.operation;
|
||||
let handle = SCHEDULER.schedule(period, move || gauge.value(op()));
|
||||
write_lock!(self.target.mut_attributes().tasks).push(handle.clone());
|
||||
write_lock!(self.target.get_attributes().tasks).push(handle.clone());
|
||||
handle
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedule a recurring task
|
||||
pub trait Observe {
|
||||
/// Schedule a recurring task.
|
||||
/// The returned handle can be used to cancel the task.
|
||||
fn observe<F>(&mut self, gauge: Gauge, operation: F) -> ObserveWhen<Self, F>
|
||||
/// Provide a source for a metric's values.
|
||||
fn observe<F>(&self, gauge: Gauge, operation: F) -> ObserveWhen<Self, F>
|
||||
where
|
||||
F: Fn() -> MetricValue + Send + Sync + 'static,
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<T: InputScope + WithAttributes> Observe for T {
|
||||
fn observe<F>(&mut self, gauge: Gauge, operation: F) -> ObserveWhen<Self, F>
|
||||
fn observe<F>(&self, gauge: Gauge, operation: F) -> ObserveWhen<Self, F>
|
||||
where
|
||||
F: Fn() -> MetricValue + Send + Sync + 'static,
|
||||
Self: Sized,
|
||||
|
@ -284,7 +285,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn on_flush() {
|
||||
let mut metrics: StatsMapScope = StatsMap::default().metrics();
|
||||
let metrics: StatsMapScope = StatsMap::default().metrics();
|
||||
let gauge = metrics.gauge("my_gauge");
|
||||
metrics.observe(gauge, || 4).on_flush();
|
||||
metrics.flush().unwrap();
|
||||
|
|
Loading…
Reference in New Issue