using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Serilog; using Serilog.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace JiShe.CollectBus.PluginFileWatcher { /// /// 数据库操作工具类,用于命令行测试数据库功能 /// public class DbUtility { private readonly EventDatabaseManager _dbManager; private readonly ILogger _logger; private readonly FileMonitorConfig _config; /// /// 初始化数据库工具类 /// /// 配置文件路径 public DbUtility(string configPath = "appsettings.json") { // 从配置文件加载配置 var configuration = new ConfigurationBuilder() .AddJsonFile(configPath, optional: false, reloadOnChange: true) .Build(); // 初始化日志 var serilogLogger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .CreateLogger(); // 将Serilog适配为Microsoft.Extensions.Logging.ILogger _logger = new SerilogLoggerFactory(serilogLogger).CreateLogger("DbUtility"); // 创建配置对象 _config = new FileMonitorConfig(); configuration.GetSection("FileMonitor").Bind(_config); // 确保SQLite存储已启用 _config.EventStorage.EnableEventStorage = true; _config.EventStorage.StorageType = "SQLite"; // 创建数据库管理器 _dbManager = new EventDatabaseManager(_config, _logger); } /// /// 执行数据库维护操作 /// /// 命令行参数 public async Task ExecuteAsync(string[] args) { if (args.Length == 0) { PrintUsage(); return; } string command = args[0].ToLower(); switch (command) { case "stats": await ShowStatisticsAsync(); break; case "cleanup": int days = args.Length > 1 && int.TryParse(args[1], out int d) ? d : _config.EventStorage.DataRetentionDays; await _dbManager.CleanupOldDataAsync(days); Console.WriteLine($"已清理 {days} 天前的旧数据"); break; case "query": await QueryEventsAsync(args); break; case "test": await GenerateTestDataAsync(args); break; default: Console.WriteLine($"未知命令: {command}"); PrintUsage(); break; } } /// /// 显示帮助信息 /// private void PrintUsage() { Console.WriteLine("数据库工具使用方法:"); Console.WriteLine(" stats - 显示数据库统计信息"); Console.WriteLine(" cleanup [days] - 清理指定天数之前的数据(默认使用配置值)"); Console.WriteLine(" query [limit] - 查询最近的事件(默认10条)"); Console.WriteLine(" query type:X ext:Y - 按类型和扩展名查询事件"); Console.WriteLine(" test [count] - 生成测试数据(默认100条)"); } /// /// 显示数据库统计信息 /// private async Task ShowStatisticsAsync() { try { var stats = await _dbManager.GetDatabaseStatsAsync(); Console.WriteLine("数据库统计信息:"); Console.WriteLine($"事件总数: {stats.TotalEvents}"); Console.WriteLine($"最早事件时间: {stats.OldestEventTime?.ToLocalTime()}"); Console.WriteLine($"最新事件时间: {stats.NewestEventTime?.ToLocalTime()}"); Console.WriteLine("\n事件类型分布:"); if (stats.EventTypeCounts != null) { foreach (var item in stats.EventTypeCounts) { Console.WriteLine($" {item.Key}: {item.Value}"); } } Console.WriteLine("\n扩展名分布 (Top 10):"); if (stats.TopExtensions != null) { foreach (var item in stats.TopExtensions) { Console.WriteLine($" {item.Key}: {item.Value}"); } } } catch (Exception ex) { Console.WriteLine($"获取统计信息出错: {ex.Message}"); _logger.LogError(ex, "获取数据库统计信息时发生错误"); } } /// /// 查询事件 /// private async Task QueryEventsAsync(string[] args) { try { var queryParams = new EventQueryParams { PageSize = 10, PageIndex = 0 }; // 解析查询参数 if (args.Length > 1) { foreach (var arg in args.Skip(1)) { if (int.TryParse(arg, out int limit)) { queryParams.PageSize = limit; } else if (arg.StartsWith("type:", StringComparison.OrdinalIgnoreCase)) { string typeValue = arg.Substring(5); if (Enum.TryParse(typeValue, true, out var eventType)) { queryParams.EventType = eventType; } } else if (arg.StartsWith("ext:", StringComparison.OrdinalIgnoreCase)) { queryParams.ExtensionFilter = arg.Substring(4); if (!queryParams.ExtensionFilter.StartsWith(".")) { queryParams.ExtensionFilter = "." + queryParams.ExtensionFilter; } } else if (arg.StartsWith("path:", StringComparison.OrdinalIgnoreCase)) { queryParams.PathFilter = arg.Substring(5); } } } // 执行查询 var result = await _dbManager.QueryEventsAsync(queryParams); Console.WriteLine($"查询结果 (总数: {result.TotalCount}):"); foreach (var evt in result.Events) { string typeStr = evt.EventType.ToString(); string timestamp = evt.Timestamp.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"); Console.WriteLine($"[{timestamp}] {typeStr,-10} {evt.FileName} ({evt.Extension})"); } if (result.HasMore) { Console.WriteLine($"... 还有更多结果,共 {result.TotalCount} 条"); } } catch (Exception ex) { Console.WriteLine($"查询事件出错: {ex.Message}"); _logger.LogError(ex, "查询事件时发生错误"); } } /// /// 生成测试数据 /// private async Task GenerateTestDataAsync(string[] args) { try { int count = args.Length > 1 && int.TryParse(args[1], out int c) ? c : 100; var events = new List(); var rnd = new Random(); string[] extensions = { ".dll", ".exe", ".txt", ".cs", ".xml", ".json", ".png", ".jpg" }; string[] directories = { "C:\\Temp", "D:\\Work", "C:\\Program Files", "D:\\Projects", "E:\\Data" }; DateTime startTime = DateTime.Now.AddHours(-24); for (int i = 0; i < count; i++) { var eventType = (FileEventType)rnd.Next(0, 5); var ext = extensions[rnd.Next(extensions.Length)]; var dir = directories[rnd.Next(directories.Length)]; var fileName = $"TestFile_{i:D5}{ext}"; var timestamp = startTime.AddMinutes(i); var fileEvent = new FileEvent { Id = Guid.NewGuid(), Timestamp = timestamp, EventType = eventType, FullPath = $"{dir}\\{fileName}", FileName = fileName, Directory = dir, Extension = ext, FileSize = rnd.Next(1024, 1024 * 1024) }; // 如果是重命名事件,添加旧文件名 if (eventType == FileEventType.Renamed) { fileEvent.OldFileName = $"OldFile_{i:D5}{ext}"; fileEvent.OldFullPath = $"{dir}\\{fileEvent.OldFileName}"; } // 添加一些元数据 fileEvent.Metadata["CreationTime"] = timestamp.AddMinutes(-rnd.Next(1, 60)).ToString("o"); fileEvent.Metadata["LastWriteTime"] = timestamp.ToString("o"); fileEvent.Metadata["IsReadOnly"] = (rnd.Next(10) < 2).ToString(); fileEvent.Metadata["TestData"] = $"测试数据 {i}"; events.Add(fileEvent); } Console.WriteLine($"正在生成 {count} 条测试数据..."); await _dbManager.SaveEventsAsync(events); Console.WriteLine("测试数据生成完成!"); } catch (Exception ex) { Console.WriteLine($"生成测试数据出错: {ex.Message}"); _logger.LogError(ex, "生成测试数据时发生错误"); } } } }