Initial commit to new repository
This commit is contained in:
266
.decompiledproj/AxCopilot/Services/UsageStatisticsService.cs
Normal file
266
.decompiledproj/AxCopilot/Services/UsageStatisticsService.cs
Normal file
@@ -0,0 +1,266 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user