Skip to content

Commit e17c6e0

Browse files
acmelclaude
andcommitted
feat(cache): log timing, file size and entry count on startup
Add an "Opening response cache" message before the DB initialization begins and a "Response cache ready" summary when it completes, reporting the number of cached entries, file size (MB/GB), lifetime tokens saved, and elapsed wall-clock time. This makes it easy to spot slow cache opens and provides useful diagnostics at startup. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Derek Barbosa <debarbos@redhat.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 000ce3e commit e17c6e0

1 file changed

Lines changed: 43 additions & 3 deletions

File tree

src/ai/cache.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use async_trait::async_trait;
33
use sha2::{Digest, Sha256};
44
use std::sync::Arc;
55
use std::sync::atomic::{AtomicU64, Ordering};
6-
use std::time::{SystemTime, UNIX_EPOCH};
6+
use std::time::{Instant, SystemTime, UNIX_EPOCH};
77
use tracing::{debug, info};
88

99
use super::{AiProvider, AiRequest, AiResponse, CacheStats, ProviderCapabilities};
@@ -20,7 +20,18 @@ pub fn fmt_thousands(n: u64) -> String {
2020
result
2121
}
2222

23-
/// Format a token count with abbreviated suffix: 1.2M, 42.1k, or raw number.
23+
pub fn fmt_bytes(n: u64) -> String {
24+
if n >= 1_073_741_824 {
25+
format!("{:.1} GB", n as f64 / 1_073_741_824.0)
26+
} else if n >= 1_048_576 {
27+
format!("{:.1} MB", n as f64 / 1_048_576.0)
28+
} else if n >= 1_024 {
29+
format!("{:.1} KB", n as f64 / 1_024.0)
30+
} else {
31+
format!("{} B", n)
32+
}
33+
}
34+
2435
pub fn fmt_tokens(n: u64) -> String {
2536
if n >= 1_000_000 {
2637
format!("{:.1}M", n as f64 / 1_000_000.0)
@@ -45,6 +56,13 @@ pub struct CachingAiProvider {
4556

4657
impl CachingAiProvider {
4758
pub async fn new(inner: Arc<dyn AiProvider>, cache_path: &str, ttl_days: u64) -> Result<Self> {
59+
let file_size = std::fs::metadata(cache_path).map(|m| m.len()).unwrap_or(0);
60+
info!(
61+
"Opening response cache ({}, {}), this may take a moment...",
62+
cache_path,
63+
fmt_bytes(file_size)
64+
);
65+
let start = Instant::now();
4866
let db = libsql::Builder::new_local(cache_path).build().await?;
4967
let conn = db.connect()?;
5068

@@ -92,12 +110,34 @@ impl CachingAiProvider {
92110
);
93111
}
94112

113+
let mut total_entries: u64 = 0;
114+
// tokens_stored = SUM(tokens_saved) — total tokens across all unique entries,
115+
// i.e. potential savings if each entry is hit once.
116+
let mut total_tokens_stored: u64 = 0;
117+
if let Ok(Some(row)) = conn
118+
.query(
119+
"SELECT COUNT(*), COALESCE(SUM(tokens_saved), 0) FROM response_cache",
120+
(),
121+
)
122+
.await?
123+
.next()
124+
.await
125+
{
126+
total_entries = row.get::<u64>(0).unwrap_or(0);
127+
total_tokens_stored = row.get::<u64>(1).unwrap_or(0);
128+
}
129+
95130
let session_start = SystemTime::now()
96131
.duration_since(UNIX_EPOCH)
97132
.unwrap_or_default()
98133
.as_secs() as i64;
99134

100-
info!("Response cache enabled ({})", cache_path);
135+
info!(
136+
"Response cache ready: {} entries, {} tokens stored, {:.2}s to load",
137+
fmt_thousands(total_entries),
138+
fmt_thousands(total_tokens_stored),
139+
start.elapsed().as_secs_f64()
140+
);
101141

102142
Ok(Self {
103143
inner,

0 commit comments

Comments
 (0)