Hyz.Trace.Storage.FreeSql
1.4.1
dotnet add package Hyz.Trace.Storage.FreeSql --version 1.4.1
NuGet\Install-Package Hyz.Trace.Storage.FreeSql -Version 1.4.1
<PackageReference Include="Hyz.Trace.Storage.FreeSql" Version="1.4.1" />
<PackageVersion Include="Hyz.Trace.Storage.FreeSql" Version="1.4.1" />
<PackageReference Include="Hyz.Trace.Storage.FreeSql" />
paket add Hyz.Trace.Storage.FreeSql --version 1.4.1
#r "nuget: Hyz.Trace.Storage.FreeSql, 1.4.1"
#:package Hyz.Trace.Storage.FreeSql@1.4.1
#addin nuget:?package=Hyz.Trace.Storage.FreeSql&version=1.4.1
#tool nuget:?package=Hyz.Trace.Storage.FreeSql&version=1.4.1
Hyz.Trace.Storage.FreeSql
基于 FreeSql ORM 的链路追踪存储实现,支持 SQLite、MySQL、PostgreSQL、SQL Server 四种数据库。
目标框架
- net8.0 / net9.0 / net10.0
支持的数据库
| 数据库 | 适用场景 | 最低版本 | 连接字符串示例 |
|---|---|---|---|
| SQLite | 开发/小型部署 | 3.x | Data Source=traces.db |
| MySQL | 中小规模生产 | 5.7 | Server=localhost;Port=3306;Database=hyz_trace;User=root;Password=xxx;CharSet=utf8mb4;AllowLoadLocalInfile=true |
| PostgreSQL | 中大规模生产 | 12 | Host=localhost;Port=5432;Database=hyz_trace;Username=postgres;Password=xxx |
| SQL Server | Windows/企业级生产 | 2008 R2 | Server=localhost;Database=hyz_trace;User Id=sa;Password=xxx;TrustServerCertificate=True |
快速开始
安装
dotnet add package Hyz.Trace.Storage.FreeSql
注册存储
using Hyz.Trace.Storage.FreeSql;
// SQLite(开发/演示,零配置)
builder.Services.UseSqliteStorage("Data Source=traces.db");
// MySQL(BulkCopy 建议 AllowLoadLocalInfile=true)
// builder.Services.UseMySqlStorage("Server=localhost;Port=3306;Database=hyz_trace;User=root;Password=xxx;CharSet=utf8mb4;AllowLoadLocalInfile=true");
// PostgreSQL
// builder.Services.UsePostgreSqlStorage("Host=localhost;Port=5432;Database=hyz_trace;Username=postgres;Password=xxx");
// SQL Server(兼容 2008 R2+,默认 dbo schema,NVARCHAR 全程 Unicode 安全)
// builder.Services.UseSqlServerStorage("Server=localhost;Database=hyz_trace;User Id=sa;Password=xxx;TrustServerCertificate=True");
需要额外注册 RuntimeConfigStore(Dashboard 中间件依赖):
builder.Services.AddSingleton<RuntimeConfigStore>();
从 DI 获取仓储
注册后,ITraceRepository、IUserRepository、IApplicationRepository 由容器解析,不要手动 new FreeSql*Repository:
using Hyz.Trace.Storage;
// 构造函数注入(推荐)
public class MyService(
ITraceRepository traces,
IUserRepository users,
IApplicationRepository apps)
{
// ...
}
// 或从 ServiceProvider 解析
var traces = app.Services.GetRequiredService<ITraceRepository>();
生命周期
IFreeSql注册为全局单例,三个仓储共享同一实例- 首次解析
IFreeSql(或依赖它的仓储)时懒创建连接 - 进程关停时由 DI 容器 Dispose 释放
IFreeSql(单例实现IDisposable) - 不要
new FreeSqlTraceRepository(DataType, connectionString)— 该构造已移除 FreeSqlFactory供扩展方法与诊断使用;业务与测试代码请通过Use*Storage注册,勿用 Factory 直接拼仓储
SQLite 连接字符串:仅使用
Data Source等 Provider 支持的关键字;勿使用Max Pool Size/Maximum Pool Size(SqlClient 风格关键字会导致解析失败)。
自动创建的表
启动时 FreeSql 自动创建以下表(AutoCreateStructure):
applications(应用表,含密钥字段)
| 列名 | 类型 | 说明 |
|---|---|---|
id |
BIGINT | 应用 ID(主键,自增) |
name |
VARCHAR(200) | 应用名称(唯一索引) |
description |
VARCHAR(500) | 应用描述 |
key_prefix |
VARCHAR(20) | API Key 前缀(明文前 12 位) |
key_hash |
VARCHAR(128) | API Key 的 SHA256 哈希(唯一索引) |
enabled |
BOOL | 是否启用 |
created_at |
DATETIME | 创建时间 |
updated_at |
DATETIME | 更新时间 |
注意:旧版
report_keys表已移除,密钥字段合并到applications表。
trace_spans(Span 数据表,按月分表 trace_spans_YYYYMM)
| 列名 | 类型 | 索引 | 说明 |
|---|---|---|---|
id |
BIGINT | PK | 主键(雪花 ID) |
application_id |
BIGINT | IDX | 应用 ID |
application_name |
VARCHAR(128) | IDX | 应用名称 |
trace_id |
VARCHAR(32) | IDX | W3C TraceId |
span_id |
VARCHAR(16) | Span ID | |
parent_span_id |
VARCHAR(16) | 父 Span ID | |
method_name |
VARCHAR(512) | 方法名 | |
start_time_utc |
DATETIME/DATETIME2 | IDX | 开始时间(UTC) |
start_time_cst |
VARCHAR(32) | 开始时间(CST 格式化) | |
duration_ms |
DOUBLE/FLOAT | 耗时(毫秒) | |
status |
VARCHAR(16) | 状态(Ok/Error) | |
error_message |
VARCHAR(2048) | 错误消息 | |
error_type |
VARCHAR(256) | 异常类型 | |
http_status_code |
INT | HTTP 状态码 | |
tags_json |
VARCHAR(4096) | 标签 JSON | |
input_parameters |
VARCHAR(4096) | 输入参数 JSON | |
request_headers |
VARCHAR(4096) | 请求头 JSON | |
return_value |
VARCHAR(4096) | 返回值 JSON | |
created_at |
DATETIME/DATETIME2 | 入库时间 |
索引:idx_{table}_traceid、idx_{table}_appid_time、idx_{table}_app_time、idx_{table}_time
分表说明:Span 数据按月自动分表(
trace_spans_YYYYMM),写入按StartTimeUtc路由,查询跨表 UNION ALL 合并,过期数据按整表 DROP 清理。启动时自动检测老表trace_spans并迁移到分表。
users(用户表)
| 列名 | 类型 | 说明 |
|---|---|---|
id |
BIGINT | 用户 ID(主键,自增) |
username |
VARCHAR(100) | 用户名(唯一索引) |
password_hash |
VARCHAR(200) | BCrypt 密码哈希 |
role |
VARCHAR(20) | 角色(Admin/User) |
enabled |
BOOL | 是否启用 |
created_at |
DATETIME | 创建时间 |
updated_at |
DATETIME | 更新时间 |
扩展方法
| 方法 | 说明 |
|---|---|
UseFreeSqlStorage(dataType, connectionString) |
通用注册(指定 DataType) |
UseSqliteStorage(connectionString) |
注册 SQLite 存储 |
UseMySqlStorage(connectionString) |
注册 MySQL 存储 |
UsePostgreSqlStorage(connectionString) |
注册 PostgreSQL 存储 |
UseSqlServerStorage(connectionString) |
注册 SQL Server 存储(兼容 2008 R2+) |
SQL Server 特定说明
- 版本兼容:支持 SQL Server 2008 R2 及以上版本,时间分桶使用
DATEDIFF+DATEADD+CONVERT实现,不依赖 2012+ 的FORMAT函数 - 字符类型:所有字符串列使用
NVARCHAR(n)Unicode 类型,完美支持中文、日文、emoji 等多语言字符 - 时间类型:
DATETIME2(7)精度 100 纳秒,符合 .NET DateTime 精度 - 标识符:使用
[方括号]引用,避免关键字冲突 - 建表方式:使用
sys.objects/sys.indexes做存在性检查(兼容 2008 R2,无CREATE TABLE IF NOT EXISTS语法) - Schema:默认使用
dboschema - 表重命名:使用
sp_rename系统存储过程
依赖包
Hyz.Trace.Storage.Abstractions— 存储抽象层(依赖)FreeSql/FreeSql.Provider.SqliteCore/FreeSql.Provider.MySqlConnector/FreeSql.Provider.PostgreSQL/FreeSql.Provider.SqlServer— ORM 和数据库驱动Hyz.Trace.IdGenerator— 雪花 ID 生成器
批量写入
InsertBatchAsync 按批大小自动路由:小批(≤ StagingBatchThreshold,默认 2000 行)走手写分方言 IGNORE(SQLite INSERT OR IGNORE / MySQL INSERT IGNORE / PG ON CONFLICT DO NOTHING),单次往返、零额外查询;大批量(> 阈值)自动路由到 dialect-native 临时表旁路(各方言原生临时表 + 专有 bulk 灌入 + INSERT...SELECT WHERE NOT EXISTS 去重),以获得协议级批量吞吐。SQL Server 始终走 SqlBulkCopy + 唯一索引 IGNORE_DUP_KEY(服务端等价去重,不进临时表)。幂等去重由分表唯一索引 (ApplicationId, TraceId, SpanId) 保证,at-least-once 重复上报不会重复入库。MySQL 的 MySqlBulkCopy 灌入路径由 FreeSqlStorageOptions.EnableMySqlBulkCopy 控制(默认 false,需经真实实例验证唯一键冲突可忽略后再启用)。
性能建议
- SQLite 适合开发环境或 Span 量小于 100 万/天的小型部署;连接字符串使用
Data Source=...即可,勿添加Max Pool Size - MySQL 建议对
start_time_utc和trace_id列建立复合索引以提升查询性能,推荐 utf8mb4 字符集 - PostgreSQL 在高并发场景下性能最佳,建议使用连接池(
Maximum Pool Size=50) - SQL Server 建议开启连接池(
Max Pool Size=100),生产环境推荐使用 SQL Server 2019+ 以获得更好的查询优化器支持;Always On 可用性组环境下在连接字符串中加入MultiSubnetFailover=True - 自动清理任务(
Cleanup)默认每天凌晨 2 点执行,根据DataRetentionDays配置清理过期数据 - 对于大规模部署(Span 量 > 1000 万/天),建议使用
Hyz.Trace.Storage.ClickHouse
| 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 is compatible. 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
- BCrypt.Net-Next (>= 4.2.0)
- Castle.Core (>= 5.2.1)
- FreeSql (>= 3.5.302)
- FreeSql.Provider.MySqlConnector (>= 3.5.302)
- FreeSql.Provider.PostgreSQL (>= 3.5.302)
- FreeSql.Provider.SqliteCore (>= 3.5.302)
- FreeSql.Provider.SqlServer (>= 3.5.302)
- Hyz.Trace.IdGenerator (>= 1.4.1)
- Hyz.Trace.Storage.Abstractions (>= 1.4.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Newtonsoft.Json (>= 13.0.3)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 2.1.11)
- Yitter.IdGenerator (>= 1.0.14)
-
net8.0
- BCrypt.Net-Next (>= 4.2.0)
- Castle.Core (>= 5.2.1)
- FreeSql (>= 3.5.302)
- FreeSql.Provider.MySqlConnector (>= 3.5.302)
- FreeSql.Provider.PostgreSQL (>= 3.5.302)
- FreeSql.Provider.SqliteCore (>= 3.5.302)
- FreeSql.Provider.SqlServer (>= 3.5.302)
- Hyz.Trace.IdGenerator (>= 1.4.1)
- Hyz.Trace.Storage.Abstractions (>= 1.4.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Newtonsoft.Json (>= 13.0.3)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 2.1.11)
- Yitter.IdGenerator (>= 1.0.14)
-
net9.0
- BCrypt.Net-Next (>= 4.2.0)
- Castle.Core (>= 5.2.1)
- FreeSql (>= 3.5.302)
- FreeSql.Provider.MySqlConnector (>= 3.5.302)
- FreeSql.Provider.PostgreSQL (>= 3.5.302)
- FreeSql.Provider.SqliteCore (>= 3.5.302)
- FreeSql.Provider.SqlServer (>= 3.5.302)
- Hyz.Trace.IdGenerator (>= 1.4.1)
- Hyz.Trace.Storage.Abstractions (>= 1.4.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Newtonsoft.Json (>= 13.0.3)
- SQLitePCLRaw.bundle_e_sqlite3 (>= 2.1.11)
- Yitter.IdGenerator (>= 1.0.14)
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.4.1 | 103 | 8/12/2026 |
| 1.4.0 | 91 | 8/11/2026 |
| 1.3.9 | 89 | 8/11/2026 |
| 1.3.8 | 101 | 8/10/2026 |
| 1.3.7 | 109 | 8/7/2026 |
| 1.3.6 | 93 | 8/7/2026 |
| 1.3.5 | 86 | 8/7/2026 |
| 1.3.4 | 91 | 8/7/2026 |
| 1.3.3 | 88 | 8/7/2026 |
| 1.3.2 | 102 | 8/6/2026 |
| 1.3.1 | 96 | 8/6/2026 |
| 1.3.0 | 95 | 8/4/2026 |
| 1.2.7 | 98 | 8/3/2026 |
| 1.2.6 | 106 | 8/2/2026 |
| 1.2.5 | 99 | 8/2/2026 |
| 1.2.3 | 100 | 8/2/2026 |
| 1.2.2 | 95 | 8/1/2026 |
| 1.2.1 | 102 | 8/1/2026 |
| 1.2.0 | 96 | 8/1/2026 |
| 1.1.0 | 99 | 8/1/2026 |