Files
Kigi-CLI/crates/codegen/kigi-sandbox/src/logging.rs
T
ZacharyZhang-NY a02b555e66 docs(comments): rewrite comments across all crates to the guidelines
Sweep every first-party crate source (1956 .rs files) to the project comment
guidelines: delete redundant restatements, decorative banners, change
narration, and end-of-line comments; keep and tighten the crucial ones
(invariants, bug rationale, SAFETY blocks, ported-source attribution).

No functional code changed. Every edit is proven comment-only against the
prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a
separate doctest-fence check. Where removing a comment made rustfmt or clippy
want to re-lay-out adjacent code, the minimal triggering comment is restored so
code tokens stay byte-identical.

Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy
--workspace --all-targets (0 warnings).

Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for
these guidelines (flags banners, end-of-line comments, change narration, and
commented-out code).
2026-07-23 16:55:39 -04:00

100 lines
2.6 KiB
Rust

//! Sandbox event logger.
//!
//! Events (profile applied, violations, bypasses) are buffered in memory and
//! flushed as JSONL to `~/.kigi/sandbox-events.jsonl`.
use std::path::PathBuf;
use std::sync::Mutex;
use crate::types::{SandboxEvent, SandboxEventType, SandboxMetrics};
pub struct SandboxLogger {
events: Mutex<Vec<SandboxEvent>>,
metrics: SandboxMetrics,
}
impl SandboxLogger {
pub fn new() -> Self {
Self {
events: Mutex::new(Vec::new()),
metrics: SandboxMetrics::default(),
}
}
pub fn log(&self, event: SandboxEvent) {
match &event.event_type {
SandboxEventType::FsViolation => self.metrics.inc_fs_violation(),
SandboxEventType::NetViolation => self.metrics.inc_net_violation(),
SandboxEventType::BypassGranted => self.metrics.inc_bypass_granted(),
SandboxEventType::BypassDenied => self.metrics.inc_bypass_denied(),
_ => {}
}
tracing::debug!(
event_type = ?event.event_type,
profile = %event.profile,
target = ?event.target,
operation = ?event.operation,
"sandbox event"
);
if let Ok(mut events) = self.events.lock() {
events.push(event);
}
}
pub fn metrics(&self) -> &SandboxMetrics {
&self.metrics
}
/// Drains the buffer.
pub fn take_events(&self) -> Vec<SandboxEvent> {
self.events
.lock()
.map(|mut events| std::mem::take(&mut *events))
.unwrap_or_default()
}
pub fn flush_to_disk(&self) -> anyhow::Result<()> {
let events = self.take_events();
if events.is_empty() {
return Ok(());
}
let log_path = Self::log_file_path();
if let Some(parent) = log_path.parent() {
std::fs::create_dir_all(parent)?;
}
use std::io::Write;
let mut file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&log_path)?;
for event in &events {
if let Ok(json) = serde_json::to_string(event) {
writeln!(file, "{}", json)?;
}
}
tracing::debug!(
path = %log_path.display(),
count = events.len(),
"flushed sandbox events to disk"
);
Ok(())
}
fn log_file_path() -> PathBuf {
kigi_config::kigi_home().join("sandbox-events.jsonl")
}
}
impl Default for SandboxLogger {
fn default() -> Self {
Self::new()
}
}