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}美元", "海康工业相机", "$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
2025-11-09 15:37:24【出处】:https://www.cnblogs.com/dosswy/p/19159138
=======================================================================================
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。(●'◡'●)
因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/19204351
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
浙公网安备 33010602011771号