metrix/instruments/switches/
flag.rs

1use crate::instruments::{
2    AcceptAllLabels, Instrument, InstrumentAdapter, LabelFilter, LabelPredicate, Update, Updates,
3};
4use crate::snapshot::Snapshot;
5use crate::util;
6use crate::{Descriptive, ObservedValue, PutsSnapshot};
7
8use super::NameAlternation;
9
10/// A `Flag` which can have the states `true` or `false`
11///
12/// The `Flag` reacts on observations with values. A value
13/// of `0` sets the `Flag` to `false`, '1' will set the
14/// `Flag` to `true`. For all other values the behaviour is undefined.
15pub struct Flag {
16    name: String,
17    title: Option<String>,
18    description: Option<String>,
19    state: Option<bool>,
20    show_inverted: Option<NameAlternation>,
21}
22
23impl Flag {
24    pub fn new<T: Into<String>>(name: T) -> Self {
25        Self {
26            name: name.into(),
27            title: None,
28            description: None,
29            state: None,
30            show_inverted: None,
31        }
32    }
33
34    pub fn new_with_state<T: Into<String>>(name: T, initial_state: bool) -> Self {
35        Self::new(name).state(initial_state)
36    }
37
38    pub fn get_name(&self) -> &str {
39        &self.name
40    }
41
42    pub fn set_name<T: Into<String>>(&mut self, name: T) {
43        self.name = name.into();
44    }
45
46    pub fn name<T: Into<String>>(mut self, name: T) -> Self {
47        self.set_name(name);
48        self
49    }
50
51    pub fn set_title<T: Into<String>>(&mut self, title: T) {
52        self.title = Some(title.into())
53    }
54
55    pub fn title<T: Into<String>>(mut self, title: T) -> Self {
56        self.set_title(title);
57        self
58    }
59
60    pub fn set_description<T: Into<String>>(&mut self, description: T) {
61        self.description = Some(description.into())
62    }
63
64    pub fn description<T: Into<String>>(mut self, description: T) -> Self {
65        self.set_description(description);
66        self
67    }
68
69    pub fn state(mut self, initial_state: bool) -> Self {
70        self.state = Some(initial_state);
71        self
72    }
73
74    /// Show the inverted value. Name will be adjusted with `name_alternation`.
75    pub fn set_show_inverted(&mut self, name_alternation: NameAlternation) {
76        self.show_inverted = Some(name_alternation)
77    }
78
79    /// Show the inverted value. Name will be adjusted with `name_alternation`.
80    pub fn show_inverted(mut self, name_alternation: NameAlternation) -> Self {
81        self.set_show_inverted(name_alternation);
82        self
83    }
84
85    /// Show the inverted value. Name will be prefixed with `prefix`.
86    pub fn set_show_inverted_prefixed<T: Into<String>>(&mut self, prefix: T) {
87        self.set_show_inverted(NameAlternation::Prefix(prefix.into()))
88    }
89
90    /// Show the inverted value. Name will be prefixed with `prefix`.
91    pub fn show_inverted_prefixed<T: Into<String>>(mut self, prefix: T) -> Self {
92        self.set_show_inverted(NameAlternation::Prefix(prefix.into()));
93        self
94    }
95
96    /// Show the inverted value. Name will be postfixed with `postfix`.
97    pub fn set_show_inverted_postfixed<T: Into<String>>(&mut self, postfix: T) {
98        self.set_show_inverted(NameAlternation::Postfix(postfix.into()))
99    }
100
101    /// Show the inverted value. Name will be postfixed with `postfix`.
102    pub fn show_inverted_postfixed<T: Into<String>>(mut self, postfix: T) -> Self {
103        self.set_show_inverted(NameAlternation::Postfix(postfix.into()));
104        self
105    }
106
107    /// Show the inverted value. Name will be renamed with `new_name`.
108    pub fn set_show_inverted_renamed<T: Into<String>>(&mut self, new_name: T) {
109        self.set_show_inverted(NameAlternation::Rename(new_name.into()))
110    }
111
112    /// Show the inverted value. Name will be renamed with `new_name`.
113    pub fn show_inverted_renamed<T: Into<String>>(mut self, new_name: T) -> Self {
114        self.set_show_inverted(NameAlternation::Rename(new_name.into()));
115        self
116    }
117
118    pub fn accept<L: Eq + Send + 'static, F: Into<LabelFilter<L>>>(
119        self,
120        accept: F,
121    ) -> InstrumentAdapter<L, Self> {
122        InstrumentAdapter::accept(accept, self)
123    }
124
125    /// Creates an `InstrumentAdapter` that makes this instrument
126    /// react on observations on the given label.
127    pub fn for_label<L: Eq + Send + 'static>(self, label: L) -> InstrumentAdapter<L, Self> {
128        self.accept(label)
129    }
130
131    /// Creates an `InstrumentAdapter` that makes this instrument
132    /// react on observations with the given labels.
133    ///
134    /// If `labels` is empty the instrument will not react to any observations
135    pub fn for_labels<L: Eq + Send + 'static>(self, labels: Vec<L>) -> InstrumentAdapter<L, Self> {
136        self.accept(labels)
137    }
138
139    /// Creates an `InstrumentAdapter` that makes this instrument react on
140    /// all observations.
141    pub fn for_all_labels<L: Eq + Send + 'static>(self) -> InstrumentAdapter<L, Self> {
142        self.accept(AcceptAllLabels)
143    }
144
145    /// Creates an `InstrumentAdapter` that makes this instrument react on
146    /// observations with labels specified by the predicate.
147    pub fn for_labels_by_predicate<L, P>(self, label_predicate: P) -> InstrumentAdapter<L, Self>
148    where
149        L: Eq + Send + 'static,
150        P: Fn(&L) -> bool + Send + 'static,
151    {
152        self.accept(LabelPredicate(label_predicate))
153    }
154
155    /// Creates an `InstrumentAdapter` that makes this instrument to no
156    /// observations.
157    pub fn adapter<L: Eq + Send + 'static>(self) -> InstrumentAdapter<L, Self> {
158        InstrumentAdapter::deaf(self)
159    }
160
161    /// Returns the current state
162    pub fn get_state(&self) -> Option<bool> {
163        self.state
164    }
165}
166
167impl Instrument for Flag {}
168
169impl PutsSnapshot for Flag {
170    fn put_snapshot(&self, into: &mut Snapshot, descriptive: bool) {
171        util::put_postfixed_descriptives(self, &self.name, into, descriptive);
172
173        if let Some(state) = self.state {
174            into.items.push((self.name.clone(), state.into()));
175            if let Some(alternation) = &self.show_inverted {
176                let label = alternation.adjust_name(&self.name);
177                into.items.push((label.into(), (!state).into()));
178            }
179        }
180    }
181}
182
183impl Updates for Flag {
184    fn update(&mut self, with: &Update) -> usize {
185        match *with {
186            Update::ObservationWithValue(ObservedValue::Bool(v), _) => {
187                self.state = Some(v);
188                1
189            }
190            Update::ObservationWithValue(ObservedValue::SignedInteger(v), _) => {
191                self.state = Some(v != 0);
192                1
193            }
194            Update::ObservationWithValue(ObservedValue::UnsignedInteger(v), _) => {
195                self.state = Some(v != 0);
196                1
197            }
198            _ => 0,
199        }
200    }
201}
202
203impl Descriptive for Flag {
204    fn title(&self) -> Option<&str> {
205        self.title.as_deref()
206    }
207
208    fn description(&self) -> Option<&str> {
209        self.description.as_deref()
210    }
211}