diff options
author | Aleksey Kladov <[email protected]> | 2020-08-01 03:09:52 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-08-01 03:09:52 +0100 |
commit | a015714defd19298632819885679fc6fdd6ea07c (patch) | |
tree | 6459f29f52c140094cd1fec857ee7b76a40d6c6b /xtask/src | |
parent | 2346a28c638dc8fe945059b68126d268dd7fb690 (diff) |
Better JSON serialization in metrics
Diffstat (limited to 'xtask/src')
-rw-r--r-- | xtask/src/metrics.rs | 132 |
1 files changed, 14 insertions, 118 deletions
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 9ac3fa51d..4bade2c7e 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | collections::BTreeMap, | 2 | collections::BTreeMap, |
3 | env, | 3 | env, |
4 | fmt::{self, Write as _}, | ||
5 | io::Write as _, | 4 | io::Write as _, |
6 | path::Path, | 5 | path::Path, |
7 | time::{Instant, SystemTime, UNIX_EPOCH}, | 6 | time::{Instant, SystemTime, UNIX_EPOCH}, |
@@ -127,40 +126,21 @@ impl Metrics { | |||
127 | self.metrics.insert(name.into(), (value, unit)); | 126 | self.metrics.insert(name.into(), (value, unit)); |
128 | } | 127 | } |
129 | 128 | ||
130 | fn json(&self) -> Json { | 129 | fn json(&self) -> String { |
131 | let mut json = Json::default(); | 130 | let mut buf = String::new(); |
132 | self.to_json(&mut json); | 131 | self.to_json(write_json::object(&mut buf)); |
133 | json | 132 | buf |
134 | } | 133 | } |
135 | fn to_json(&self, json: &mut Json) { | ||
136 | json.begin_object(); | ||
137 | { | ||
138 | json.field("host"); | ||
139 | self.host.to_json(json); | ||
140 | |||
141 | json.field("timestamp"); | ||
142 | let timestamp = self.timestamp.duration_since(UNIX_EPOCH).unwrap(); | ||
143 | json.number(timestamp.as_secs() as f64); | ||
144 | 134 | ||
145 | json.field("revision"); | 135 | fn to_json(&self, mut obj: write_json::Object<'_>) { |
146 | json.string(&self.revision); | 136 | self.host.to_json(obj.object("host")); |
147 | 137 | let timestamp = self.timestamp.duration_since(UNIX_EPOCH).unwrap(); | |
148 | json.field("metrics"); | 138 | obj.number("timestamp", timestamp.as_secs() as f64); |
149 | json.begin_object(); | 139 | obj.string("revision", &self.revision); |
150 | { | 140 | let mut metrics = obj.object("metrics"); |
151 | for (k, (value, unit)) in &self.metrics { | 141 | for (k, (value, unit)) in &self.metrics { |
152 | json.field(k); | 142 | metrics.array(k).number(*value as f64).string(unit); |
153 | json.begin_array(); | ||
154 | { | ||
155 | json.number(*value as f64); | ||
156 | json.string(unit); | ||
157 | } | ||
158 | json.end_array(); | ||
159 | } | ||
160 | } | ||
161 | json.end_object() | ||
162 | } | 143 | } |
163 | json.end_object(); | ||
164 | } | 144 | } |
165 | } | 145 | } |
166 | 146 | ||
@@ -189,91 +169,7 @@ impl Host { | |||
189 | Ok(line[field.len()..].trim().to_string()) | 169 | Ok(line[field.len()..].trim().to_string()) |
190 | } | 170 | } |
191 | } | 171 | } |
192 | fn to_json(&self, json: &mut Json) { | 172 | fn to_json(&self, mut obj: write_json::Object<'_>) { |
193 | json.begin_object(); | 173 | obj.string("os", &self.os).string("cpu", &self.cpu).string("mem", &self.mem); |
194 | { | ||
195 | json.field("os"); | ||
196 | json.string(&self.os); | ||
197 | |||
198 | json.field("cpu"); | ||
199 | json.string(&self.cpu); | ||
200 | |||
201 | json.field("mem"); | ||
202 | json.string(&self.mem); | ||
203 | } | ||
204 | json.end_object(); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | struct State { | ||
209 | obj: bool, | ||
210 | first: bool, | ||
211 | } | ||
212 | |||
213 | #[derive(Default)] | ||
214 | struct Json { | ||
215 | stack: Vec<State>, | ||
216 | buf: String, | ||
217 | } | ||
218 | |||
219 | impl Json { | ||
220 | fn begin_object(&mut self) { | ||
221 | self.stack.push(State { obj: true, first: true }); | ||
222 | self.buf.push('{'); | ||
223 | } | ||
224 | fn end_object(&mut self) { | ||
225 | self.stack.pop(); | ||
226 | self.buf.push('}') | ||
227 | } | ||
228 | fn begin_array(&mut self) { | ||
229 | self.stack.push(State { obj: false, first: true }); | ||
230 | self.buf.push('['); | ||
231 | } | ||
232 | fn end_array(&mut self) { | ||
233 | self.stack.pop(); | ||
234 | self.buf.push(']') | ||
235 | } | ||
236 | fn field(&mut self, name: &str) { | ||
237 | self.object_comma(); | ||
238 | self.string_token(name); | ||
239 | self.buf.push(':'); | ||
240 | } | ||
241 | fn string(&mut self, value: &str) { | ||
242 | self.array_comma(); | ||
243 | self.string_token(value); | ||
244 | } | ||
245 | fn string_token(&mut self, value: &str) { | ||
246 | self.buf.push('"'); | ||
247 | self.buf.extend(value.escape_default()); | ||
248 | self.buf.push('"'); | ||
249 | } | ||
250 | fn number(&mut self, value: f64) { | ||
251 | self.array_comma(); | ||
252 | write!(self.buf, "{}", value).unwrap(); | ||
253 | } | ||
254 | |||
255 | fn array_comma(&mut self) { | ||
256 | let state = self.stack.last_mut().unwrap(); | ||
257 | if state.obj { | ||
258 | return; | ||
259 | } | ||
260 | if !state.first { | ||
261 | self.buf.push(','); | ||
262 | } | ||
263 | state.first = false; | ||
264 | } | ||
265 | |||
266 | fn object_comma(&mut self) { | ||
267 | let state = self.stack.last_mut().unwrap(); | ||
268 | if !state.first { | ||
269 | self.buf.push(','); | ||
270 | } | ||
271 | state.first = false; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | impl fmt::Display for Json { | ||
276 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
277 | write!(f, "{}", self.buf) | ||
278 | } | 174 | } |
279 | } | 175 | } |