Layout.WatchDog.NET
1.5.0-beta.3
dotnet add package Layout.WatchDog.NET --version 1.5.0-beta.3
NuGet\Install-Package Layout.WatchDog.NET -Version 1.5.0-beta.3
<PackageReference Include="Layout.WatchDog.NET" Version="1.5.0-beta.3" />
<PackageVersion Include="Layout.WatchDog.NET" Version="1.5.0-beta.3" />
<PackageReference Include="Layout.WatchDog.NET" />
paket add Layout.WatchDog.NET --version 1.5.0-beta.3
#r "nuget: Layout.WatchDog.NET, 1.5.0-beta.3"
#:package Layout.WatchDog.NET@1.5.0-beta.3
#addin nuget:?package=Layout.WatchDog.NET&version=1.5.0-beta.3&prerelease
#tool nuget:?package=Layout.WatchDog.NET&version=1.5.0-beta.3&prerelease
WatchDog
简介
WatchDog 是一个专为 ASP.NET Core Web 应用程序和 API 设计的实时消息、事件、HTTP(请求和响应)和异常记录器和查看器。它允许开发人员记录和查看消息、事件、对其 Web 应用程序的 HTTP 请求以及在运行时捕获的异常,全部实时显示。
WatchDog 利用 SignalR 实现实时通信,默认使用轻量级数据库 LiteDB(无需配置),同时支持扩展至外部数据库(MSSQL, MySQL, PostgreSQL, MongoDB, SQLite)。
主要功能
- 实时 HTTP 监控:记录所有请求和响应的详细信息。
- 异常捕获:自动捕获并记录应用程序运行时的异常。
- 代码内日志:支持在业务代码中手动记录消息和事件。
- 实时仪表盘:提供
Web界面 (/watchdog) 查看日志,支持搜索和过滤。 - 多种数据库支持:内置
LiteDB,支持一键切换至主流关系型数据库、MongoDB与SQLite。 - 日志自动清理:支持配置定时自动清理旧日志。
截图预览
- 登录页面
- 请求与响应查看器
- 异常日志示例
安装
方式一:.NET CLI
你需要安装 Layout.WatchDog.NET 包。在终端运行:
dotnet add package Layout.WatchDog.NET --version 1.5.0-beta.2
当前发布的是预发布版
1.5.0-beta.2,必须显式指定版本号(或加--prerelease),否则默认只会装到稳定版。
方式二:NuGet 包管理器
除了 dotnet cli 安装,还可以通过 nuget 包管理器安装:
Install-Package Layout.WatchDog.NET --version 1.5.0-beta.2
方式三:源码编译(可选)
本仓库以 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
# 打包
dotnet pack src/WatchDog/WatchDog.csproj -c Release -o ./artifacts
快速开始
1. 注册服务
在 Program.cs 中注册 WatchDog 服务。
using WatchDog;
// 在 Program.cs 中 (适用于 .NET 6+)
builder.Services.AddWatchDogServices();
2. 配置中间件
在 HTTP 请求管道中启用 WatchDog 中间件。注意顺序非常重要。
var app = builder.Build();
// 使用 WatchDog 异常记录器
app.UseWatchDogExceptionLogger();
...
// 建议在 UseRouting, UseAuthentication, UseAuthorization 之后添加
app.UseWatchDog(opt =>
{
// 设置查看器的登录账号
opt.WatchPageUsername = "admin";
opt.WatchPagePassword = "Qwerty@123";
});
注意:在主要 WatchDog 中间件之前添加异常记录器,最好是在中间件层次结构的顶部,以便捕获可能的早期异常。
3. 查看日志
启动你的应用程序,访问 /watchdog 路径(例如:https://localhost:5000/watchdog),使用配置的用户名和密码登录即可查看实时日志。
进阶配置
设置外部数据库(可选)
WatchDog 默认使用 LiteDB(零配置)。如需切换到 MSSQL / MySQL / PostgreSQL / MongoDB / SQLite,需同时指定驱动类型与连接字符串:
services.AddWatchDogServices(opt =>
{
opt.DbDriverOption = WatchDogDbDriverEnum.PostgreSql;
opt.SetExternalDbConnString = "Server=localhost;Database=WatchDogDb;User Id=postgres;Password=root;";
});
各数据库的连接串示例、表结构、分页与清表行为、压缩支持、依赖版本等详见 数据库后端接入指南。
设置自动清除日志(可选)
services.AddWatchDogServices(opt =>
{
opt.IsAutoClear = true; // 开启自动清除
opt.ClearTimeSchedule = 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 条日志的数据库清空前后均为
90112bytes,压缩后降至40960bytes。
多实例部署:设置 Worker ID(可选)
日志记录的 Id 不再由数据库自增,而是由应用生成一个 64 位整数(雪花算法:41 位毫秒时间 + 10 位 Worker ID + 12 位序列号)。因此即使清空日志或压缩 LiteDB 数据文件,新记录的 Id 依然大于旧记录,排序不会错乱。
单进程、单机部署无需配置:默认的 Worker ID 由机器名哈希与进程号推导得到。
只有多个进程写入同一个数据库时(同一个 LiteDB 文件的多个共享连接,或多个实例连同一个 MongoDB 库),才需要显式指定,以保证 Id 全局有序:
services.AddWatchDogServices(opt =>
{
opt.WorkerId = 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的存量数据均无需迁移。
可选配置项
在 app.UseWatchDog() 中可以配置更多选项:
app.UseWatchDog(opt =>
{
opt.WatchPageUsername = "admin";
opt.WatchPagePassword = "Qwerty@123";
// 可选配置项:
// 黑名单:逗号分隔的路径,不记录这些指定 Endpoint 端点/接口
opt.Blacklist = "Test/testPost, api/auth/login";
// JSON 序列化器:WatchDog 默认使用内置的 System.Text.Json(无需额外配置)
// opt.Serializer = WatchDogSerializerEnum.Newtonsoft; // 已废弃,Newtonsoft 不再被使用
// CORS 策略名称
opt.CorsPolicy = "MyCorsPolicy";
// 应用程序使用 asp.net core8+ 输出缓存
opt.UseOutputCache = true;
// 启用正则表达式黑名单
opt.UseRegexForBlacklisting = true;
});
启用独立看板(可选)
包里内置一个可选的独立看板(Vue 实现),可替代原来的内嵌页面。默认关闭,关闭时行为与之前完全一致。
app.UseWatchDog(opt =>
{
opt.WatchPageUsername = "admin";
opt.WatchPagePassword = "******";
// 打开独立看板
opt.Dashboard.Enabled = true;
});
- 入口:
/watchdog(看板)、/watchdog-legacy(原内嵌页面) - 数据接口:
/watchdog-api/v1/*,与旧端点共用同一数据库与登录会话 - 前端资源随程序集内嵌,无需额外部署前端,也不需要单独起服务
- 若打包时未包含看板产物,运行时会自动降级回内嵌页面并记一条 warning
其他可选配置:
opt.Dashboard.BasePath = "/wd"; // 自定义挂载路径
opt.Dashboard.KeepLegacyPage = false; // 不再暴露原页面
opt.Dashboard.FallbackToEmbeddedPage = false; // 产物缺失时直接抛异常,而不是降级
opt.Dashboard.DefaultLocale = "zh-Hans"; // 首次访问的默认语言:en / zh-Hans
opt.Dashboard.DefaultTheme = "dark"; // 首次访问的默认主题:system / dark / light
看板内提供主题(跟随系统 / 深色 / 浅色)与语言(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/:核心库源码。src/Controllers/:包含处理日志查看请求的控制器。src/Helpers/:数据库操作辅助类(支持LiteDB, SQL, MongoDB),以及日志 ID 生成器等工具。src/Hubs/:SignalR集线器,用于实时推送日志。src/Models/:数据模型定义。src/Services/:后台自动清理服务等。src/WatchPage/:内嵌前端页面(由/WTCHDGstatics提供)。
tests/Test.WatchDog.API/:API项目演示。tests/Test.WatchDog.MVC/:MVC项目演示。
贡献
如果你发现了 Bug 或者希望增加新功能:
Fork本仓库。- 创建你的特性分支 (
git checkout -b feature/AmazingFeature)。 - 提交你的更改 (
git commit -m 'Add some AmazingFeature')。 - 推送到分支 (
git push origin feature/AmazingFeature)。 - 发起
Pull Request。
致谢
许可证:本项目采用 MIT 许可证。
| Product | Versions 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. |
-
net10.0
- Dapper (>= 2.1.89)
- LiteDB.Queryable (>= 10.0.2)
- Microsoft.Data.SqlClient (>= 7.1.1)
- Microsoft.Data.Sqlite (>= 10.0.14)
- Microsoft.Extensions.FileProviders.Embedded (>= 10.0.14)
- Microsoft.IO.RecyclableMemoryStream (>= 3.0.1)
- MongoDB.Driver (>= 3.13.0)
- MySql.Data (>= 26.10.0)
- Npgsql (>= 10.0.3)
-
net8.0
- Dapper (>= 2.1.89)
- LiteDB.Queryable (>= 10.0.2)
- Microsoft.Data.SqlClient (>= 7.1.1)
- Microsoft.Data.Sqlite (>= 8.0.33)
- Microsoft.IO.RecyclableMemoryStream (>= 3.0.1)
- MongoDB.Driver (>= 3.13.0)
- MySql.Data (>= 9.7.0)
- Npgsql (>= 8.0.9)
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.3 | 36 | 10/29/2026 |
| 1.5.0-beta.2 | 39 | 10/29/2026 |
| 1.5.0-beta.1 | 41 | 10/28/2026 |
1.5.0-beta.3 - 预发布版本,在 1.5.0-beta.2 基础上统一代码整理与数据库 ID 策略最终落地
修复与统一
- 所有数据库后端(LiteDB / MongoDB / MSSQL / MySQL / PostgreSQL / SQLite)的日志主键 Id 统一由应用层雪花算法生成,清空后 id 不回退
- SQL 系列表结构移除自增列;MSSQL 旧库通过 SET IDENTITY_INSERT ON/OFF 兼容已有 IDENTITY 列的显式写入
- LiteDBHelper、MongoDBHelper 中各自的 id 赋值逻辑移除,统一由 DynamicDBManager 在 Insert 时分配
- 清空表操作统一使用 DELETE FROM,避免不同驱动行为差异
依赖版本
- 继续按 TargetFramework 区分数据库驱动版本:
Microsoft.Data.Sqlite(net8.0 8.0.33 / net10.0 10.0.14)
Npgsql(net8.0 8.0.9 / net10.0 10.0.3)
MySql.Data(net8.0 9.7.0 / net10.0 26.10.0)
1.5.0-beta.2 - 预发布版本,新增独立 Dashboard 看板(含服务器资源监控)与 SQLite 驱动支持
...
(此处保留原有 beta.2 的完整说明不变)