日志成海,何以检索:Serilog 解锁 .NET 日志可查询新范式

线上出问题,你远程桌面连上服务器,打开日志文件夹,用记事本打开 .txt 文件,Ctrl+F 搜 "ERROR"。好不容易找到一行关键异常,却不知道它属于哪个请求、哪个用户、从哪台服务器来------上下文要么没记,要么散落在滚动条之间。这就是纯文本日志的困局:人勉强能看,但机器几乎无法结构化检索。

Serilog 为 .NET 带来结构化日志 ,把日志变成携带属性的完整事件。配合 Seq ------一个带网页界面的日志服务器------你可以让多台服务器的日志统一汇聚,在浏览器里搜索、过滤、分析。哪台机器出问题、某个订单的全链路日志,一秒钟定位。日志从此不再是"文本文件",而是一个可查询的可观测数据源。我们从一个控制台程序开始,让你立刻看到效果。

Serilog 是什么

Serilog 是面向 .NET 的开源诊断日志库

官网:https://serilog.nethttps://serilog.net

GitHub:

https://github.com/serilog/seriloghttps://github.com/serilog/serilog

它解决的核心工程问题:用结构化事件替代纯文本日志,使日志易于被机器检索、聚合和分析,同时保持对人类友好的阅读体验

四条核心机制与工程价值:

  1. 消息模板 + 属性捕获Log.Information("订单 {OrderId} 已支付", order.Id) 会将 OrderId 作为结构化属性存储,而不只是拼成字符串。

  2. Sink(输出适配器)架构:通过 Sink 将日志输出到文件、控制台、数据库、Elasticsearch、Seq 等数十种目标,切换目标只需更换 Sink,无需改动打点代码。

  3. 延迟渲染与高性能:只记录模板和属性,真正的消息字符串在输出时才由 Sink 生成,且大量 Sink 支持异步批处理,对应用性能影响可控。

  4. 丰富的扩展生态:官方及社区提供了 100+ Sink 和 Enricher(上下文增强器),可自动附加机器名、线程ID、HTTP请求信息等,极少代码即可构建全面的可观测数据。

授权情况 :Serilog 完全开源,采用 Apache License 2.0 ,可免费用于商业项目,无任何功能受限的"商业版"。配套的可视化日志服务器 Seq 有免费版和付费版,但 Serilog 本身不受限制,不需要购买许可。

怎么引入

安装(在 Visual Studio 的 NuGet 包管理器中操作,或执行以下命令):

复制代码
dotnet add package Serilog                              # 核心库,提供结构化打点能力
dotnet add package Serilog.Sinks.Console                # 输出到控制台,开发调试实时看
dotnet add package Serilog.Sinks.File                   # 输出到本地文件,持久化兜底
dotnet add package Serilog.Sinks.Seq                    # 发送到 Seq 服务器,浏览器集中查询

最小接入配置(Program.cs)

cs 复制代码
using Serilog;

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/app.txt", rollingInterval: RollingInterval.Day)
    .WriteTo.Seq("http://localhost:5341")
    .CreateLogger();

Log.Information("控制台、文件、Seq 三路输出测试");
Log.CloseAndFlush();

快速上手:一个示例演示三路输出

下面的示例完整展示"控制台看、文件留、Seq 查"的效果。所有代码在一个 .NET 8 控制台程序中即可运行。

Seq 安装

  • 下载地址:

https://datalust.co/downloadhttps://datalust.co/download

  • Windows 选择 .msi 安装包,一路下一步,装完自动后台运行。

  • 验证:浏览器打开 http://localhost:5341,看到 Seq 界面表示启动成功。

  • 也可用 Docker:docker run -d --name seq -e ACCEPT_EULA=Y -p 5341:80 datalust/seq

关于商用:Seq 免费版支持单用户,搜索、过滤、事件查看、仪表盘、告警等核心功能完整,个人学习和开发完全够用。多用户权限、SSO、集群等高阶功能需付费版,团队协作按需升级。

完整代码(Program.cs)

cs 复制代码
using Serilog;
using Serilog.Core;
using Serilog.Events;
using System.Net;
using System.Net.Sockets;

// 配置 Serilog:三路输出 + 全局属性
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .Enrich.WithMachineName()
    .Enrich.With<LocalIpEnricher>()
    .WriteTo.Console(outputTemplate:
        "[{Timestamp:HH:mm:ss} {Level:u3} {MachineName}/{LocalIP}] {Message:lj}{NewLine}{Exception}")
    .WriteTo.File("logs/app.txt",
        rollingInterval: RollingInterval.Day,
        retainedFileCountLimit: 7,
        outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {MachineName}/{LocalIP} {Message:lj} {Properties:j}{NewLine}{Exception}")
    .WriteTo.Seq("http://localhost:5341",
        restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information)
    .CreateLogger();

// 模拟业务打点
Log.Information("========== 订单服务启动 ==========");

var orders = new[] { 1001, 1002, 1003 };
foreach (var orderId in orders)
{
    using (Serilog.Context.LogContext.PushProperty("OrderId", orderId))
    {
        Log.Information("开始处理订单");
        Thread.Sleep(200);
        if (orderId == 1002)
            Log.Warning("订单 {OrderId} 触发风控检查", orderId);
        Log.Information("订单处理完成");
    }
}

Log.Information("========== 本轮处理结束 ==========");
Log.CloseAndFlush();

Console.WriteLine("日志已输出到控制台、文件、Seq,按任意键退出...");
Console.ReadKey();

// 自定义 Enricher:类必须放在顶级语句后面
public class LocalIpEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
        var ip = Dns.GetHostEntry(Dns.GetHostName())
            .AddressList
            .FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork)?
            .ToString() ?? "127.0.0.1";
        logEvent.AddPropertyIfAbsent(pf.CreateProperty("LocalIP", ip));
    }
}

关于商用:Seq 免费版支持单用户,搜索、过滤、事件查看、仪表盘、告警等核心功能完整,个人学习和开发完全够用。多用户权限、SSO、集群等高阶功能需付费版,团队协作按需升级。

验证三路输出

  • 控制台:运行程序,窗口实时打印带机器名、IP 的日志。
  • 文件 :打开 logs\app{日期}.txt,每行是一条 JSON,包含 OrderId 等属性,可长期留存。
  • Seq :浏览器访问 http://localhost:5341,所有日志集中展示。搜索 OrderId = 1002,该订单所有日志立即呈现;搜索 @Level = "Warning",只看警告;搜索 MachineName = "你的机器名",多机部署时只看某台服务器的日志。

Seq 架构示意

Seq 的部署架构非常简单,本质是一个"收日志的网站":

cs 复制代码
┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│  服务器 A     │   │  服务器 B     │   │  服务器 C     │
│  Serilog     │   │  Serilog     │   │  Serilog     │
│  + MachineName│  │  + MachineName│  │  + MachineName│
│  + LocalIP   │   │  + LocalIP   │   │  + LocalIP   │
└──────┬───────┘   └──────┬───────┘   └──────┬───────┘
       │                  │                  │
       │    结构化日志       │                  │
       └──────────────────┼──────────────────┘
                          │
                          ▼
              ┌─────────────────────┐
              │      Seq 服务器      │
              │  http://seq:5341    │
              │                     │
              │  • 接收并存储日志     │
              │  • 提供 Web 查询界面  │
              │  • 支持过滤、搜索     │
              └──────────┬──────────┘
                         │
                         ▼
              ┌─────────────────────┐
              │    你的浏览器         │
              │  http://seq:5341    │
              │                     │
              │  全局搜索、实时查看    │
              └─────────────────────┘

每台应用服务器只需要在 Program.cs 里加一行 .WriteTo.Seq("http://seq服务器地址:5341"),日志就会自动发送过去。Seq 本身是一个独立的进程(Windows 服务或 Docker 容器),提供类似数据库的查询能力,让你用浏览器取代记事本和远程桌面。

常见报错

适用场景

  • 单机应用:控制台 + 文件足够,开发调试方便,生产留 JSON 文件备查。

  • 多服务器:所有服务用同样的 Enricher 配置,日志统一发到 Seq。浏览器中按机器名、业务Id 搜索,故障定位从数小时降到秒级。

  • 高并发:Seq Sink 内置内存缓冲与自动重连,Seq 暂不可达时不丢日志;加上文件兜底双保险。

  • 不适用场景:已有 ELK 等平台的,可不用 Seq,但结构化打点方式完全一样,只需把 Sink 换成 Elasticsearch。

前置条件:Seq 服务器需能被所有应用服务器访问;生产环境建议为 Seq 配置 HTTPS 和登录认证(免费版支持单用户)。

实战建议

坑位1:拼字符串导致属性丢失 错误:Log.Information("用户 " + name + " 登录")修复:Log.Information("用户 {UserName} 登录", name){UserName} 自动成为属性。

坑位2:文件未限制级别占满磁盘 错误:生产配 Verbose,海量 Debug 日志写满硬盘。修复:生产设 Warning,或对文件单独限制 .WriteTo.File("...", restrictedToMinimumLevel: LogEventLevel.Warning),并配置滚动和保留天数。

坑位3:只依赖 Seq,无本地兜底 错误:Seq 宕机同时进程崩溃,内存日志丢失。修复:始终加 .WriteTo.File() 双写,文件作为永久存档和容灾备份。

选型建议

果断用 Serilog + Seq 的场景

  • .NET 项目,希望日志可查询,不再翻记事本。

  • 多机部署,需要集中看日志,讨厌逐台远程。

  • 团队不限,免费版 Seq 足够开发测试和个人使用。

可执行决策:新项目直接 Serilog + File + Seq,几小时接入。已有项目从关键模块开始替换,逐步享受结构化日志的红利。

从一个控制台程序开始,Serilog 让日志从无序文本变成了结构化属性。喜欢可视化的同学,Seq 把多台机器的日志汇集到一个浏览器标签页里;不想折腾额外服务的,只用文件 Sink 也完全够用 ------哪怕只是把 Debug.WriteLine 换成 Log.Information("处理订单 {OrderId}", id),然后加一行 .WriteTo.File("logs/app.txt"),你的日志就已经是结构化的 JSON,每一条都带属性,将来导入任何平台都无缝对接。

落地建议 :今天就给项目加上 Serilog,至少配一个文件输出,所有日志用 {属性} 模板。Seq 是可选项,按需再上。哪怕现在只有一台服务器、只写本地文件,你也已经拥有了日志可查询的基因。

相关推荐
SelectDB13 小时前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
zzzzzz3102 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220703 天前
如何搭建本地yum源(上)
运维
大树886 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠6 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz6 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智6 天前
ARP代理--工作原理
运维·网络·arp·arp代理