1use diem_infallible::{duration_since_epoch, Mutex};
9use once_cell::sync::Lazy;
10use serde::{Deserialize, Serialize};
11use serde_json::{self, value as json};
12use std::{collections::VecDeque, convert::TryInto};
13
14#[derive(Serialize, Deserialize, Clone)]
15pub struct JsonLogEntry {
16 pub name: String,
17 pub timestamp: u64,
18 pub json: json::Value,
19}
20
21const MAX_EVENTS_IN_QUEUE: usize = 10_000;
22
23#[macro_export]
28macro_rules! event {
29 ($name:expr, $($json:tt)*) => {
30 $crate::json_log::send_json_log($crate::json_log::JsonLogEntry::new(
31 $name,
32 serde_json::json!({$($json)+}),
33 ));
34 };
35}
36
37static JSON_LOG_ENTRY_QUEUE: Lazy<Mutex<VecDeque<JsonLogEntry>>> =
40 Lazy::new(|| Mutex::new(VecDeque::with_capacity(MAX_EVENTS_IN_QUEUE)));
41
42impl JsonLogEntry {
43 pub fn new(name: &'static str, json: json::Value) -> Self {
44 let timestamp = duration_since_epoch()
45 .as_millis()
46 .try_into()
47 .expect("Unable to convert u128 into u64");
48 JsonLogEntry {
49 name: name.into(),
50 timestamp,
51 json,
52 }
53 }
54}
55
56pub fn send_json_log(entry: JsonLogEntry) {
63 let mut queue = JSON_LOG_ENTRY_QUEUE.lock();
64 if queue.len() >= MAX_EVENTS_IN_QUEUE {
65 queue.pop_front();
66 }
67 queue.push_back(entry);
68}
69
70pub fn pop_last_entries() -> Vec<JsonLogEntry> {
72 let mut queue = JSON_LOG_ENTRY_QUEUE.lock();
73 queue.drain(..).collect()
74}