在工业自动化、物联网和设备监控领域,记录设备运行日志是保障系统稳定和问题追踪的关键环节。本文将详细介绍如何使用C#和SQLite数据库构建一个轻量级但功能强大的设备日志记录系统,并使用流行的Spectre.Console库为控制台输出添加美观的视觉效果。 
为什么选择SQLite? SQLite作为一个嵌入式数据库,具有以下优势: 
零配置,无需安装独立数据库服务 单文件存储,便于备份和迁移 跨平台兼容性强 资源占用少,适合嵌入式设备 支持SQL标准查询 系统设计 我们的设备日志系统包含以下核心组件: 
日志类型枚举(LogType) 设备日志实体类(DeviceLog) 日志管理器(DeviceLogManager) 控制台展示界面(使用Spectre.Console) 基础结构定义 首先,让我们定义日志类型枚举和设备日志实体类: 
// 日志类型枚举 public enum  LogType  {     Info,      // 一般信息     Warning,   // 警告信息     Error,     // 错误信息     Critical   // 严重错误 } // 设备日志实体类 public class   DeviceLog   {      public int  Id { get;  set ; }                 // 日志唯一标识      public  DateTime Timestamp { get;  set ; }     // 时间戳      public string  DeviceId { get;  set ; }        // 设备标识      public  LogType LogLevel { get;  set ; }       // 日志级别      public string  Message { get;  set ; }         // 日志消息      public double ? Temperature { get;  set ; }    // 温度(可选)      public double ? Voltage { get;  set ; }        // 电压(可选) } 数据库管理 日志管理器负责与SQLite数据库交互,实现日志的存储和检索: 
// 日志管理器 public class   DeviceLogManager   {      private string  _connectionString;      // 构造函数,接收数据库文件路径      public   DeviceLogManager ( string  dbPath)        {         _connectionString = $ "Data Source={dbPath};Version=3;" ;         InitializeDatabase();     }      // 初始化数据库,如果表不存在则创建      private   void   InitializeDatabase ()        {          using  (var connection =  new  SQLiteConnection(_connectionString))          {             connection.Open();              using  (var command =  new  SQLiteCommand(connection))              {                 command.CommandText = @ "                     CREATE TABLE IF NOT EXISTS DeviceLogs (                         Id INTEGER PRIMARY KEY AUTOINCREMENT,                         Timestamp DATETIME NOT NULL,                         DeviceId TEXT NOT NULL,                         LogLevel INTEGER NOT NULL,                         Message TEXT NOT NULL,                         Temperature REAL,                         Voltage REAL                     )" ;                 command.ExecuteNonQuery();             }         }     }      // 记录日志方法      public   void   LogEvent (DeviceLog  log )        {          using  (var connection =  new  SQLiteConnection(_connectionString))          {             connection.Open();              using  (var command =  new  SQLiteCommand(connection))              {                 command.CommandText = @ "                     INSERT INTO DeviceLogs                      (Timestamp, DeviceId, LogLevel, Message, Temperature, Voltage)                     VALUES                      (@Timestamp, @DeviceId, @LogLevel, @Message, @Temperature, @Voltage)" ;                 command.Parameters.AddWithValue( "@Timestamp" ,  log .Timestamp);                 command.Parameters.AddWithValue( "@DeviceId" ,  log .DeviceId);                 command.Parameters.AddWithValue( "@LogLevel" , ( int ) log .LogLevel);                 command.Parameters.AddWithValue( "@Message" ,  log .Message);                  // 对可能为空的数值使用DBNull.Value                 command.Parameters.AddWithValue( "@Temperature" ,  log .Temperature ?? (object)DBNull.Value);                 command.Parameters.AddWithValue( "@Voltage" ,  log .Voltage ?? (object)DBNull.Value);                 command.ExecuteNonQuery();             }         }     }      // 查询日志方法,支持多种过滤条件      public  List<DeviceLog> GetLogs(          string  deviceId = null,         LogType? logLevel = null,         DateTime? startTime = null,         DateTime? endTime = null)      {         var logs =  new  List<DeviceLog>();          using  (var connection =  new  SQLiteConnection(_connectionString))          {             connection.Open();              using  (var command =  new  SQLiteCommand(connection))              {                  // 构建WHERE子句                 var whereConditions =  new  List< string >();                  if  (! string .IsNullOrEmpty(deviceId))                      whereConditions.Add( "DeviceId = @DeviceId" );                  if  (logLevel.HasValue)                      whereConditions.Add( "LogLevel = @LogLevel" );                  if  (startTime.HasValue)                      whereConditions.Add( "Timestamp >= @StartTime" );                  if  (endTime.HasValue)                      whereConditions.Add( "Timestamp <= @EndTime" );                  string  whereClause = whereConditions.Any()                      ? $ "WHERE {string.Join("  AND  ", whereConditions)}"                     :  "" ;                  // 构建SQL查询                 command.CommandText = $@ "                     SELECT * FROM DeviceLogs                      {whereClause}                     ORDER BY Timestamp DESC" ;                  // 添加参数                  if  (! string .IsNullOrEmpty(deviceId))                     command.Parameters.AddWithValue( "@DeviceId" , deviceId);                  if  (logLevel.HasValue)                     command.Parameters.AddWithValue( "@LogLevel" , ( int )logLevel.Value);                  if  (startTime.HasValue)                     command.Parameters.AddWithValue( "@StartTime" , startTime.Value);                  if  (endTime.HasValue)                     command.Parameters.AddWithValue( "@EndTime" , endTime.Value);                  // 读取结果                  using  (var reader = command.ExecuteReader())                  {                      while  (reader.Read())                      {                         logs.Add( new  DeviceLog                          {                             Id = Convert.ToInt32(reader[ "Id" ]),                             Timestamp = Convert.ToDateTime(reader[ "Timestamp" ]),                             DeviceId = reader[ "DeviceId" ].ToString(),                             LogLevel = (LogType)Convert.ToInt32(reader[ "LogLevel" ]),                             Message = reader[ "Message" ].ToString(),                             Temperature = reader[ "Temperature" ] == DBNull.Value                                  ? null                                  : Convert.ToDouble(reader[ "Temperature" ]),                             Voltage = reader[ "Voltage" ] == DBNull.Value                                  ? null                                  : Convert.ToDouble(reader[ "Voltage" ])                         });                     }                 }             }         }          return  logs;     }      // 删除过期日志      public   void   DeleteOldLogs ( int  daysToKeep)        {          using  (var connection =  new  SQLiteConnection(_connectionString))          {             connection.Open();              using  (var command =  new  SQLiteCommand(connection))              {                 command.CommandText = @ "                     DELETE FROM DeviceLogs                      WHERE Timestamp < @OldDate" ;                 command.Parameters.AddWithValue( "@OldDate" , DateTime.Now.AddDays(-daysToKeep));                 command.ExecuteNonQuery();             }         }     } } 使用Spectre.Console美化控制台输出 Spectre.Console是一个现代化的.NET库,能够为控制台应用程序创建美观、交互式的用户界面。下面,我们将使用Spectre.Console提升我们的设备日志系统的可视化效果: 
using  Spectre.Console; using  System; using  System.Data.SQLite; using  System.Linq; namespace  DeviceLoggerSystem {      class   Program     {          static   void   Main ( string [] args)          {              // 创建标题             AnsiConsole.Write(                  new  FigletText( "设备日志系统" )                     .LeftJustified()                     .Color(Color.Green));              // 创建日志管理器             var dbPath =  "device_logs.db" ;             var logManager =  new  DeviceLogManager(dbPath);              // 使用进度条显示系统初始化             AnsiConsole.Progress()                 .Start(ctx =>                 {                     var task = ctx.AddTask( "[green]初始化系统[/]" );                      for  ( int  i =  0 ; i <  100 ; i++)                     {                         task.Increment( 1 );                         System.Threading.Thread.Sleep( 20 );                     }                 });              // 记录一些示例日志             AddSampleLogs(logManager);              // 主循环              bool  running =  true ;              while  (running)             {                 var choice = AnsiConsole.Prompt(                      new  SelectionPrompt< string >()                         .Title( "[yellow]请选择操作:[/]" )                         .PageSize( 10 )                         .AddChoices( new []                         {                              "添加新日志" ,                               "查询设备日志" ,                              "查看统计信息" ,                              "清理旧日志" ,                              "退出"                         }));                  switch  (choice)                 {                      case "添加新日志" :                         AddNewLog(logManager);                          break ;                      case "查询设备日志" :                         QueryLogs(logManager);                          break ;                      case "查看统计信息" :                         ShowStatistics(logManager);                          break ;                      case "清理旧日志" :                         CleanupOldLogs(logManager);                          break ;                      case "退出" :                         running =  false ;                          break ;                 }             }         }          // 添加示例日志数据          static   void   AddSampleLogs (DeviceLogManager logManager)          {             var deviceIds =  new [] {  "DEVICE_001" ,  "DEVICE_002" ,  "DEVICE_003"  };             var random =  new  Random();             foreach (var deviceId in deviceIds)             {                  // 添加一些随机的历史数据                  for  ( int  i =  0 ; i <  5 ; i++)                 {                     var timestamp = DateTime.Now.AddHours(-random.Next( 1 ,  48 ));                     var logType = (LogType)random.Next( 0 ,  4 );                     var temp =  20.0  + random.NextDouble() *  30.0 ;                     var voltage =  200.0  + random.NextDouble() *  40.0 ;                      string  message = logType  switch                     {                         LogType.Info =>  "定期检查正常" ,                         LogType.Warning =>  "温度偏高,请注意" ,                         LogType.Error =>  "电压异常,需要检查" ,                         LogType.Critical =>  "设备紧急停机" ,                         _ =>  "系统记录"                     };                     logManager.LogEvent( new  DeviceLog                     {                         Timestamp = timestamp,                         DeviceId = deviceId,                         LogLevel = logType,                         Message = message,                         Temperature = temp,                         Voltage = voltage                     });                 }             }             AnsiConsole.MarkupLine( "[green]示例数据已创建![/]" );         }          // 添加新日志          static   void   AddNewLog (DeviceLogManager logManager)          {             var deviceId = AnsiConsole.Ask< string >( "输入设备ID:" );             var logLevel = AnsiConsole.Prompt(                  new  SelectionPrompt<LogType>()                     .Title( "选择日志级别:" )                     .AddChoices(Enum.GetValues(typeof(LogType)).Cast<LogType>()));             var message = AnsiConsole.Ask< string >( "输入日志消息:" );              // 可选参数              double ? temperature = null;              double ? voltage = null;              if  (AnsiConsole.Confirm( "是否记录温度?" ))             {                 temperature = AnsiConsole.Ask< double >( "输入温度值:" );             }              if  (AnsiConsole.Confirm( "是否记录电压?" ))             {                 voltage = AnsiConsole.Ask< double >( "输入电压值:" );             }             logManager.LogEvent( new  DeviceLog             {                 Timestamp = DateTime.Now,                 DeviceId = deviceId,                 LogLevel = logLevel,                 Message = message,                 Temperature = temperature,                 Voltage = voltage             });             AnsiConsole.MarkupLine( "[green]日志已添加成功![/]" );         }          // 查询日志          static   void   QueryLogs (DeviceLogManager logManager)          {              // 构建查询条件              string  deviceId = null;              if  (AnsiConsole.Confirm( "是否按设备ID筛选?" ))             {                 deviceId = AnsiConsole.Ask< string >( "请输入设备ID:" );             }             LogType? logLevel = null;              if  (AnsiConsole.Confirm( "是否按日志级别筛选?" ))             {                 logLevel = AnsiConsole.Prompt(                      new  SelectionPrompt<LogType>()                         .Title( "选择日志级别:" )                         .AddChoices(Enum.GetValues(typeof(LogType)).Cast<LogType>()));             }             DateTime? startTime = null;              if  (AnsiConsole.Confirm( "是否设置开始时间?" ))             {                  string  dateStr = AnsiConsole.Ask< string >( "请输入开始时间 (yyyy-MM-dd HH:mm:ss):" );                  if  (DateTime.TryParse(dateStr, out var dt))                     startTime = dt;             }             DateTime? endTime = null;              if  (AnsiConsole.Confirm( "是否设置结束时间?" ))             {                  string  dateStr = AnsiConsole.Ask< string >( "请输入结束时间 (yyyy-MM-dd HH:mm:ss):" );                  if  (DateTime.TryParse(dateStr, out var dt))                     endTime = dt;             }              // 执行查询             var logs = logManager.GetLogs(deviceId, logLevel, startTime, endTime);              if  (logs.Count ==  0 )             {                 AnsiConsole.MarkupLine( "[yellow]未找到符合条件的日志记录[/]" );                  return ;             }              // 创建表格显示结果             var table =  new  Table();             table.Border(TableBorder.Rounded);             table.Expand();              // 添加列             table.AddColumn( "ID" );             table.AddColumn( "时间" );             table.AddColumn( "设备ID" );             table.AddColumn( "级别" );             table.AddColumn( "消息" );             table.AddColumn( "温度" );             table.AddColumn( "电压" );              // 添加数据行             foreach (var  log  in logs)             {                  string  tempStr =  log .Temperature.HasValue ? $ "{log.Temperature:F1}°C"  :  "-" ;                  string  voltStr =  log .Voltage.HasValue ? $ "{log.Voltage:F1}V"  :  "-" ;                  // 根据日志级别设置行颜色                 var style =  log .LogLevel  switch                 {                     LogType.Info =>  "green" ,                     LogType.Warning =>  "yellow" ,                     LogType.Error =>  "red" ,                     LogType.Critical =>  "red bold" ,                     _ =>  "white"                 };                 table.AddRow(                     $ "[{style}]{log.Id}[/]" ,                     $ "[{style}]{log.Timestamp}[/]" ,                     $ "[{style}]{log.DeviceId}[/]" ,                     $ "[{style}]{log.LogLevel}[/]" ,                     $ "[{style}]{log.Message}[/]" ,                     $ "[{style}]{tempStr}[/]" ,                     $ "[{style}]{voltStr}[/]"                 );             }             AnsiConsole.Write(table);             AnsiConsole.MarkupLine($ "[blue]共找到 {logs.Count} 条记录[/]" );         }          // 显示统计信息          static   void   ShowStatistics (DeviceLogManager logManager)          {              // 获取所有日志             var allLogs = logManager.GetLogs();              // 按设备统计             var deviceCounts = allLogs                 .GroupBy(l => l.DeviceId)                 .Select(g => (DeviceId: g.Key, Count: g.Count()))                 .ToList();              // 按日志级别统计             var levelCounts = allLogs                 .GroupBy(l => l.LogLevel)                 .Select(g => (Level: g.Key, Count: g.Count()))                 .ToList();              // 创建统计图表             AnsiConsole.Write( new  Rule( "[yellow]设备日志统计[/]" ));              // 设备柱状图             var deviceChart =  new  BarChart()                 .Width( 60 )                 .Label( "[green bold]按设备统计[/]" )                 .CenterLabel();             foreach (var item in deviceCounts)             {                 deviceChart.AddItem(item.DeviceId, item.Count, Color.Blue);             }             AnsiConsole.Write(deviceChart);              // 日志级别饼图             var levelChart =  new  BarChart()                 .Width( 60 )                 .Label( "[red bold]按日志级别统计[/]" )                 .CenterLabel();             foreach (var item in levelCounts)             {                 var color = item.Level  switch                 {                     LogType.Info => Color.Green,                     LogType.Warning => Color.Yellow,                     LogType.Error => Color.Red,                     LogType.Critical => Color.Purple,                     _ => Color.White                 };                 levelChart.AddItem(item.Level.ToString(), item.Count, color);             }             AnsiConsole.Write(levelChart);              // 时间分布              if  (allLogs.Any())             {                 AnsiConsole.MarkupLine($ "[blue]最早记录时间: {allLogs.Min(l => l.Timestamp)}[/]" );                 AnsiConsole.MarkupLine($ "[blue]最新记录时间: {allLogs.Max(l => l.Timestamp)}[/]" );                 AnsiConsole.MarkupLine($ "[blue]总记录数: {allLogs.Count}[/]" );             }         }          // 清理旧日志          static   void   CleanupOldLogs (DeviceLogManager logManager)          {             var days = AnsiConsole.Ask( "保留最近几天的日志?" ,  30 );              if  (AnsiConsole.Confirm($ "确定要删除 {days} 天前的所有日志记录?" ))             {                 AnsiConsole.Status()                     .Start( "正在清理旧日志..." , ctx =>                      {                         logManager.DeleteOldLogs(days);                         System.Threading.Thread.Sleep( 1000 );  // 模拟操作                     });                 AnsiConsole.MarkupLine( "[green]旧日志清理完成![/]" );             }         }     } } 
总结 本文介绍了如何使用C#和SQLite构建一个功能完整的设备日志记录系统,并借助Spectre.Console库打造美观的控制台界面。该系统具有以下优势: 
轻量级 高效性 可扩展 用户友好 实用功能 无论是在工业控制、智能家居还是物联网应用领域,这套系统都能为设备运行状态的监控和问题诊断提供有力支持。通过SQLite的高效存储和Spectre.Console的精美展示,让设备数据管理既实用又赏心悦目。 
您可以根据实际需求进一步扩展这个系统,例如添加数据导出功能、实现远程日志收集、开发Web管理界面等。 
阅读原文:原文链接