Layout.WatchDog.NET.Storages.SqlServer 1.5.0-beta.4

This is a prerelease version of Layout.WatchDog.NET.Storages.SqlServer.
dotnet add package Layout.WatchDog.NET.Storages.SqlServer --version 1.5.0-beta.4
                    
NuGet\Install-Package Layout.WatchDog.NET.Storages.SqlServer -Version 1.5.0-beta.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Layout.WatchDog.NET.Storages.SqlServer" Version="1.5.0-beta.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Layout.WatchDog.NET.Storages.SqlServer" Version="1.5.0-beta.4" />
                    
Directory.Packages.props
<PackageReference Include="Layout.WatchDog.NET.Storages.SqlServer" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Layout.WatchDog.NET.Storages.SqlServer --version 1.5.0-beta.4
                    
#r "nuget: Layout.WatchDog.NET.Storages.SqlServer, 1.5.0-beta.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Layout.WatchDog.NET.Storages.SqlServer@1.5.0-beta.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Layout.WatchDog.NET.Storages.SqlServer&version=1.5.0-beta.4&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Layout.WatchDog.NET.Storages.SqlServer&version=1.5.0-beta.4&prerelease
                    
Install as a Cake Tool

WatchDog

WatchDog 版本 下载量 MIT 许可证

简介

WatchDog 是一个专为 ASP.NET Core Web 应用程序和 API 设计的实时消息、事件、HTTP(请求和响应)和异常记录器和查看器。它允许开发人员记录和查看消息、事件、对其 Web 应用程序的 HTTP 请求以及在运行时捕获的异常,全部实时显示。

WatchDog 利用 SignalR 实现实时通信,默认使用轻量级数据库 LiteDB(无需配置),同时支持扩展至外部数据库(MSSQL, MySQL, PostgreSQL, MongoDB, SQLite)。

主要功能

  • 实时 HTTP 监控:记录所有请求和响应的详细信息。
  • 异常捕获:自动捕获并记录应用程序运行时的异常。
  • 代码内日志:支持在业务代码中手动记录消息和事件。
  • 实时仪表盘:提供 Web 界面 (/watchdog) 查看日志,支持搜索和过滤。
  • 多种数据库支持:内置 LiteDB,支持一键切换至主流关系型数据库、MongoDB 与 SQLite。
  • 日志自动清理:支持配置定时自动清理旧日志。

截图预览

  • 登录页面

Login

  • 请求与响应查看器

请求和响应查看器

  • 异常日志示例

异常示例详情

安装

方式一:.NET CLI

你需要安装 Layout.WatchDog.NET 核心包。在终端运行:

dotnet add package Layout.WatchDog.NET --version 1.5.0-beta.4

当前发布的是预发布版 1.5.0-beta.4,必须显式指定版本号(或加 --prerelease),否则默认只会装到稳定版。

如需使用外部数据库(MSSQL / MySQL / PostgreSQL / SQLite / MongoDB),额外安装对应的 Storage 扩展包:

# 例如使用 PostgreSQL
dotnet add package Layout.WatchDog.NET.Storages.PostgreSql --version 1.5.0-beta.4

可用 Storage 包:

驱动 包 ID
SQL Server Layout.WatchDog.NET.Storages.SqlServer
MySQL Layout.WatchDog.NET.Storages.MySql
PostgreSQL Layout.WatchDog.NET.Storages.PostgreSql
SQLite Layout.WatchDog.NET.Storages.Sqlite
MongoDB Layout.WatchDog.NET.Storages.MongoDb

默认 LiteDB 后端内置于核心包,无需额外安装。各 Storage 包的详细用法见数据库后端接入指南。

方式二:NuGet 包管理器

除了 dotnet cli 安装,还可以通过 nuget 包管理器安装:

Install-Package Layout.WatchDog.NET --version 1.5.0-beta.4
# 如需外部数据库,例如 PostgreSQL:
Install-Package Layout.WatchDog.NET.Storages.PostgreSql --version 1.5.0-beta.4

方式三:源码编译(可选)

本仓库以 Layout.WatchDog.NET 为包 ID 发布持续维护的版本,同时面向 .NET 8 与 .NET 10 编译。上游 WatchDog.NET 的最新公开版本 1.4.12 存在已知依赖安全隐患,请勿继续使用。

如果你需要自行打包(例如发布到内部 NuGet 源),版本号定义在 src/WatchDog/WatchDog.csproj 中:

# 克隆仓库
git clone https://gitee.com/dolayout/watch-dog.git
cd watch-dog
# 打包(核心包 + 5 个 Storage 扩展包)
dotnet pack src/WatchDog/WatchDog.csproj -c Release -o ./artifacts
for p in SqlServer MySql PostgreSql Sqlite MongoDb; do
  dotnet pack "src/WatchDog.Storages.$p/WatchDog.Storages.$p.csproj" -c Release -o ./artifacts
done

发布顺序:先推核心包 Layout.WatchDog.NET,再推 Storage 包 —— 后者的 nuspec 依赖 Layout.WatchDog.NET >= 1.5.0-beta.4。

快速开始

1. 注册服务

在 Program.cs 中注册 WatchDog 服务。

using WatchDog;

// 在 Program.cs 中 (适用于 .NET 6+)
builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "Qwerty@123"));

2. 配置中间件

在 HTTP 请求管道中启用 WatchDog 中间件。建议在 UseRouting, UseAuthentication, UseAuthorization 之后添加。

var app = builder.Build();

app.UseWatchDog();

异常日志中间件已由 UseWatchDog() 内部自动挂载,无需手动调用。

3. 查看日志

启动你的应用程序,访问 /watchdog 路径(例如:https://localhost:5000/watchdog),使用配置的用户名和密码登录即可查看实时日志。

进阶配置

从 appsettings.json 读取配置(可选)

除纯代码配置外,WatchDog 还支持从 appsettings.json(或任意 IConfiguration 来源)绑定配置。调用 FromConfiguration 后,再用 With* 方法覆盖个别字段:

{
  "WatchDog": {
    "Username": "admin",
    "Password": "Qwerty@123",
    "Blacklist": ["api/auth/login", "Test/testPost"],
    "UseRegexForBlacklisting": false,
    "IsAutoClear": true,
    "ClearTimeSchedule": "Monthly",
    "CorsPolicy": "",
    "UseOutputCache": false,
    "Serializer": "Default",
    "WorkerId": null,
    "Dashboard": {
      "Enabled": true,
      "BasePath": "/watchdog",
      "LegacyPath": "/watchdog-legacy",
      "KeepLegacyPage": true,
      "FallbackToEmbeddedPage": true,
      "AlwaysExposeApi": false,
      "DefaultLocale": "en",
      "DefaultTheme": "system",
      "Features": {
        "Requests": true,
        "Exceptions": true,
        "InCode": true,
        "ClearLogs": true,
        "Compact": true,
        "Metrics": false,
        "SecureHub": false
      }
    }
  }
}
builder.Services.AddWatchDog(wd => wd
    .FromConfiguration(builder.Configuration.GetSection("WatchDog"))
    .WithAutoClear(WatchDogAutoClearScheduleEnum.Monthly));

各配置项含义(键名大小写不敏感,与 WatchDogOptions 属性同名):

键 类型 默认值 说明
Username / Password string 空 看板登录凭据,必填,为空时启动抛 OptionsValidationException
Blacklist string[] [] 不记录日志的路径列表,必须是 JSON 数组;写成 "a, b" 只会得到一条字面量路径
UseRegexForBlacklisting bool false Blacklist 条目按正则解释(等价 UseRegexBlacklist())
IsAutoClear bool false 启用后台定时清理日志
ClearTimeSchedule string Weekly Daily / Weekly / Monthly / Quarterly / Hourly / Every6Hours / Every12Hours
CorsPolicy string 空 在 WatchDog 管道内应用的 CORS 策略名
UseOutputCache bool false 启用输出缓存中间件(仅 .NET 8+ 生效)
Serializer string Default Newtonsoft 仅为源码兼容保留,行为与 Default 一致
WorkerId int? null 雪花 ID 的 Worker ID,0-1023;多进程写同一库时必填且互不相同
Dashboard.* object 见下 独立看板配置,字段含义见启用独立看板
Dashboard.Features.* bool 见下 看板能力开关,字段含义见看板能力开关

绑定是"打底",With* 是"覆盖":先 FromConfiguration 读 JSON,再用 With* 改个别字段,不会丢失 JSON 里其余配置。TimeProvider 无法从 JSON 绑定,保持 null 即使用系统时钟。

不要把 ExternalDbConnString / DbDriverOption 写进 JSON:这两个字段由 Storage 包的 Use*() 写入,不是"选择后端"的开关。只写这两项而不调 Use*(),AddWatchDog 会直接抛 InvalidOperationException(不会静默退回 LiteDB)。详见数据库后端接入指南。

AddWatchDog 只能调用一次:它每次都会创建一套全新的 WatchDogOptions 并注册为单例。写成两次调用(例如一次只做 FromConfiguration、另一次只做 WithAuth)时,后一次的注册会覆盖前一次——JSON 里配的 Blacklist / Dashboard / IsAutoClear 等会静默丢失;若配置节里没有账号密码,第一次调用还会因校验失败直接抛 OptionsValidationException。beta.4 起重复调用会在启动时抛 InvalidOperationException。所有配置必须写在同一个回调里,顺序为「先 FromConfiguration,后 With*」。

设置外部数据库(可选)

WatchDog 默认使用 LiteDB(零配置,内置于核心包)。如需切换到 MSSQL / MySQL / PostgreSQL / MongoDB / SQLite,需引用对应的 Storage 扩展包并调用 Use*() 方法:

// 1. 安装 NuGet 包:Layout.WatchDog.NET.Storages.PostgreSql
// 2. using WatchDog.Storages.PostgreSql;
builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "Qwerty@123")
    .UsePostgreSql("Server=localhost;Database=WatchDogDb;User Id=postgres;Password=root;"));

1.5.0-beta.4 破坏性变更:WithExternalDb(driver, connStr) 方法已移除,改为各 Storage 包提供独立的 Use*() 方法。核心包不再传递依赖数据库驱动 NuGet 包,用户按需引用。

各数据库的连接串示例、表结构、分页与清表行为、压缩支持、依赖版本等详见 数据库后端接入指南。

设置自动清除日志(可选)

builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "Qwerty@123")
    .WithAutoClear(WatchDogAutoClearScheduleEnum.Weekly)); // 默认每周

手动压缩数据文件(LiteDB / SQLite)

LiteDB 的 DeleteAll 只是把数据页标记为空闲,数据文件本身不会变小。清空日志后如果不重写文件,watchdog.db 会一直保持它曾经达到的最大体积。SQLite 的 DELETE 同理,文件不会自动缩小,需要 VACUUM 重写文件。

ClearLogs 与后台自动清理在删除成功后会各自自动压缩一次(LiteDB 调 Compact、SQLite 调 VACUUM),因此日常使用无需干预。下面这个端点用于手动触发,仅在 LiteDB 与 SQLite 后端有效:

GET /WTCHDwatchpage/Compact

需要先登录查看器(与日志页面共用会话),返回 JSON 布尔值。压缩只重写数据文件,不会删除任何日志记录。

# 1. 登录并保存会话 Cookie
curl -c cookies.txt -X POST "https://localhost:5000/WTCHDwatchpage/Auth" \
     --data-urlencode "username=admin" \
     --data-urlencode "password=Qwerty@123"

# 2. 触发压缩
curl -b cookies.txt "https://localhost:5000/WTCHDwatchpage/Compact"
# => true

返回 false 的常见原因:

  • 数据文件不存在(还没有写入过日志)。
  • 有其它进程以非共享方式占用了文件,例如 LiteDB Studio 直接打开了 watchdog.db,或另一个应用实例正在运行。关掉占用方后重试即可。
  • 使用的是 MSSQL / MySQL / PostgreSQL 或 MongoDB 后端。这几种后端不需要压缩,该端点恒返回 false。

调用前请注意:压缩期间会阻塞所有日志读写,数据库越大耗时越长(几十 MB 级别为秒级)。LiteDB 压缩还会生成一个约等于原库大小的备份文件、完成后自动删除,因此瞬时磁盘占用接近翻倍;SQLite 的 VACUUM 则在临时文件中重写后替换原文件。建议在业务低峰执行。

适用场景:

  • 升级后一次性治理:旧版本清空日志不压缩,长期运行过的实例文件已经膨胀。升级后可调用一次回收这部分空间,且无需丢弃当前日志。
  • 磁盘空间告急:需要立即腾出空间,同时希望保留最近的日志用于排查。

实测参考:50 条日志的数据库清空前后均为 90112 bytes,压缩后降至 40960 bytes。

多实例部署:设置 Worker ID(可选)

日志记录的 Id 不再由数据库自增,而是由应用生成一个 64 位整数(雪花算法:41 位毫秒时间 + 10 位 Worker ID + 12 位序列号)。因此即使清空日志或压缩 LiteDB 数据文件,新记录的 Id 依然大于旧记录,排序不会错乱。

单进程、单机部署无需配置:默认的 Worker ID 由机器名哈希与进程号推导得到。

只有多个进程写入同一个数据库时(同一个 LiteDB 文件的多个共享连接,或多个实例连同一个 MongoDB 库),才需要显式指定,以保证 Id 全局有序:

builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "Qwerty@123")
    .WithWorkerId(1)); // 0-1023,同一个库上的每个进程必须不同

也可以不改代码,用环境变量为每个实例注入:

# Linux / macOS
WATCHDOG_WORKER_ID=2 dotnet MyApp.dll
# Windows PowerShell
$env:WATCHDOG_WORKER_ID = 2

说明:

  • 取值范围 0-1023,超出会被限制到该区间;代码中的显式配置优先于环境变量。
  • 所有后端(LiteDB / SQLite / MSSQL / MySQL / PostgreSQL / MongoDB)均使用雪花算法生成 Id,配置此项对所有后端生效。
  • Worker ID 冲突的后果仅限于两个进程之间的 Id 排序可能交错,日志本身不会丢失或错乱。
  • Id 是 64 位整数,超过 JavaScript 的安全整数范围(2^53)。如果需要在浏览器端读取 Id,请按字符串传输,否则会丢精度。WatchDog 自带页面不读取该字段。
  • 需要从 Id 反推生成时间时,id >> 22 即为相对 2024-01-01 UTC 的毫秒数。

从旧版本升级:LiteDB 中 Id 为 Int32 的历史记录会在首次打开数据库时自动宽化为 Int64,数据不丢失;旧记录的 Id 数值本身不变,因此会排在新记录之后。SQL 的旧 INT 自增列与 MongoDB 的存量数据均无需迁移。

可选配置项

所有配置项都在 AddWatchDog 阶段用 Fluent Builder 声明,UseWatchDog() 无参调用:

builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "Qwerty@123")
    // 黑名单:路径数组,不记录这些指定 Endpoint 端点/接口
    .WithBlacklist("Test/testPost", "api/auth/login")
    // CORS 策略名称
    .WithCorsPolicy("MyCorsPolicy")
    // 应用程序使用 asp.net core8+ 输出缓存
    .WithOutputCache()
    // 启用正则表达式黑名单
    .UseRegexBlacklist());

JSON 序列化器:WatchDog 默认使用内置的 System.Text.Json(无需额外配置)。WatchDogSerializerEnum.Newtonsoft 仅为源码兼容保留,行为与默认一致。

启用独立看板(可选)

包里内置一个可选的独立看板(Vue 实现),可替代原来的内嵌页面。默认关闭,关闭时行为与之前完全一致。

builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "******")
    // 打开独立看板
    .WithDashboard(d => d.Enabled = true));
  • 入口:/watchdog(看板)、/watchdog-legacy(原内嵌页面)
  • 数据接口:/watchdog-api/v1/*,与旧端点共用同一数据库与登录会话
  • 前端资源随程序集内嵌,无需额外部署前端,也不需要单独起服务
  • 若打包时未包含看板产物,运行时会自动降级回内嵌页面并记一条 warning

其他可选配置:

builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "******")
    .WithDashboard(d =>
    {
        d.Enabled = true;
        d.BasePath = "/wd";                 // 自定义挂载路径
        d.KeepLegacyPage = false;          // 不再暴露原页面
        d.FallbackToEmbeddedPage = false;  // 产物缺失时直接抛异常,而不是降级
        d.DefaultLocale = "zh-Hans";       // 首次访问的默认语言:en / zh-Hans
        d.DefaultTheme = "dark";           // 首次访问的默认主题:system / dark / light
    }));

看板能力开关(Features)

看板通过 Features 声明启用哪些能力,未开启的入口在界面上直接隐藏:

builder.Services.AddWatchDog(wd => wd
    .WithAuth("admin", "******")
    .WithDashboard(d =>
    {
        d.Enabled = true;
        d.Features.Requests = true;    // HTTP 请求/响应(默认开)
        d.Features.Exceptions = true;  // 异常日志(默认开)
        d.Features.InCode = true;      // 代码内日志(默认开)
        d.Features.ClearLogs = true;   // 清空日志(默认开)
        d.Features.Compact = true;     // 手动压缩(默认开)
        d.Features.Metrics = true;     // 节点资源监控(默认关)
        d.Features.SecureHub = true;   // SignalR 强制会话鉴权(默认关)
    }));

节点资源监控(可选)

开启 Features.Metrics 后,看板提供 Infra 总览页(/infra/overview),并对外提供节点级资源快照接口:

GET /watchdog-api/v1/metrics
  • 节点级:CPU、内存、磁盘、网络、load average(Windows / Linux / macOS 各自实现;缺失项以 unavailable 声明,不用 0 冒充真实值)
  • 进程级:CPU、内存、GC、线程、句柄、线程池、运行时长
  • 首次采样没有速率基线时返回 null 并登记 unavailable;进程 CPU 沿用单核口径,可超过 100%
  • 未开启 Features.Metrics 时该接口返回 404

看板内提供主题(跟随系统 / 深色 / 浅色)与语言(EN / 中文)切换,选择存在浏览器里; 上面的默认值只在用户从未选择过时生效。原内嵌页面 /watchdog-legacy 不受影响。

记录自定义日志

你可以在代码的任何位置调用 WatchLogger 来记录日志:

using WatchDog;

// 记录普通信息
WatchLogger.Log("用户登录成功");

// 记录警告
WatchLogger.LogWarning("请求频率过高");

// 记录错误
WatchLogger.LogError("处理订单失败", eventId: "Order_001");

集成 Microsoft ILogger

你还可以将标准的 ILogger 日志汇总到 WatchDog 中:

// .NET 6+ 在 Program.cs 中配置
builder.Logging.AddWatchDogLogger();

项目结构

该项目主要包含以下模块:

  • src/WatchDog/:核心库源码(Layout.WatchDog.NET,内置 LiteDB 后端与看板嵌入资源宿主)。
    • Extensions/:AddWatchDog / UseWatchDog 入口与 Fluent Builder。
    • Validation/:启动期配置校验。
    • src/Controllers/:包含处理日志查看请求的控制器。
    • src/Storages/:默认 LiteDB 存储实现(IWatchDogStorage)。
    • src/Helpers/:日志 ID 生成器、分页、节点指标采集等工具。
    • src/Hubs/:SignalR 集线器,用于实时推送日志。
    • src/Models/:数据模型定义与统一配置模型 WatchDogOptions。
    • src/Services/:后台自动清理服务等。
    • src/WatchPage/:内嵌前端页面(由 /WTCHDGstatics 提供)。
    • src/Dashboard/:Vue 看板构建产物(内嵌为资源)。
  • src/WatchDog.Storages.SqlServer/、.MySql/、.PostgreSql/、.Sqlite/、.MongoDb/:外部数据库 Storage 扩展包,各自只依赖一个驱动。
  • src/WatchDog.Dashboard/:独立看板前端源码(Vue 3 + Vite + Tailwind)。
  • tests/Test.WatchDog.API/:API 项目演示。
  • tests/Test.WatchDog.MVC/:MVC 项目演示。

贡献

如果你发现了 Bug 或者希望增加新功能:

  1. Fork 本仓库。
  2. 创建你的特性分支 (git checkout -b feature/AmazingFeature)。
  3. 提交你的更改 (git commit -m 'Add some AmazingFeature')。
  4. 推送到分支 (git push origin feature/AmazingFeature)。
  5. 发起 Pull Request。

致谢


许可证:本项目采用 MIT 许可证。

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.5.0-beta.4 37 10/31/2026