Skip to content

Commit ec7af71

Browse files
committed
fix: filter stats sessions without timestamps
1 parent 7954d02 commit ec7af71

2 files changed

Lines changed: 67 additions & 5 deletions

File tree

src/cortex-cli/src/stats_cmd.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ fn infer_provider(model: &str) -> String {
330330
}
331331

332332
/// Collect statistics from session files.
333-
async fn collect_stats(sessions_dir: &PathBuf, cli: &StatsCli) -> Result<UsageStats> {
333+
pub(super) async fn collect_stats(sessions_dir: &PathBuf, cli: &StatsCli) -> Result<UsageStats> {
334334
let mut stats = UsageStats::default();
335335

336336
// Calculate date range
@@ -363,10 +363,15 @@ async fn collect_stats(sessions_dir: &PathBuf, cli: &StatsCli) -> Result<UsageSt
363363
// Try to parse the session
364364
if let Ok(session_data) = parse_session_file(&path) {
365365
// Check if session is within date range
366-
if let Some(ref timestamp) = session_data.timestamp
367-
&& let Ok(session_date) = chrono::DateTime::parse_from_rfc3339(timestamp)
368-
&& session_date < start_date
369-
{
366+
let Some(session_date) = session_data
367+
.timestamp
368+
.as_deref()
369+
.and_then(|timestamp| chrono::DateTime::parse_from_rfc3339(timestamp).ok())
370+
else {
371+
continue;
372+
};
373+
374+
if session_date < start_date {
370375
continue;
371376
}
372377

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use serde_json::json;
2+
3+
#[path = "../src/stats_cmd.rs"]
4+
mod stats_cmd;
5+
6+
fn write_session(
7+
sessions_dir: &std::path::Path,
8+
name: &str,
9+
timestamp: Option<&str>,
10+
input_tokens: u64,
11+
) {
12+
let mut session = json!({
13+
"model": "gpt-4o",
14+
"usage": {
15+
"input_tokens": input_tokens,
16+
"output_tokens": 1
17+
}
18+
});
19+
20+
if let Some(timestamp) = timestamp {
21+
session["timestamp"] = json!(timestamp);
22+
}
23+
24+
std::fs::write(
25+
sessions_dir.join(name),
26+
serde_json::to_string_pretty(&session).expect("serialize session"),
27+
)
28+
.expect("write session");
29+
}
30+
31+
#[tokio::test]
32+
async fn stats_days_ignores_sessions_without_parseable_timestamps() {
33+
let temp = tempfile::tempdir().expect("temp dir");
34+
let sessions_dir = temp.path().join("sessions");
35+
std::fs::create_dir_all(&sessions_dir).expect("create sessions dir");
36+
37+
let recent_timestamp = chrono::Utc::now().to_rfc3339();
38+
write_session(&sessions_dir, "recent.json", Some(&recent_timestamp), 10);
39+
write_session(&sessions_dir, "old.json", Some("2000-01-01T00:00:00Z"), 100);
40+
write_session(&sessions_dir, "invalid.json", Some("not-a-date"), 1_000);
41+
write_session(&sessions_dir, "missing.json", None, 10_000);
42+
43+
let cli = stats_cmd::StatsCli {
44+
days: 1,
45+
provider: None,
46+
model: None,
47+
json: true,
48+
verbose: false,
49+
};
50+
let stats = stats_cmd::collect_stats(&sessions_dir, &cli)
51+
.await
52+
.expect("collect stats");
53+
54+
assert_eq!(stats.total_sessions, 1);
55+
assert_eq!(stats.input_tokens, 10);
56+
assert_eq!(stats.output_tokens, 1);
57+
}

0 commit comments

Comments
 (0)