2020-06-06 10:18:28 -07:00
|
|
|
use std::cell::RefCell;
|
|
|
|
|
2020-11-23 14:06:00 -08:00
|
|
|
const LOG_MESSAGES_BYTES_LIMIT: usize = 10 * 1000;
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
struct LogCollectorInner {
|
|
|
|
messages: Vec<String>,
|
|
|
|
bytes_written: usize,
|
|
|
|
limit_warning: bool,
|
|
|
|
}
|
|
|
|
|
2020-06-06 10:18:28 -07:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct LogCollector {
|
2020-11-23 14:06:00 -08:00
|
|
|
inner: RefCell<LogCollectorInner>,
|
2020-06-06 10:18:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LogCollector {
|
|
|
|
pub fn log(&self, message: &str) {
|
2020-11-23 14:06:00 -08:00
|
|
|
let mut inner = self.inner.borrow_mut();
|
|
|
|
|
|
|
|
if inner.bytes_written + message.len() >= LOG_MESSAGES_BYTES_LIMIT {
|
|
|
|
if !inner.limit_warning {
|
|
|
|
inner.limit_warning = true;
|
|
|
|
inner.messages.push(String::from("Log truncated"));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
inner.bytes_written += message.len();
|
|
|
|
inner.messages.push(message.to_string());
|
|
|
|
}
|
2020-06-06 10:18:28 -07:00
|
|
|
}
|
2020-06-13 13:20:08 -07:00
|
|
|
}
|
2020-10-08 12:06:15 -07:00
|
|
|
|
2021-01-23 11:55:15 -08:00
|
|
|
impl From<LogCollector> for Vec<String> {
|
|
|
|
fn from(log_collector: LogCollector) -> Self {
|
|
|
|
log_collector.inner.into_inner().messages
|
2020-11-23 14:06:00 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub(crate) mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_log_messages_bytes_limit() {
|
|
|
|
let lc = LogCollector::default();
|
|
|
|
|
|
|
|
for _i in 0..LOG_MESSAGES_BYTES_LIMIT * 2 {
|
|
|
|
lc.log("x");
|
|
|
|
}
|
|
|
|
|
|
|
|
let logs: Vec<_> = lc.into();
|
|
|
|
assert_eq!(logs.len(), LOG_MESSAGES_BYTES_LIMIT);
|
|
|
|
for log in logs.iter().take(LOG_MESSAGES_BYTES_LIMIT - 1) {
|
|
|
|
assert_eq!(*log, "x".to_string());
|
|
|
|
}
|
|
|
|
assert_eq!(logs.last(), Some(&"Log truncated".to_string()));
|
2020-06-06 10:18:28 -07:00
|
|
|
}
|
|
|
|
}
|