LogUserControl 1.2.0
dotnet add package LogUserControl --version 1.2.0
NuGet\Install-Package LogUserControl -Version 1.2.0
<PackageReference Include="LogUserControl" Version="1.2.0" />
<PackageVersion Include="LogUserControl" Version="1.2.0" />
<PackageReference Include="LogUserControl" />
paket add LogUserControl --version 1.2.0
#r "nuget: LogUserControl, 1.2.0"
#:package LogUserControl@1.2.0
#addin nuget:?package=LogUserControl&version=1.2.0
#tool nuget:?package=LogUserControl&version=1.2.0
LogUserControl 使用说明
一个可发布到 NuGet 的 WPF User Control Library,封装了日志记录与日志查看功能。其他项目引用本库后,可以直接使用内置的日志处理器写入日志,并在界面中嵌入日志查看控件实时浏览、按类别切换、按时间/级别查询日志。
一、功能特性
- 按类别分文件:记录日志时传入类别,日志自动写入对应类别的独立文件。
- 按天滚动:日志文件按日期命名,每天一个文件,自动归档。
- 自动清理:可设置日志保留天数(默认 60 天),过期日志文件自动删除。
- 类别 Tab 展示:日志查看控件以 Tab 形式展示所有类别,可切换查看指定类别。
- 时间 / 级别查询:支持按开始时间、结束时间、日志级别筛选,并限制显示条数。
- 现代化外观:内置现代化主题样式,并支持通过依赖属性定制配色与样式。
- 开箱即用:其他项目引用本库后,直接调用
LogManager静态方法即可记录日志。
二、目录结构
LogUserControl/
├── LogUserControl/ # 主库(WPF User Control Library)
│ ├── Logging/
│ │ ├── LogLevel.cs # 日志级别枚举
│ │ ├── LogEntry.cs # 日志条目模型
│ │ └── LogManager.cs # 核心日志处理器(静态)
│ ├── Controls/
│ │ ├── LogViewerControl.xaml # 日志查看控件(UI)
│ │ ├── LogViewerControl.xaml.cs # 日志查看控件(逻辑)
│ │ └── Themes/ModernStyles.xaml # 内置现代化主题样式
├── Demo/ # 示例项目(可运行的 WPF 应用)
│ ├── App.xaml / App.xaml.cs
│ ├── MainWindow.xaml # 演示写入日志 + 嵌入控件
│ └── MainWindow.xaml.cs
└── LogUserControl.sln
三、环境要求
- .NET SDK(
net10.0-windows) - Windows 操作系统(WPF)
- JetBrains Rider 或 Visual Studio 2022+
四、快速开始(运行 Demo)
在项目根目录执行:
dotnet run --project Demo\Demo.csproj
或在 Rider 中将 Demo 设为启动项目后直接运行。
运行后:
- 顶部输入 类别 / 级别 / 内容,点击「记录日志」写入一条;
- 点击「随机生成」批量写入 5 条随机日志;
- 下方日志查看控件自动按类别生成 Tab,可切换查看,并支持顶部「开始时间 / 结束时间 / 级别」查询。
日志默认写到 Demo 运行目录下的 Logs\ 文件夹。
五、核心概念
5.1 命名空间
| 命名空间 | 用途 |
|---|---|
LogUserControl.Logging |
日志处理器 LogManager、LogLevel、LogEntry |
LogUserControl.Controls |
日志查看控件 LogViewerControl |
5.2 日志文件结构
Logs/ # 日志根目录(可配置)
├── UserService/
│ ├── 2026-08-28.log
│ └── 2026-08-29.log
├── OrderService/
│ └── 2026-08-28.log
└── System/
│ └── 2026-08-28.log
- 每个类别对应一个子目录;
- 每天一个
.log文件,文件名格式yyyy-MM-dd.log; - 单行日志格式:
[yyyy-MM-dd HH:mm:ss.fff] [LEVEL] message。
5.3 日志级别
LogLevel 枚举:Debug、Info、Warn、Error、Fatal。
六、详细使用说明
6.1 在其他项目中引用本库
方式一:项目引用(开发阶段)
在目标项目的 .csproj 中添加:
<ItemGroup>
<ProjectReference Include="..\LogUserControl\LogUserControl.csproj" />
</ItemGroup>
方式二:NuGet 引用(发布后)
dotnet add package LogUserControl
6.2 使用日志处理器 LogManager
LogManager 是静态类,所有方法可直接调用,无需实例化。
引入命名空间:
using LogUserControl.Logging;
(可选)设置日志根目录:
// 不设置则默认写入 程序运行目录\Logs
LogManager.SetLogDirectory(@"D:\MyApp\Logs");
// 或直接读取当前根目录
string dir = LogManager.RootDirectory;
(可选)设置日志保留天数:
// 默认保留 60 天,0 表示永久保留;设置后立即清理过期文件
LogManager.SetRetentionDays(10);
// 或直接赋值
LogManager.RetentionDays = 30;
记录一条日志:
// 基础写法(level 默认为 Info)
LogManager.Log("UserService", "用户登录成功");
// 指定级别
LogManager.Log("OrderService", "订单创建完成", LogLevel.Info);
按级别快捷方法:
LogManager.Debug("UserService", "缓存 key 已刷新");
LogManager.Info("UserService", "用户登录成功");
LogManager.Warn("PaymentService", "支付回调延迟超过 3 秒");
LogManager.Error("OrderService", "库存不足,下单失败");
LogManager.Fatal("System", "数据库连接已断开");
记录异常:
try
{ // 业务逻辑 }
catch (Exception ex)
{
LogManager.LogException("OrderService", ex);
}
读取日志(用于自定义展示):
// 读取指定类别的日志
var logs = LogManager.ReadLogs(
category: "UserService", start: DateTime.Today, // 起始时间(含),可为 null
end: null, // 结束时间(含),可为 null
level: LogLevel.Error, // 级别过滤,可为 null
maxCount: 500
); // 最多返回条数(取最新),可为 null
// 读取所有类别的日志
var allLogs = LogManager.ReadAllLogs(start: null, end: null, level: null, maxCount: 1000);
// 获取当前所有类别
var categories = LogManager.GetCategories();
每条日志是一个 LogEntry,包含:
| 属性 | 类型 | 说明 |
|---|---|---|
Time |
DateTime |
记录时间 |
Level |
LogLevel |
日志级别 |
Category |
string |
日志类别 |
Message |
string |
日志内容 |
6.3 使用日志查看控件 LogViewerControl
XAML 中声明:
<Window xmlns:log="clr-namespace:LogUserControl.Controls;assembly=LogUserControl">
<Grid>
<log:LogViewerControl x:Name="LogViewer" />
</Grid>
</Window>
依赖属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
LogDirectory |
string? |
null |
日志根目录;为空时使用 LogManager 的默认目录 |
AutoRefresh |
bool |
true |
是否自动监听日志目录变化并刷新 |
MaxLogCount |
int |
0 |
单个类别最多显示的条数,0 表示不限 |
RetentionDays |
int |
60 |
日志文件保留天数,0 表示永久保留 |
ButtonStyle |
Style? |
null |
顶部按钮样式,为空时使用内置默认样式 |
TextBoxStyle |
Style? |
null |
输入框样式,为空时使用内置默认样式 |
ComboBoxStyle |
Style? |
null |
下拉框样式,为空时使用内置默认样式 |
DatePickerStyle |
Style? |
null |
日期选择器样式,为空时使用内置默认样式 |
TabControlStyle |
Style? |
null |
类别 Tab 样式,为空时使用内置默认样式 |
PrimaryBrush |
Brush? |
null |
主题主色,为空时使用内置默认主色 |
XAML 配置示例:
<log:LogViewerControl x:Name="LogViewer" LogDirectory="D:\MyApp\Logs" AutoRefresh="True" MaxLogCount="500" RetentionDays="10" />
代码后置配置:
LogViewer.LogDirectory = @"D:\MyApp\Logs"; // 会自动同步到 LogManager
LogViewer.AutoRefresh = true;
LogViewer.MaxLogCount = 500;
LogViewer.RetentionDays = 10;
手动刷新方法:
LogViewer.RefreshTabs(); // 全量刷新:重建所有类别 Tab 及各 Tab 内容
LogViewer.RefreshCurrent(); // 增量刷新:只刷新当前选中 Tab 的内容(开销更小)
说明:
AutoRefresh = true时,控件通过FileSystemWatcher自动监听日志目录,日志文件有变化会自动刷新,无需手动调用。
6.4 定制样式
控件内置了一套现代化主题(靛蓝主色 #6366F1)。宿主项目可通过依赖属性覆盖配色与样式。
改主色:
<log:LogViewerControl Grid.Row="1" x:Name="LogViewer">
<log:LogViewerControl.PrimaryBrush>
<SolidColorBrush Color="#FF5722"/>
</log:LogViewerControl.PrimaryBrush>
</log:LogViewerControl>
替换按钮 / Tab 样式:
<log:LogViewerControl Grid.Row="1" x:Name="LogViewer">
<log:LogViewerControl.ButtonStyle>
<Style TargetType="Button" BasedOn="{StaticResource MyButtonStyle}"/>
</log:LogViewerControl.ButtonStyle>
<log:LogViewerControl.TabControlStyle>
<Style TargetType="TabControl" BasedOn="{StaticResource MyTabStyle}"/>
</log:LogViewerControl.TabControlStyle>
</log:LogViewerControl>
代码方式:
LogViewer.ButtonStyle = (Style)FindResource("MyButtonStyle");
LogViewer.TabControlStyle = (Style)FindResource("MyTabStyle");
注意:
BasedOn里引用的资源键(如MyButtonStyle)必须是已在当前 XAML 资源中定义的真实资源,否则运行时会报「找不到资源」。
七、完整示例
以下是一个最小可运行的窗口,演示「写入日志 + 展示日志」:
MainWindow.xaml
using System.IO;
using System.Windows;
using LogUserControl.Logging;
namespace Demo;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var logDir = Path.Combine(AppContext.BaseDirectory, "Logs");
LogViewer.LogDirectory = logDir; // 同时作用于 LogManager
}
private void OnWriteClicked(object sender, RoutedEventArgs e)
{
var category = string.IsNullOrWhiteSpace(CategoryBox.Text) ? "Default" : CategoryBox.Text.Trim();
var message = string.IsNullOrWhiteSpace(MessageBox.Text) ? "测试日志" : MessageBox.Text.Trim();
LogManager.Log(category, message);
LogViewer.RefreshCurrent();
}
}
八、NuGet 打包与发布
主库 .csproj 已配置打包元数据(PackageId、Version、GeneratePackageOnBuild 等)。
打包:
cd LogUserControl
dotnet pack -c Release
生成文件位于 LogUserControl\bin\Release\LogUserControl.1.0.0.nupkg。
发布到 NuGet:
dotnet nuget push bin\Release\LogUserControl.1.0.0.nupkg -k <API_KEY> -s https://api.nuget.org/v3/index.json
九、常见问题(FAQ)
Q1:日志写到哪里了?
默认写到程序运行目录下的 Logs\{类别}\yyyy-MM-dd.log。可通过 LogManager.SetLogDirectory() 或控件的 LogDirectory 属性修改。
Q2:为什么切换 Tab 会自动刷新?
控件默认开启 AutoRefresh,通过 FileSystemWatcher 监听日志目录。设为 False 即可关闭。
Q3:日志量很大时如何优化?
设置控件的 MaxLogCount(如 500),读取时只取最新 N 条,避免一次性加载全部日志。
Q4:日志内容里的换行会怎样?
写入时会把换行符 \r、\n 转成空格,保证每条日志占一行。
Q5:类别名包含非法字符会怎样?
非法文件名字符(如 :、*、?)会被替换为下划线 _。
Q6:如何修改控件主题色?
设置控件的 PrimaryBrush 依赖属性即可(如 LogViewer.PrimaryBrush = new SolidColorBrush(Colors.Red)),按钮、选中态、下划线指示器会同步变色。
Q7:如何设置日志保留天数?
调用 LogManager.SetRetentionDays(10) 或设置控件 RetentionDays = 10;0 表示永久保留,默认 60 天,设置后会自动清理过期文件。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
-
net10.0-windows7.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.