scouter_types/queue/
types.rs1use crate::ProfileFuncs;
2use pyo3::prelude::*;
3
4use crate::error::TypeError;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::fmt;
8use std::fmt::Display;
9use std::fmt::Formatter;
10
11#[pyclass]
12#[derive(Clone, Debug, Serialize)]
13pub enum EntityType {
14 Feature,
15 Metric,
16}
17
18#[pyclass]
19#[derive(Clone, Serialize, Deserialize, Debug)]
20pub struct IntFeature {
21 pub name: String,
22 pub value: i64,
23}
24
25#[pymethods]
26impl IntFeature {
27 pub fn __str__(&self) -> String {
28 ProfileFuncs::__str__(self)
29 }
30}
31
32impl IntFeature {
33 pub fn to_float(&self) -> f64 {
34 self.value as f64
35 }
36}
37
38#[pyclass]
39#[derive(Clone, Serialize, Deserialize, Debug)]
40pub struct FloatFeature {
41 pub name: String,
42 pub value: f64,
43}
44
45#[pymethods]
46impl FloatFeature {
47 pub fn __str__(&self) -> String {
48 ProfileFuncs::__str__(self)
49 }
50}
51
52#[pyclass]
53#[derive(Clone, Serialize, Deserialize, Debug)]
54pub struct StringFeature {
55 pub name: String,
56 pub value: String,
57}
58
59#[pymethods]
60impl StringFeature {
61 pub fn __str__(&self) -> String {
62 ProfileFuncs::__str__(self)
63 }
64}
65
66impl StringFeature {
67 pub fn to_float(&self, feature_map: &FeatureMap) -> Result<f64, TypeError> {
68 feature_map
69 .features
70 .get(&self.name)
71 .and_then(|feat_map| {
72 feat_map
73 .get(&self.value)
74 .or_else(|| feat_map.get("missing"))
75 })
76 .map(|&val| val as f64)
77 .ok_or(TypeError::MissingStringValueError)
78 }
79}
80
81#[pyclass]
82#[derive(Clone, Serialize, Deserialize, Debug)]
83pub enum Feature {
84 Int(IntFeature),
85 Float(FloatFeature),
86 String(StringFeature),
87}
88
89#[pymethods]
90impl Feature {
91 #[staticmethod]
92 pub fn int(name: String, value: i64) -> Self {
93 Feature::Int(IntFeature { name, value })
94 }
95
96 #[staticmethod]
97 pub fn float(name: String, value: f64) -> Self {
98 Feature::Float(FloatFeature { name, value })
99 }
100
101 #[staticmethod]
102 pub fn string(name: String, value: String) -> Self {
103 Feature::String(StringFeature { name, value })
104 }
105
106 pub fn __str__(&self) -> String {
107 ProfileFuncs::__str__(self)
108 }
109}
110
111impl Feature {
112 pub fn to_float(&self, feature_map: &FeatureMap) -> Result<f64, TypeError> {
113 match self {
114 Feature::Int(feature) => Ok(feature.to_float()),
115 Feature::Float(feature) => Ok(feature.value),
116 Feature::String(feature) => feature.to_float(feature_map),
117 }
118 }
119
120 pub fn name(&self) -> &str {
121 match self {
122 Feature::Int(feature) => &feature.name,
123 Feature::Float(feature) => &feature.name,
124 Feature::String(feature) => &feature.name,
125 }
126 }
127}
128
129impl Display for Feature {
130 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
131 match self {
132 Feature::Int(feature) => write!(f, "{}", feature.value),
133 Feature::Float(feature) => write!(f, "{}", feature.value),
134 Feature::String(feature) => write!(f, "{}", feature.value),
135 }
136 }
137}
138
139#[pyclass]
140#[derive(Clone, Debug, Serialize)]
141pub struct Features {
142 #[pyo3(get)]
143 pub features: Vec<Feature>,
144
145 #[pyo3(get)]
146 pub entity_type: EntityType,
147}
148
149#[pymethods]
150impl Features {
151 #[new]
152 pub fn new(features: Vec<Feature>) -> Self {
153 Features {
154 features,
155 entity_type: EntityType::Feature,
156 }
157 }
158
159 pub fn __str__(&self) -> String {
160 ProfileFuncs::__str__(self)
161 }
162}
163
164impl Features {
165 pub fn iter(&self) -> std::slice::Iter<'_, Feature> {
166 self.features.iter()
167 }
168}
169
170#[pyclass]
171#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
172pub struct FeatureMap {
173 #[pyo3(get)]
174 pub features: HashMap<String, HashMap<String, usize>>,
175}
176
177#[pymethods]
178impl FeatureMap {
179 pub fn __str__(&self) -> String {
180 ProfileFuncs::__str__(self)
182 }
183}
184
185#[pyclass]
186#[derive(Clone, Serialize, Debug)]
187pub struct Metric {
188 pub name: String,
189 pub value: f64,
190}
191
192#[pymethods]
193impl Metric {
194 #[new]
195 pub fn new(name: String, value: f64) -> Self {
196 Metric { name, value }
197 }
198 pub fn __str__(&self) -> String {
199 ProfileFuncs::__str__(self)
200 }
201}
202
203#[pyclass]
204#[derive(Clone, Serialize, Debug)]
205pub struct Metrics {
206 #[pyo3(get)]
207 pub metrics: Vec<Metric>,
208
209 #[pyo3(get)]
210 pub entity_type: EntityType,
211}
212
213#[pymethods]
214impl Metrics {
215 #[new]
216 pub fn new(metrics: Vec<Metric>) -> Self {
217 Metrics {
218 metrics,
219 entity_type: EntityType::Metric,
220 }
221 }
222 pub fn __str__(&self) -> String {
223 ProfileFuncs::__str__(self)
224 }
225}
226
227impl Metrics {
228 pub fn iter(&self) -> std::slice::Iter<'_, Metric> {
229 self.metrics.iter()
230 }
231}
232
233#[derive(Debug)]
234pub enum QueueItem {
235 Features(Features),
236 Metrics(Metrics),
237}
238
239impl QueueItem {
240 pub fn from_py_entity(entity: &Bound<'_, PyAny>) -> Result<Self, TypeError> {
242 let entity_type = entity.getattr("entity_type")?.extract::<EntityType>()?;
243
244 match entity_type {
245 EntityType::Feature => {
246 let features = entity.extract::<Features>()?;
247 Ok(QueueItem::Features(features))
248 }
249 EntityType::Metric => {
250 let metrics = entity.extract::<Metrics>()?;
251 Ok(QueueItem::Metrics(metrics))
252 }
253 }
254 }
255}
256
257pub trait QueueExt: Send + Sync {
258 fn metrics(&self) -> &Vec<Metric>;
259 fn features(&self) -> &Vec<Feature>;
260}
261
262impl QueueExt for Features {
263 fn metrics(&self) -> &Vec<Metric> {
264 static EMPTY: Vec<Metric> = Vec::new();
267 &EMPTY
268 }
269
270 fn features(&self) -> &Vec<Feature> {
271 &self.features
272 }
273}
274
275impl QueueExt for Metrics {
276 fn metrics(&self) -> &Vec<Metric> {
277 &self.metrics
278 }
279
280 fn features(&self) -> &Vec<Feature> {
281 static EMPTY: Vec<Feature> = Vec::new();
284 &EMPTY
285 }
286}