Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Services/UsageStatisticsService.cs

267 lines
5.4 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using AxCopilot.Models;
namespace AxCopilot.Services;
internal static class UsageStatisticsService
{
private static readonly string _statsDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "stats");
private static DailyUsageStats _today = new DailyUsageStats();
private static bool _initialized;
private static readonly object _lock = new object();
private const int RetentionDays = 30;
public static void RecordLauncherOpen()
{
EnsureInitialized();
lock (_lock)
{
_today.LauncherOpens++;
}
SaveTodayAsync();
}
public static void RecordCommandUsage(string commandKey)
{
if (!string.IsNullOrWhiteSpace(commandKey))
{
EnsureInitialized();
lock (_lock)
{
_today.CommandUsage.TryGetValue(commandKey, out var value);
_today.CommandUsage[commandKey] = value + 1;
}
SaveTodayAsync();
}
}
public static void AddActiveSeconds(int seconds)
{
if (seconds > 0)
{
EnsureInitialized();
lock (_lock)
{
_today.ActiveSeconds += seconds;
}
SaveTodayAsync();
}
}
public static int GetTodayActiveSeconds()
{
EnsureInitialized();
lock (_lock)
{
return _today.ActiveSeconds;
}
}
public static void RecordChat(string tab)
{
if (string.IsNullOrWhiteSpace(tab))
{
tab = "Chat";
}
EnsureInitialized();
lock (_lock)
{
_today.ChatCounts.TryGetValue(tab, out var value);
_today.ChatCounts[tab] = value + 1;
}
SaveTodayAsync();
}
public static void RecordTokens(int promptTokens, int completionTokens)
{
if (promptTokens > 0 || completionTokens > 0)
{
EnsureInitialized();
lock (_lock)
{
_today.PromptTokens += promptTokens;
_today.CompletionTokens += completionTokens;
_today.TotalTokens += promptTokens + completionTokens;
}
SaveTodayAsync();
}
}
public static List<DailyUsageStats> GetStats(int days = 30)
{
EnsureInitialized();
List<DailyUsageStats> list = new List<DailyUsageStats>();
DateTime today = DateTime.Today;
for (int num = days - 1; num >= 0; num--)
{
string text = today.AddDays(-num).ToString("yyyy-MM-dd");
if (text == _today.Date)
{
DailyUsageStats item;
lock (_lock)
{
item = CloneToday();
}
list.Add(item);
}
else
{
string filePath = GetFilePath(text);
if (File.Exists(filePath))
{
try
{
string json = File.ReadAllText(filePath);
DailyUsageStats dailyUsageStats = JsonSerializer.Deserialize<DailyUsageStats>(json);
if (dailyUsageStats != null)
{
list.Add(dailyUsageStats);
}
else
{
list.Add(new DailyUsageStats
{
Date = text
});
}
}
catch
{
list.Add(new DailyUsageStats
{
Date = text
});
}
}
else
{
list.Add(new DailyUsageStats
{
Date = text
});
}
}
}
return list;
}
private static void EnsureInitialized()
{
if (_initialized)
{
return;
}
lock (_lock)
{
if (_initialized)
{
return;
}
try
{
Directory.CreateDirectory(_statsDir);
string text = DateTime.Today.ToString("yyyy-MM-dd");
string filePath = GetFilePath(text);
if (File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
DailyUsageStats dailyUsageStats = JsonSerializer.Deserialize<DailyUsageStats>(json);
_today = dailyUsageStats ?? new DailyUsageStats
{
Date = text
};
}
else
{
_today = new DailyUsageStats
{
Date = text
};
}
PurgeOldFiles();
}
catch (Exception ex)
{
LogService.Warn("통계 서비스 초기화 실패: " + ex.Message);
_today = new DailyUsageStats
{
Date = DateTime.Today.ToString("yyyy-MM-dd")
};
}
_initialized = true;
}
}
private static void PurgeOldFiles()
{
try
{
DateTime dateTime = DateTime.Today.AddDays(-30.0);
string[] files = Directory.GetFiles(_statsDir, "????-??-??.json");
foreach (string path in files)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
if (DateTime.TryParse(fileNameWithoutExtension, out var result) && result < dateTime)
{
File.Delete(path);
}
}
}
catch (Exception ex)
{
LogService.Warn("통계 파일 정리 실패: " + ex.Message);
}
}
private static async Task SaveTodayAsync()
{
try
{
DailyUsageStats snapshot;
lock (_lock)
{
snapshot = CloneToday();
}
string path = GetFilePath(snapshot.Date);
string json = JsonSerializer.Serialize(snapshot, new JsonSerializerOptions
{
WriteIndented = false
});
await File.WriteAllTextAsync(path, json);
}
catch (Exception ex)
{
Exception ex2 = ex;
LogService.Warn("통계 저장 실패: " + ex2.Message);
}
}
private static DailyUsageStats CloneToday()
{
return new DailyUsageStats
{
Date = _today.Date,
LauncherOpens = _today.LauncherOpens,
ActiveSeconds = _today.ActiveSeconds,
CommandUsage = new Dictionary<string, int>(_today.CommandUsage),
ChatCounts = new Dictionary<string, int>(_today.ChatCounts),
TotalTokens = _today.TotalTokens,
PromptTokens = _today.PromptTokens,
CompletionTokens = _today.CompletionTokens
};
}
private static string GetFilePath(string dateStr)
{
return Path.Combine(_statsDir, dateStr + ".json");
}
}