Skip to main content

vgi_rpc/
log.rs

1//! Client-directed log messages carried in batch custom_metadata.
2
3use serde_json::json;
4
5/// Log severity level. Matches the Python `vgi_rpc.log.Level` values.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum LogLevel {
8    Trace,
9    Debug,
10    Info,
11    Warn,
12    Error,
13    Exception,
14}
15
16impl LogLevel {
17    pub fn as_str(self) -> &'static str {
18        match self {
19            LogLevel::Trace => "TRACE",
20            LogLevel::Debug => "DEBUG",
21            LogLevel::Info => "INFO",
22            LogLevel::Warn => "WARN",
23            LogLevel::Error => "ERROR",
24            LogLevel::Exception => "EXCEPTION",
25        }
26    }
27}
28
29/// A log message emitted by a server method, delivered to the client
30/// via an out-of-band zero-row batch.
31#[derive(Debug, Clone)]
32pub struct LogMessage {
33    pub level: LogLevel,
34    pub message: String,
35    pub extras: Vec<(String, String)>,
36}
37
38impl LogMessage {
39    pub fn new(level: LogLevel, message: impl Into<String>) -> Self {
40        Self {
41            level,
42            message: message.into(),
43            extras: Vec::new(),
44        }
45    }
46
47    pub fn with_extra(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
48        self.extras.push((key.into(), value.into()));
49        self
50    }
51
52    /// JSON encoding of extras as a flat object (string values).
53    pub fn extras_json(&self) -> String {
54        let mut map = serde_json::Map::new();
55        for (k, v) in &self.extras {
56            map.insert(k.clone(), json!(v));
57        }
58        serde_json::Value::Object(map).to_string()
59    }
60}