use crate::types::Degrade;
use chrono::{Local, SecondsFormat};
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::sync::Arc;
use std::time::Instant;
pub type EventSink = Arc<dyn Fn(&LogEvent) + Send + Sync>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEvent {
pub ts: String,
pub kind: String,
pub ms: u64,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub stages: BTreeMap<String, u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub candidates: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub folded: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rerank_docs: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rerank_tokens: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hits: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub documents: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub format: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub degraded: Vec<Degrade>,
}
impl LogEvent {
pub fn new(kind: &str) -> Self {
Self {
ts: Local::now().to_rfc3339_opts(SecondsFormat::Millis, false),
kind: kind.to_string(),
ms: 0,
stages: BTreeMap::new(),
candidates: None,
folded: None,
rerank_docs: None,
rerank_tokens: None,
hits: None,
documents: None,
format: None,
degraded: Vec::new(),
}
}
}
#[derive(Default)]
pub(crate) struct EventRegistry {
sink: Mutex<Option<EventSink>>,
}
impl EventRegistry {
pub fn get(&self) -> Option<EventSink> {
self.sink.lock().clone()
}
pub fn set(&self, sink: EventSink) {
*self.sink.lock() = Some(sink);
}
pub fn clear(&self) -> bool {
self.sink.lock().take().is_some()
}
pub fn is_registered(&self) -> bool {
self.sink.lock().is_some()
}
}
pub(crate) struct StageTimer {
last: Instant,
marks: BTreeMap<String, u64>,
}
impl StageTimer {
pub fn start() -> Self {
Self { last: Instant::now(), marks: BTreeMap::new() }
}
pub fn mark(&mut self, name: &str) {
let now = Instant::now();
self.marks.insert(name.to_string(), (now - self.last).as_millis() as u64);
self.last = now;
}
pub fn finish(mut self, name: &str) -> BTreeMap<String, u64> {
self.mark(name);
self.marks
}
}