Skip to content

Commit dccf6e0

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 b992715 commit dccf6e0

1 file changed

Lines changed: 41 additions & 3 deletions

File tree

src/ai/cache.rs

Lines changed: 41 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,32 @@ impl CachingAiProvider {
92110
);
93111
}
94112

113+
let mut total_entries: u64 = 0;
114+
let mut total_tokens_saved: u64 = 0;
115+
if let Ok(Some(row)) = conn
116+
.query(
117+
"SELECT COUNT(*), COALESCE(SUM(tokens_saved), 0) FROM response_cache",
118+
(),
119+
)
120+
.await?
121+
.next()
122+
.await
123+
{
124+
total_entries = row.get::<u64>(0).unwrap_or(0);
125+
total_tokens_saved = row.get::<u64>(1).unwrap_or(0);
126+
}
127+
95128
let session_start = SystemTime::now()
96129
.duration_since(UNIX_EPOCH)
97130
.unwrap_or_default()
98131
.as_secs() as i64;
99132

100-
info!("Response cache enabled ({})", cache_path);
133+
info!(
134+
"Response cache ready: {} entries, {} tokens saved lifetime, {:.2}s to load",
135+
fmt_thousands(total_entries),
136+
fmt_thousands(total_tokens_saved),
137+
start.elapsed().as_secs_f64()
138+
);
101139

102140
Ok(Self {
103141
inner,

0 commit comments

Comments
 (0)