Formatting trait

This commit is contained in:
Francis Lalonde 2018-10-18 08:54:41 -04:00
parent 5e9aebbb22
commit 40bef5115c
3 changed files with 29 additions and 58 deletions

View File

@ -5,9 +5,7 @@ extern crate dipstick;
use std::thread::sleep;
use std::time::Duration;
use dipstick::{Proxy, Stream, Counter, Marker, InputScope, QueuedOutput, Input, SimpleFormat, Formatting, AppLabel};
use std::io;
use std::thread;
use dipstick::{Proxy, Stream, Counter, InputScope, Input, SimpleFormat, Formatting, AppLabel};
metrics!{
COUNTER: Counter = "counter_a";
@ -16,6 +14,7 @@ metrics!{
fn main() {
Proxy::set_default_target(
Stream::stderr().formatting(SimpleFormat::default()).input());
AppLabel::set("abc", "xyz");
loop {
// report some metric values from our "application" loop

View File

@ -62,91 +62,61 @@ thread_local! {
static THREAD_LABELS: RefCell<LabelScope> = RefCell::new(LabelScope::default());
}
///// Scopes to which metric labels can be attached.
//#[derive(Debug, Clone, Copy)]
//pub enum LabelContext {
//
// #[cfg(feature="tokio")]
// /// Handle metric labels for the current tokio "task".
// /// Serves the same purpose as thread scope when using shared-thread async frameworks.
// TASK,
//
// /// Scope local to this single metric value.
// /// Labels are passed explicitly by the calling code.
// /// Value scope labels have the highest lookup priority and will override any value specified
// /// in lower scopes.
// VALUE,
//}
pub trait LabelContext {
/// Retrieve a value for the scope.
fn get(key: &str) -> Option<Arc<String>>;
/// Set a new value for the scope.
/// Replaces any previous value for the key.
fn set(key: String, value: String);
/// Unset a value for the scope.
/// Has no effect if key was not set.
fn unset(key: &str);
/// Freeze the current label values for usage at later time.
fn export() -> LabelScope;
}
/// Handle metric labels for the current thread.
/// App scope labels have the lowest lookup priority and serve as a fallback to other scopes.
pub struct ThreadLabel;
impl LabelContext for ThreadLabel {
fn get(key: &str) -> Option<Arc<String>> {
impl ThreadLabel {
/// Retrieve a value from the thread scope.
pub fn get(key: &str) -> Option<Arc<String>> {
THREAD_LABELS.with(|map| map.borrow().get(key))
}
fn set(key: String, value: String) {
let lab_val = Arc::new(value);
/// Set a new value for the thread scope.
/// Replaces any previous value for the key.
pub fn set<S: Into<String>>(key: S, value: S) {
THREAD_LABELS.with(|map| {
let new = { map.borrow().set(key, lab_val) };
let new = { map.borrow().set(key.into(), Arc::new(value.into())) };
*map.borrow_mut() = new;
});
}
fn unset(key: &str) {
/// Unset a value for the app scope.
/// Has no effect if key was not set.
pub fn unset(key: &str) {
THREAD_LABELS.with(|map| {
let new = { map.borrow().unset(key) };
*map.borrow_mut() = new;
});
}
fn export() -> LabelScope {
THREAD_LABELS.with(|map| map.borrow().clone())
}
}
/// Handle metric labels for the whole application (globals).
/// App scope labels have the lowest lookup priority and serve as a fallback to other scopes.
pub struct AppLabel;
impl LabelContext for AppLabel {
fn get(key: &str) -> Option<Arc<String>> {
impl AppLabel {
/// Retrieve a value from the app scope.
pub fn get(key: &str) -> Option<Arc<String>> {
APP_LABELS.read().expect("Global Labels").get(key)
}
fn set(key: String, value: String) {
let b = { APP_LABELS.read().expect("Global Labels").set(key, Arc::new(value)) };
/// Set a new value for the app scope.
/// Replaces any previous value for the key.
pub fn set<S: Into<String>>(key: S, value: S) {
let b = { APP_LABELS.read().expect("Global Labels").set(key.into(), Arc::new(value.into())) };
*APP_LABELS.write().expect("Global Labels") = b;
}
fn unset(key: &str) {
/// Unset a value for the app scope.
/// Has no effect if key was not set.
pub fn unset(key: &str) {
let b = { APP_LABELS.read().expect("Global Labels").unset(key) };
*APP_LABELS.write().expect("Global Labels") = b;
}
fn export() -> LabelScope {
APP_LABELS.read().expect("Global Labels").clone()
}
}
/// Base structure to carry metric labels from the application to the metric backend(s).
/// Can carry both one-off labels and exported context labels (if async metrics are enabled).
/// Used in applications through the labels!() macro.
@ -178,8 +148,8 @@ impl Labels {
/// Used to save metric context before enqueuing value for async output.
pub fn save_context(&mut self) {
self.scopes.push(ThreadLabel::export());
self.scopes.push(AppLabel::export());
self.scopes.push(THREAD_LABELS.with(|map| map.borrow().clone()));
self.scopes.push(APP_LABELS.read().expect("Global Labels").clone());
}
/// Generic label lookup function.
@ -193,12 +163,15 @@ impl Labels {
match self.scopes.len() {
// no value labels, no saved context labels
// just lookup implicit context
0 => lookup_current_context(key),
// some value labels, no saved context labels
// lookup value label, then lookup implicit context
1 => self.scopes[0].get(key).or_else(|| lookup_current_context(key)),
// some context labels
// value + saved context labels
// lookup explicit context in turn
_ => {
for src in &self.scopes {
if let Some(label_value) = src.get(key) {

View File

@ -101,7 +101,6 @@ impl LineFormat for SimpleFormat {
]
}
}
}