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}美元", "海康工業相機", "$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