aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-08-01 03:09:52 +0100
committerAleksey Kladov <[email protected]>2020-08-01 03:09:52 +0100
commita015714defd19298632819885679fc6fdd6ea07c (patch)
tree6459f29f52c140094cd1fec857ee7b76a40d6c6b
parent2346a28c638dc8fe945059b68126d268dd7fb690 (diff)
Better JSON serialization in metrics
-rw-r--r--Cargo.lock7
-rw-r--r--xtask/Cargo.toml1
-rw-r--r--xtask/src/metrics.rs132
3 files changed, 22 insertions, 118 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 234c31406..c974022a2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1832,6 +1832,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1832checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1832checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1833 1833
1834[[package]] 1834[[package]]
1835name = "write-json"
1836version = "0.1.0"
1837source = "registry+https://github.com/rust-lang/crates.io-index"
1838checksum = "8b3f9a784c809a99e38d2e825907617cb03bd880d5421153bc4548e9317f59d0"
1839
1840[[package]]
1835name = "ws2_32-sys" 1841name = "ws2_32-sys"
1836version = "0.2.1" 1842version = "0.2.1"
1837source = "registry+https://github.com/rust-lang/crates.io-index" 1843source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1852,4 +1858,5 @@ dependencies = [
1852 "quote", 1858 "quote",
1853 "ungrammar", 1859 "ungrammar",
1854 "walkdir", 1860 "walkdir",
1861 "write-json",
1855] 1862]
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 8140da87f..72a2ae26b 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -17,3 +17,4 @@ proc-macro2 = "1.0.8"
17quote = "1.0.2" 17quote = "1.0.2"
18ungrammar = "0.1.0" 18ungrammar = "0.1.0"
19walkdir = "2.3.1" 19walkdir = "2.3.1"
20write-json = "0.1.0"
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 @@
1use std::{ 1use 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
208struct State {
209 obj: bool,
210 first: bool,
211}
212
213#[derive(Default)]
214struct Json {
215 stack: Vec<State>,
216 buf: String,
217}
218
219impl 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
275impl fmt::Display for Json {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 write!(f, "{}", self.buf)
278 } 174 }
279} 175}