Serilog基于Seq開源框架實現日志分析
Serilog 是.NET 的日志記錄庫,核心是結構化日志;Seq 是開源的日志服務器,專注于集中管理和分析日志,接收、存儲、查詢和可視化日志,是獨立于應用的 “日志管理中心”。
日志記錄庫 Serilog
-
以鍵值對形式記錄結構化日志
-
可靈活配置日志輸出目的地,支持控制臺、文件、數據庫等多種 “接收器”。
-
支持異步記錄,性能較好,能適應高并發的.NET 應用場景。
日志服務器 Seq
-
專為結構化日志設計,能完美解析 Serilog 生成的鍵值對日志。
-
提供實時查詢功能,可快速篩選、分析日志數據,不用手動翻找日志文件。
-
支持日志可視化,能通過圖表直觀展示日志趨勢,適合排查問題和監控應用。
一、NuGet 包管理器中下載相關包
-
Serilog
-
Serilog.Sinks.Console(控制臺輸出)
-
Serilog.Sinks.File(輸出到文件)
-
Serilog.Sinks.Seq(輸出到Seq服務)
-
Seq.Api(Seq.Api HTTP服務)

二、搭建 Seq 日志服務
Docker命令行快速啟動
// 啟動項【將卷掛載到宿主機,配置數據持久化存儲,可避免容器或服務重啟后丟失數據】
docker run -d --name seq -e ACCEPT_EULA=Y -v /data/SeqData:/data -e SEQ_FIRSTRUN_ADMINUSERNAME=admin -e SEQ_FIRSTRUN_ADMINPASSWORD="123456" -p 5341:5341 -p 8081:80 datalust/seq:2025.2
瀏覽器輸入地址查看是否部署成功(http://localhost:8081/)

三、創建Serilog接口以及實現接口
點擊查看代碼
/// <summary>
/// Serilog 日志接口
/// </summary>
public interface ISerilogLogger
{
/// <summary>
/// 配置Seq服務日志記錄器
/// </summary>
/// <returns>Seq日志記錄器實例</returns>
ILogger ConfigureSeqLogger();
/// <summary>
/// 配置控制臺日志記錄器
/// </summary>
/// <returns>控制臺日志記錄器實例</returns>
ILogger ConfigureConsoleLogger();
/// <summary>
/// 配置文件日志記錄器
/// </summary>
/// <returns>文件日志記錄器實例</returns>
ILogger ConfigureFileLogger();
/// <summary>
/// 獲取默認日志記錄器實例
/// </summary>
/// <returns>Seq日志記錄器實例</returns>
ILogger GetLogger();
}
點擊查看代碼
/// <summary>
/// Serilog 記錄日志
/// </summary>
public class SerilogLogger : ISerilogLogger
{
/// <summary>
/// Seq服務 URL地址
/// </summary>
private readonly string _connectionString;
/// <summary>
/// 啟動程序
/// </summary>
private readonly string _applicationName;
/// <summary>
/// 輸出模板
/// </summary>
private readonly string _outputTemplate;
/// <summary>
/// 日志實例
/// </summary>
private ILogger _logger;
/// <summary>
/// 構造函數
/// </summary>
/// <param name="connectionString">Seq服務 URL地址</param>
public SerilogLogger(string connectionString)
{
this._connectionString = connectionString ?? string.Empty;
this._applicationName = Assembly.GetEntryAssembly()?.GetName().Name ?? string.Empty;
this._outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u4}] [LogType:{LogType}] [{ApplicationName}] [{SourceContext}] [{Module}] {Message:lj}{NewLine}{Exception}";
this._logger = ConfigureSeqLogger(); // 默認配置Seq日志記錄器
}
/// <summary>
/// 配置Seq服務日志記錄器
/// </summary>
/// <returns>Seq日志記錄器實例</returns>
public ILogger ConfigureSeqLogger()
{
try
{
// 若連接字符串為空,則使用控制臺日志
if (string.IsNullOrWhiteSpace(_connectionString))
{
return ConfigureConsoleLogger();
}
// 配置 Seq 日志記錄器
return new LoggerConfiguration()
.WriteTo.Seq(_connectionString) // 接入Seq日志服務
.Enrich.WithProperty("ApplicationName", _applicationName)
.Enrich.With(new UuidEnricher()) // 添加 UUID
.MinimumLevel.Verbose() // 設置最低日志級別為 Verbose
.CreateLogger();
}
catch
{
// 若配置失敗,創建控制臺日志
return ConfigureConsoleLogger();
}
}
/// <summary>
/// 配置控制臺日志記錄器
/// </summary>
/// <returns>控制臺日志記錄器實例</returns>
public ILogger ConfigureConsoleLogger()
{
try
{
return new LoggerConfiguration()
.WriteTo.Console(outputTemplate: _outputTemplate)
.Enrich.WithProperty("ApplicationName", _applicationName)
.Enrich.With(new UuidEnricher())
.MinimumLevel.Verbose()
.CreateLogger();
}
catch
{
// 若配置失敗,創建基礎控制臺日志
return new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
}
}
/// <summary>
/// 配置文件日志記錄器
/// </summary>
/// <returns>文件日志記錄器實例</returns>
public ILogger ConfigureFileLogger()
{
try
{
return new LoggerConfiguration()
.WriteTo.File(
path: "logs\\defaultLogs.log",
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30, // 保留30天
fileSizeLimitBytes: 5_000_000, // 單文件最大5MB
outputTemplate: _outputTemplate
)
.Enrich.WithProperty("ApplicationName", _applicationName)
.Enrich.With(new UuidEnricher())
.MinimumLevel.Verbose()
.CreateLogger();
}
catch
{
// 若配置失敗,創建控制臺日志
return ConfigureConsoleLogger();
}
}
/// <summary>
/// 獲取默認日志記錄器實例
/// </summary>
/// <returns>Seq日志記錄器實例</returns>
public ILogger GetLogger()
{
return _logger ?? ConfigureConsoleLogger();
}
}
四、創建Logger拓展類以及日志類型枚舉類
點擊查看代碼
/// <summary>
/// Serilog Logger Extensions
/// Provides extended logging methods with LogType and Module support
/// </summary>
public static class LoggerExtensions
{
#region Debug Methods
/// <summary>
/// Writes a debug log message with specified log type and module
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
public static void Debug(this ILogger logger, LogType logType, string module, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Debug(message);
}
/// <summary>
/// Writes a debug log message with specified log type, module and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Debug(this ILogger logger, LogType logType, string module, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Debug(message, propertyValues);
}
#endregion
#region Information Methods
/// <summary>
/// Writes an information log message with specified log type and module
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
public static void Information(this ILogger logger, LogType logType, string module, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Information(message);
}
/// <summary>
/// Writes an information log message with specified log type, module and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Information(this ILogger logger, LogType logType, string module, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Information(message, propertyValues);
}
#endregion
#region Warning Methods
/// <summary>
/// Writes a warning log message with specified log type and module
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
public static void Warning(this ILogger logger, LogType logType, string module, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Warning(message);
}
/// <summary>
/// Writes a warning log message with specified log type, module and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Warning(this ILogger logger, LogType logType, string module, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Warning(message, propertyValues);
}
#endregion
#region Error Methods
/// <summary>
/// Writes an error log message with specified log type and module
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
public static void Error(this ILogger logger, LogType logType, string module, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Error(message);
}
/// <summary>
/// Writes an error log message with specified log type, module and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Error(this ILogger logger, LogType logType, string module, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Error(message, propertyValues);
}
/// <summary>
/// Writes an error log message with specified log type, module and exception
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
public static void Error(this ILogger logger, LogType logType, string module, Exception exception, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Error(exception, message);
}
/// <summary>
/// Writes an error log message with specified log type, module, exception and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Error(this ILogger logger, LogType logType, string module, Exception exception, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Error(exception, message, propertyValues);
}
#endregion
#region Fatal Methods
/// <summary>
/// Writes a fatal log message with specified log type and module
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
public static void Fatal(this ILogger logger, LogType logType, string module, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Fatal(message);
}
/// <summary>
/// Writes a fatal log message with specified log type, module and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Fatal(this ILogger logger, LogType logType, string module, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Fatal(message, propertyValues);
}
/// <summary>
/// Writes a fatal log message with specified log type, module and exception
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
public static void Fatal(this ILogger logger, LogType logType, string module, Exception exception, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Fatal(exception, message);
}
/// <summary>
/// Writes a fatal log message with specified log type, module, exception and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Fatal(this ILogger logger, LogType logType, string module, Exception exception, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Fatal(exception, message, propertyValues);
}
#endregion
#region Verbose Methods
/// <summary>
/// Writes a verbose log message with specified log type and module
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
public static void Verbose(this ILogger logger, LogType logType, string module, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Verbose(message);
}
/// <summary>
/// Writes a verbose log message with specified log type, module and parameters
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="module">Module name where the log originates</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Verbose(this ILogger logger, LogType logType, string module, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", module ?? string.Empty)
.Verbose(message, propertyValues);
}
#endregion
#region Backward Compatibility Methods
/// <summary>
/// Writes a debug log message with specified log type (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
public static void Debug(this ILogger logger, LogType logType, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Debug(message);
}
/// <summary>
/// Writes a debug log message with specified log type and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Debug(this ILogger logger, LogType logType, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Debug(message, propertyValues);
}
/// <summary>
/// Writes an information log message with specified log type (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
public static void Information(this ILogger logger, LogType logType, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Information(message);
}
/// <summary>
/// Writes an information log message with specified log type and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Information(this ILogger logger, LogType logType, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Information(message, propertyValues);
}
/// <summary>
/// Writes a warning log message with specified log type (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
public static void Warning(this ILogger logger, LogType logType, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Warning(message);
}
/// <summary>
/// Writes a warning log message with specified log type and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Warning(this ILogger logger, LogType logType, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Warning(message, propertyValues);
}
/// <summary>
/// Writes an error log message with specified log type (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
public static void Error(this ILogger logger, LogType logType, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Error(message);
}
/// <summary>
/// Writes an error log message with specified log type and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Error(this ILogger logger, LogType logType, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Error(message, propertyValues);
}
/// <summary>
/// Writes an error log message with specified log type and exception (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
public static void Error(this ILogger logger, LogType logType, Exception exception, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Error(exception, message);
}
/// <summary>
/// Writes an error log message with specified log type, exception and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Error(this ILogger logger, LogType logType, Exception exception, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Error(exception, message, propertyValues);
}
/// <summary>
/// Writes a fatal log message with specified log type (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
public static void Fatal(this ILogger logger, LogType logType, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Fatal(message);
}
/// <summary>
/// Writes a fatal log message with specified log type and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Fatal(this ILogger logger, LogType logType, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Fatal(message, propertyValues);
}
/// <summary>
/// Writes a fatal log message with specified log type and exception (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
public static void Fatal(this ILogger logger, LogType logType, Exception exception, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Fatal(exception, message);
}
/// <summary>
/// Writes a fatal log message with specified log type, exception and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="exception">The exception to log</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Fatal(this ILogger logger, LogType logType, Exception exception, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Fatal(exception, message, propertyValues);
}
/// <summary>
/// Writes a verbose log message with specified log type (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
public static void Verbose(this ILogger logger, LogType logType, string message)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Verbose(message);
}
/// <summary>
/// Writes a verbose log message with specified log type and parameters (module will be empty)
/// </summary>
/// <param name="logger">The logger instance</param>
/// <param name="logType">Type of the log entry</param>
/// <param name="message">Log message template</param>
/// <param name="propertyValues">Parameters for the message template</param>
public static void Verbose(this ILogger logger, LogType logType, string message, params object[] propertyValues)
{
logger.ForContext("LogType", logType)
.ForContext("Module", string.Empty)
.Verbose(message, propertyValues);
}
#endregion
}
點擊查看代碼
/// <summary>
/// 日志類型(可選或自定義)
/// </summary>
public enum LogType
{
/// <summary>
/// 系統日志 - 系統啟動、關閉、配置變更等系統級操作
/// </summary>
System = 1,
/// <summary>
/// 操作日志 - 用戶業務操作、業務流程記錄
/// </summary>
Operation = 2,
/// <summary>
/// 硬件日志 - 設備狀態、硬件交互、傳感器等
/// </summary>
Hardware = 3,
/// <summary>
/// 安全日志 - 登錄認證、權限變更、安全事件等
/// </summary>
Security = 4,
}
五、寫入Prism容器,方便其它地方調用
點擊查看代碼
// protected override void RegisterTypes(IContainerRegistry containerRegistry) 方法
#region 注冊單例:通過 Prism 容器管理 日志實例
// 獲取 Seq服務URL
string connectionString = ConnectionString["Sequrl"]?["ConnectionString"]?.ToString() ?? string.Empty;
// 注冊時先初始化日志配置
var loggerInstance = new SerilogLogger(connectionString);
containerRegistry.RegisterSingleton<ISerilogLogger>(() => loggerInstance);
#endregion
點擊查看代碼
// 示例:記錄調試日志
// 從容器獲取日志實例:GetLogger 輸出方式,MainWindowViewModel調用上下文
ILogger logger = container.Resolve<ISerilogLogger>().GetLogger().ForContext<MainWindowViewModel>();
// 一、基本用法(等級 + 模塊 + 記錄文本)
logger.Debug(LogType.System, "Seq日志", "初始化日志模塊成功。");
// 二、參數用法(等級 + 模塊 + 消息模板 + 消息參數)
logger.Information(LogType.Operation, "訂單模塊", "購買{Product}成功!總計金額:{Amount}美元", "??倒I相機", "$6888.99");
六、Seq日志分析平臺


七、Seq服務申請 API Keys授權

八、基于 Seq.Api 實現自定義日志操作
點擊查看代碼
/// <summary>
/// Seq日志查詢接口
/// </summary>
public interface ISeqQueryService
{
/// <summary>
/// 按時間范圍查詢日志
/// </summary>
/// <param name="startTime">開始時間</param>
/// <param name="endTime">結束時間</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByTimeRangeAsync(DateTime startTime, DateTime endTime, int count = 1000);
/// <summary>
/// 按天數查詢日志(查詢最近N天的日志)
/// </summary>
/// <param name="days">天數</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByDaysAsync(int days, int count = 1000);
/// <summary>
/// 按屬性值查詢日志
/// </summary>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByPropertyAsync(string propertyName, string propertyValue, int count = 1000);
/// <summary>
/// 按日志等級查詢
/// </summary>
/// <param name="level">日志等級</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByLevelAsync(LogEventLevel level, int count = 1000);
/// <summary>
/// 組合查詢(時間范圍 + 日志等級 + 屬性值)
/// </summary>
/// <param name="startTime">開始時間</param>
/// <param name="endTime">結束時間</param>
/// <param name="level">日志等級</param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByTimeLevelAndPropertyAsync(DateTime startTime, DateTime endTime, LogEventLevel level, string propertyName, string propertyValue, int count = 1000);
/// <summary>
/// 組合查詢(時間范圍 + 屬性值)
/// </summary>
/// <param name="startTime">開始時間</param>
/// <param name="endTime">結束時間</param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByTimeAndPropertyAsync(DateTime startTime, DateTime endTime, string propertyName, string propertyValue, int count = 1000);
/// <summary>
/// 組合查詢(日志等級 + 屬性值)
/// </summary>
/// <param name="level">日志等級</param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryByLevelAndPropertyAsync(LogEventLevel level, string propertyName, string propertyValue, int count = 1000);
/// <summary>
/// 基礎查詢方法(僅使用filter條件)
/// </summary>
/// <param name="filter">過濾條件</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
Task<List<EventEntity>> QueryLogsAsync(string filter, int count);
}
點擊查看代碼
/// <summary>
/// Seq 日志查詢
/// 提供按時間、天數、屬性值、日志等級、返回數據條數的查詢功能
/// </summary>
public class SeqQueryService : IDisposable, ISeqQueryService
{
private readonly SeqConnection _connection;
private bool _disposed = false;
/// <summary>
/// 初始化Seq查詢服務
/// </summary>
/// <param name="serverUrl">Seq服務地址</param>
/// <param name="apiKey">API密鑰</param>
public SeqQueryService(string serverUrl, string apiKey)
{
_connection = new SeqConnection(serverUrl, apiKey);
}
/// <summary>
/// 按時間范圍查詢日志
/// </summary>
/// <param name="startTime">開始時間</param>
/// <param name="endTime">結束時間</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByTimeRangeAsync(DateTime startTime, DateTime endTime, int count = 1000)
{
// 確保時間轉換為UTC(Seq存儲的是UTC時間)
var fromTimeUtc = startTime.Kind == DateTimeKind.Utc ? startTime : startTime.ToUniversalTime();
var toTimeUtc = endTime.Kind == DateTimeKind.Utc ? endTime : endTime.ToUniversalTime();
// 使用Seq API專用的時間參數,避免filter拼接問題
var resultSet = _connection.Events.EnumerateAsync(
fromDateUtc: fromTimeUtc, // 專用的開始時間參數
toDateUtc: toTimeUtc, // 專用的結束時間參數
count: count,
render: true);
var logs = new List<EventEntity>();
await foreach (var logEvent in resultSet)
{
logs.Add(logEvent);
}
return logs;
}
/// <summary>
/// 按天數查詢日志(查詢最近N天的日志)
/// </summary>
/// <param name="days">天數</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByDaysAsync(int days, int count = 1000)
{
// 計算開始時間(當前時間往前推days天)
var startTime = DateTime.Now.AddDays(-days);
// 確保時間轉換為UTC
var fromTimeUtc = startTime.Kind == DateTimeKind.Utc ? startTime : startTime.ToUniversalTime();
// 使用Seq API專用的時間參數
var resultSet = _connection.Events.EnumerateAsync(
fromDateUtc: fromTimeUtc, // 專用的開始時間參數
count: count,
render: true);
var logs = new List<EventEntity>();
await foreach (var logEvent in resultSet)
{
logs.Add(logEvent);
}
return logs;
}
/// <summary>
/// 按屬性值查詢日志
/// </summary>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByPropertyAsync(string propertyName, string propertyValue, int count = 1000)
{
var filter = $"{propertyName} = '{propertyValue}'";
return await QueryLogsAsync(filter, count);
}
/// <summary>
/// 按日志等級查詢
/// </summary>
/// <param name="level">日志等級(如:Information、Error、Warning等)</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByLevelAsync(LogEventLevel level, int count = 1000)
{
var filter = $"@Level = '{level}'";
return await QueryLogsAsync(filter, count);
}
/// <summary>
/// 組合查詢(時間范圍 + 日志等級 + 屬性值)
/// </summary>
/// <param name="startTime">開始時間</param>
/// <param name="endTime">結束時間</param>
/// <param name="level">日志等級</param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByTimeLevelAndPropertyAsync(DateTime startTime, DateTime endTime, LogEventLevel level, string propertyName, string propertyValue, int count = 1000)
{
// 確保時間轉換為UTC
var fromTimeUtc = startTime.Kind == DateTimeKind.Utc ? startTime : startTime.ToUniversalTime();
var toTimeUtc = endTime.Kind == DateTimeKind.Utc ? endTime : endTime.ToUniversalTime();
// 構建屬性過濾條件
var filter = $"@Level = '{level}' and {propertyName} = '{propertyValue}'";
// 使用Seq API專用的時間參數和filter組合
var resultSet = _connection.Events.EnumerateAsync(
fromDateUtc: fromTimeUtc,
toDateUtc: toTimeUtc,
filter: filter,
count: count,
render: true);
var logs = new List<EventEntity>();
await foreach (var logEvent in resultSet)
{
logs.Add(logEvent);
}
return logs;
}
/// <summary>
/// 組合查詢(時間范圍 + 屬性值)
/// </summary>
/// <param name="startTime">開始時間</param>
/// <param name="endTime">結束時間</param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByTimeAndPropertyAsync(DateTime startTime, DateTime endTime, string propertyName, string propertyValue, int count = 1000)
{
// 確保時間轉換為UTC
var fromTimeUtc = startTime.Kind == DateTimeKind.Utc ? startTime : startTime.ToUniversalTime();
var toTimeUtc = endTime.Kind == DateTimeKind.Utc ? endTime : endTime.ToUniversalTime();
// 構建屬性過濾條件
var filter = $"{propertyName} = '{propertyValue}'";
// 使用Seq API專用的時間參數和filter組合
var resultSet = _connection.Events.EnumerateAsync(
fromDateUtc: fromTimeUtc,
toDateUtc: toTimeUtc,
filter: filter,
count: count,
render: true);
var logs = new List<EventEntity>();
await foreach (var logEvent in resultSet)
{
logs.Add(logEvent);
}
return logs;
}
/// <summary>
/// 組合查詢(日志等級 + 屬性值)
/// </summary>
/// <param name="level">日志等級</param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryByLevelAndPropertyAsync(LogEventLevel level, string propertyName, string propertyValue, int count = 1000)
{
var filter = $"@Level = '{level}' and {propertyName} = '{propertyValue}'";
return await QueryLogsAsync(filter, count);
}
/// <summary>
/// 基礎查詢方法(僅使用filter條件)
/// </summary>
/// <param name="filter">過濾條件,如:"PropertyName = 'Value'"</param>
/// <param name="count">返回數據條數</param>
/// <returns>日志事件列表</returns>
public async Task<List<EventEntity>> QueryLogsAsync(string filter, int count)
{
var logs = new List<EventEntity>();
var resultSet = _connection.Events.EnumerateAsync(
render: true,
count: count,
filter: filter);
await foreach (var logEvent in resultSet)
{
logs.Add(logEvent);
}
return logs;
}
/// <summary>
/// 釋放資源
/// </summary>
public void Dispose()
{
if (!_disposed)
{
_connection?.Dispose();
_disposed = true;
}
}
}
九、參考資料
Seq官方文檔:https://datalust.co/
Seq.Api文檔:https://github.com/datalust/seq-api

浙公網安備 33010602011771號