mirror of
https://github.com/facebook/sapling.git
synced 2025-01-08 14:46:47 +03:00
blackbox: buffer logs before initialization
Summary: This allows us to preserve logs before the blackbox initialization. In the edenscm usecase, we might want to log a "process start" event before knowing the location of the blackbox. Reviewed By: xavierd Differential Revision: D16044038 fbshipit-source-id: 7f41994989bb3a83e9ded3014e5afeae00f3350c
This commit is contained in:
parent
17ee0df47c
commit
56cf4cef7d
@ -21,7 +21,8 @@ use std::time::SystemTime;
|
||||
/// Local, rotated log consists of events tagged with "Invocation ID" and
|
||||
/// timestamps.
|
||||
pub struct Blackbox {
|
||||
log: RotateLog,
|
||||
// Used by singleton.
|
||||
pub(crate) log: RotateLog,
|
||||
opts: BlackboxOptions,
|
||||
|
||||
// An ID that can be "grouped by" to figure everything about a session.
|
||||
@ -380,7 +381,7 @@ fn new_session_id() -> u64 {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
@ -391,7 +392,7 @@ mod tests {
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
enum Event {
|
||||
pub(crate) enum Event {
|
||||
A(u64),
|
||||
B(String),
|
||||
}
|
||||
|
@ -8,8 +8,9 @@
|
||||
//! Useful for cases where it's inconvenient to pass [`Blackbox`] around.
|
||||
|
||||
use crate::{Blackbox, BlackboxOptions};
|
||||
use indexedlog::rotate::RotateLowLevelExt;
|
||||
use lazy_static::lazy_static;
|
||||
use std::ops::DerefMut;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
@ -18,14 +19,28 @@ lazy_static! {
|
||||
}
|
||||
|
||||
/// Replace the global [`Blackbox`] instance.
|
||||
pub fn init(blackbox: Blackbox) {
|
||||
///
|
||||
/// If [`log`] was called, their side effects will be re-applied to the
|
||||
/// specified blackbox.
|
||||
pub fn init(mut blackbox: Blackbox) {
|
||||
let mut singleton = SINGLETON.lock().unwrap();
|
||||
|
||||
// Insert dirty entries to the new blackbox.
|
||||
let old_blackbox = singleton.deref();
|
||||
for log in old_blackbox.log.logs().iter() {
|
||||
for entry in log.iter_dirty() {
|
||||
if let Ok(entry) = entry {
|
||||
let _ = blackbox.log.append(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*singleton.deref_mut() = blackbox;
|
||||
}
|
||||
|
||||
/// Log to the global [`Blackbox`] instance.
|
||||
///
|
||||
/// Do nothing if [`init`] was not called.
|
||||
/// If [`init`] was not called, log requests will be buffered in memory.
|
||||
pub fn log(data: &impl serde::Serialize) {
|
||||
if let Ok(mut singleton) = SINGLETON.lock() {
|
||||
let blackbox = singleton.deref_mut();
|
||||
@ -40,3 +55,31 @@ pub fn sync() {
|
||||
blackbox.sync();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::blackbox::{tests::Event, IndexFilter};
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[test]
|
||||
fn test_buffered_writes() {
|
||||
let events = vec![Event::A(42), Event::B("foo".to_string())];
|
||||
for e in &events {
|
||||
log(e);
|
||||
}
|
||||
|
||||
let dir = tempdir().unwrap();
|
||||
let blackbox = BlackboxOptions::new().open(&dir).unwrap();
|
||||
init(blackbox);
|
||||
|
||||
for e in &events[1..2] {
|
||||
log(e);
|
||||
}
|
||||
|
||||
let mut singleton = SINGLETON.lock().unwrap();
|
||||
let blackbox = singleton.deref_mut();
|
||||
assert_eq!(blackbox.filter::<Event>(IndexFilter::Nop, None).len(), 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user