Skip to content

Commit 295c72a

Browse files
authored
Merge pull request #153 from liubchigo/fix/data-discrepancy
🐛 Fix dashboard data discrepancy
2 parents 3cab365 + dc2a6e3 commit 295c72a

File tree

1 file changed

+56
-17
lines changed

1 file changed

+56
-17
lines changed

src/extension.ts

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -612,16 +612,41 @@ class CopilotTokenTracker implements vscode.Disposable {
612612
}
613613

614614
try {
615+
// Fast check: Get file stats first to avoid processing old files
615616
const fileStats = fs.statSync(sessionFile);
617+
618+
// Skip files modified before the current month (quick filter)
619+
// This is the main performance optimization - filters out old sessions without reading file content
620+
if (fileStats.mtime < monthStart) {
621+
skippedFiles++;
622+
continue;
623+
}
624+
625+
// For files within current month, check if data is cached to avoid redundant reads
626+
const mtime = fileStats.mtime.getTime();
627+
const wasCached = this.isCacheValid(sessionFile, mtime);
628+
629+
// Get interactions count (uses cache if available)
630+
const interactions = await this.countInteractionsInSessionCached(sessionFile, mtime);
631+
632+
// Skip empty sessions (no interactions = just opened chat panel, no messages sent)
633+
if (interactions === 0) {
634+
skippedFiles++;
635+
continue;
636+
}
637+
638+
// Get remaining data (all use cache if available)
639+
const tokens = await this.estimateTokensFromSessionCached(sessionFile, mtime);
640+
const modelUsage = await this.getModelUsageFromSessionCached(sessionFile, mtime);
641+
const editorType = this.getEditorTypeFromPath(sessionFile);
642+
643+
// For date filtering, get lastInteraction from session details
644+
const details = await this.getSessionFileDetails(sessionFile);
645+
const lastActivity = details.lastInteraction
646+
? new Date(details.lastInteraction)
647+
: new Date(details.modified);
616648

617-
if (fileStats.mtime >= monthStart) {
618-
// Check if data is cached before making calls
619-
const wasCached = this.isCacheValid(sessionFile, fileStats.mtime.getTime());
620-
621-
const tokens = await this.estimateTokensFromSessionCached(sessionFile, fileStats.mtime.getTime());
622-
const interactions = await this.countInteractionsInSessionCached(sessionFile, fileStats.mtime.getTime());
623-
const modelUsage = await this.getModelUsageFromSessionCached(sessionFile, fileStats.mtime.getTime());
624-
const editorType = this.getEditorTypeFromPath(sessionFile);
649+
if (lastActivity >= monthStart) {
625650

626651
// Update cache statistics
627652
if (wasCached) {
@@ -650,7 +675,7 @@ class CopilotTokenTracker implements vscode.Disposable {
650675
monthStats.modelUsage[model].outputTokens += usage.outputTokens;
651676
}
652677

653-
if (fileStats.mtime >= todayStart) {
678+
if (lastActivity >= todayStart) {
654679
todayStats.tokens += tokens;
655680
todayStats.sessions += 1;
656681
todayStats.interactions += interactions;
@@ -673,7 +698,7 @@ class CopilotTokenTracker implements vscode.Disposable {
673698
}
674699
}
675700
else {
676-
// File is too old, skip it
701+
// Session is too old (no activity in current month), skip it
677702
skippedFiles++;
678703
}
679704
} catch (fileError) {
@@ -683,7 +708,7 @@ class CopilotTokenTracker implements vscode.Disposable {
683708

684709
this.log(`✅ Analysis complete: Today ${todayStats.sessions} sessions, Month ${monthStats.sessions} sessions`);
685710
if (skippedFiles > 0) {
686-
this.log(`⏭️ Skipped ${skippedFiles} session file(s) (too old, not in current month)`);
711+
this.log(`⏭️ Skipped ${skippedFiles} session file(s) (empty or no activity in current month)`);
687712
}
688713
const totalCacheAccesses = cacheHits + cacheMisses;
689714
this.log(`💾 Cache performance: ${cacheHits} hits, ${cacheMisses} misses (${totalCacheAccesses > 0 ? ((cacheHits / totalCacheAccesses) * 100).toFixed(1) : 0}% hit rate)`);
@@ -3206,7 +3231,25 @@ class CopilotTokenTracker implements vscode.Disposable {
32063231
fourteenDaysAgo.setDate(fourteenDaysAgo.getDate() - 14);
32073232
const detailedSessionFiles: SessionFileDetails[] = [];
32083233

3209-
for (const file of sessionFiles.slice(0, 500)) {
3234+
// Sort files by modification time (most recent first) before taking first 500
3235+
// This ensures we prioritize recent sessions regardless of their folder location
3236+
const fileStats = await Promise.all(
3237+
sessionFiles.map(async (file) => {
3238+
try {
3239+
const stat = await fs.promises.stat(file);
3240+
return { file, mtime: stat.mtime.getTime() };
3241+
} catch {
3242+
return { file, mtime: 0 };
3243+
}
3244+
})
3245+
);
3246+
3247+
const sortedFiles = fileStats
3248+
.sort((a, b) => b.mtime - a.mtime)
3249+
.map(item => item.file);
3250+
3251+
// Process up to 500 most recent session files
3252+
for (const file of sortedFiles.slice(0, 500)) {
32103253
// Check if panel was disposed
32113254
if (!panel.visible && panel.viewColumn === undefined) {
32123255
this.log('Diagnostic panel closed, stopping background load');
@@ -3215,11 +3258,7 @@ class CopilotTokenTracker implements vscode.Disposable {
32153258

32163259
try {
32173260
const details = await this.getSessionFileDetails(file);
3218-
// Filter: skip empty sessions (no interactions = just opened chat panel, no messages sent)
3219-
if (details.interactions === 0) {
3220-
continue;
3221-
}
3222-
// Filter: only include sessions with activity in the last 14 days
3261+
// Only include sessions with activity (lastInteraction or file modified time) within the last 14 days
32233262
const lastActivity = details.lastInteraction
32243263
? new Date(details.lastInteraction)
32253264
: new Date(details.modified);

0 commit comments

Comments
 (0)