Hyz.Trace.Weaving.Fody 1.4.1

dotnet add package Hyz.Trace.Weaving.Fody --version 1.4.1
                    
NuGet\Install-Package Hyz.Trace.Weaving.Fody -Version 1.4.1
                    
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="Hyz.Trace.Weaving.Fody" Version="1.4.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Hyz.Trace.Weaving.Fody" Version="1.4.1" />
                    
Directory.Packages.props
<PackageReference Include="Hyz.Trace.Weaving.Fody">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 Hyz.Trace.Weaving.Fody --version 1.4.1
                    
#r "nuget: Hyz.Trace.Weaving.Fody, 1.4.1"
                    
#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 Hyz.Trace.Weaving.Fody@1.4.1
                    
#: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=Hyz.Trace.Weaving.Fody&version=1.4.1
                    
Install as a Cake Addin
#tool nuget:?package=Hyz.Trace.Weaving.Fody&version=1.4.1
                    
Install as a Cake Tool

Hyz.Trace.Weaving.Fody

Hyz.Trace 的 Fody IL 编织器 — 编译时扫描 [Trace] 特性,采用方法外壳包装(Thunk/Wrapper)模式自动织入 TraceScope 包装代码,实现方法级 Span 的零侵入捕获,理论编织成功率 100%。

特性优先级:类级 [Trace] 编织类内所有方法(含 public/protected/internal/private/static);方法级 [Trace] 仅编织打标的单个方法。两者可混用,方法级标注总是生效。

安装

dotnet add package Hyz.Trace.Weaving.Fody

本包不包含 Hyz.Trace 核心库,需配合以下任一包使用:

  • Hyz.Trace.Client(客户端元包,推荐)
  • Hyz.Trace(仅核心库)

安装后确保项目存在 FodyWeavers.xml(通常由 NuGet 包自动引入),其中启用本编织器:

<Weavers>
  <Hyz.Trace.Weaving.Fody />
</Weavers>

[Trace] 特性详解

[Trace] 特性定义于 Hyz.Trace 命名空间,可标注于 类、方法、属性AttributeTargets.Method | Class | PropertyInherited = true)。

特性属性

属性 类型 默认值 说明
Name string? null 自定义 Span 名称。为空时使用 {TypeName}.{MethodName}
IncludeParameters bool true 是否将方法入参记录到 Span 的 inputParameters Tag
IncludeReturnValue bool true 是否将方法返回值记录到 Span 的 returnValue Tag

标注位置与行为

标注位置 行为
标在 该类所有符合条件的方法均被编织(含 public/protected/internal/private/static,详见下方支持矩阵)
标在方法 仅该方法被编织;优先级高于类级标注,且不受类级标注影响
标在属性 该属性的 get_/set_ 访问器被编织(Span 名为 {TypeName}.{PropName}.get / .set

混用规则:类级 [Trace] + 方法级 [Trace] 可共存。方法级标注的方法一定会被编织(即使类未标注);类级标注会编织类内所有方法,方法级标注的方法同样会被编织,不会重复。

工作原理

方法外壳包装(Thunk/Wrapper)模式:与传统的内联 IL 修改方式不同,本编织器完全不修改原方法体,而是:

  1. 编译时 Fody 加载本 weaver DLL
  2. 扫描程序集中所有标注 [Trace] 特性的方法或类
  3. 重命名原方法:将原方法重命名为 <MethodName>__TraceOriginal,改为 private,原方法体 IL 保持 100% 不变
  4. 生成包装方法:创建一个与原方法签名完全一致的新方法(保留原访问级别与 static / virtual / override 修饰;显式接口 Overrides 迁到包装方法,原方法改为 private non-virtual)
  5. 织入追踪代码:包装方法内部通过 TraceScope.Run() / TraceScope.RunAsync() 调用原方法,自动处理:
    • Span 创建与命名(默认 {TypeName}.{MethodName}
    • 输入参数捕获
    • 返回值捕获
    • 异常自动捕获与 SetError()
    • 正常完成时 SetOk()
    • using 模式确保 Dispose() 始终执行
  6. 对于 ref/out 参数,采用直接 IL 路径避免闭包开销
  7. 内部调用自动重定向到包装方法,确保追踪连续性

核心优势:原方法体完全不被修改,从根本上避免了内联编织遇到复杂控制流(多 return、try-catch-finally、using、lock、迭代器、泛型方法、Dictionary 初始化器等)时的 IL 验证失败和 InvalidProgramException

支持的方法类型

编织能力矩阵

方法类型 类级 [Trace] 方法级 [Trace] 说明
同步 void SyncVoid 模式
同步有返回值(TResult) SyncFunc 模式
异步 Task(无返回值) AsyncTask 模式,async/await 原生支持
异步 Task<T> AsyncTaskT 模式
异步 ValueTask / ValueTask<T> 与 Task 同等处理
实例方法(public)
实例方法(protected/internal)
实例方法(private)
静态方法 包装方法自动加 static 修饰,不生成 <>4__this 字段
泛型方法(含 where T : class 等约束) 自动处理类型泛型参数与方法泛型参数映射
ref / out / in 参数 直接 IL 路径,无闭包开销
属性 get/set([Trace] 标在属性上) Span 名 {Type}.{Prop}.get / .set
复杂控制流(try-catch/using/lock/多 return/迭代器/递归/lambda 闭包) 原方法体不修改,全部支持

不编织的方法(自动跳过)

方法类型 跳过原因
构造函数(实例/静态) 不支持编织
abstract 方法 无方法体
runtime/internal call/unmanaged 方法 无 IL 方法体
无方法体方法(如 P/Invoke、外部方法) 无法包装
编译器生成方法(get_/set_/move_next 等) 类级 [Trace] 自动跳过;但属性/事件显式标 [Trace] 时其访问器会被编织
ref/out 参数 + async Task 返回类型组合 组合无法安全编织,跳过并告警

使用示例

方法级追踪

using Hyz.Trace;

public class UserService
{
    // 自动生成 Span,名称为 "UserService.GetUser"
    [Trace]
    public User? GetUser(int id)
    {
        return userRepository.Find(id);
    }
}

类级追踪(覆盖所有方法)

using Hyz.Trace;

[Trace]
public class OrderService
{
    public Order CreateOrder(CreateOrderRequest request) { /* 会被编织 */ }
    public void CancelOrder(int orderId) { /* 会被编织 */ }

    // 类级 [Trace] 同样编织 private / protected / static 方法
    private void InternalHelper() { /* 会被编织 */ }
    protected virtual void Validate(Order order) { /* 会被编织 */ }
    public static Order? FindById(int id) { /* 会被编织 */ }

    // 构造函数不会被编织(不支持)
    public OrderService() { }
}

自定义 Span 名称与参数控制

public class PaymentService
{
    [Trace(Name = "process-payment")]
    public PaymentResult Process(PaymentRequest request) { /* ... */ }

    // 关闭入参/返回值记录(避免敏感数据或大对象进入 Span)
    [Trace(IncludeParameters = false, IncludeReturnValue = false)]
    public string GetToken() { /* ... */ }
}

属性级追踪

public class ConfigProvider
{
    // Span 名为 "ConfigProvider.Cache.get" / ".set"
    [Trace]
    public string? Cache { get; set; }
}

复杂方法也能正常编织

[Trace]
public static HttpResult<T> WebRequest<T>(string url, Dictionary<string, string>? headers = null)
{
    // 任意复杂控制流都不会导致编织失败:
    // 多 return、try-catch-finally、using、lock、迭代器、递归、lambda 闭包、泛型约束
    // 原方法体完全保持不变
}

编译日志

编织过程会在 Visual Studio 生成输出中打印详细日志(前缀 [Hyz.Trace.Weaving]):

  • Normal 详细级别

    • OK {Kind} {MethodName}:编织成功(显示方法类型:SyncVoid/SyncFunc/AsyncTask/AsyncTaskT)
    • SKIP {Source} {MethodName} : {原因}:跳过编织(Source[Trace][类级Trace]
    • 汇总统计:总计扫描/成功/跳过/失败数量
  • Detailed 详细级别

    • FAIL {MethodName} : {错误信息}:编织失败(带完整异常堆栈)
    • 失败状态始终在 Normal 级别显示为警告

日志示例

[Hyz.Trace.Weaving] =========================================================
[Hyz.Trace.Weaving] 开始扫描程序集: Hyz.Trace.Demo.NetFramework.Console
[Hyz.Trace.Weaving] =========================================================
[Hyz.Trace.Weaving] --- Hyz.Trace.Demo.NetFramework.TraceConsole.Services.OrderService ---
[Hyz.Trace.Weaving]   OK SyncFunc CreateOrder
[Hyz.Trace.Weaving]   OK SyncFunc GetOrder
[Hyz.Trace.Weaving] --- Hyz.Trace.Demo.NetFramework.TraceConsole.Services.SafetyStressService ---
[Hyz.Trace.Weaving]   OK SyncFunc PrivateGeneric
[Hyz.Trace.Weaving]   OK SyncFunc PublicWithUsingAndThrow
[Hyz.Trace.Weaving]   OK SyncFunc MultiBranchServiceCallHandle
[Hyz.Trace.Weaving]   ...
[Hyz.Trace.Weaving] =========================================================
[Hyz.Trace.Weaving] 编织完成: 总计 86, 成功 49, 跳过 37, 失败 0
[Hyz.Trace.Weaving] =========================================================

安全保障机制

  1. 原方法体零修改:从根本上避免 IL 损坏
  2. 原子提交:新类型/方法先添加到模块树,再生成 IL,失败时自动回滚
  3. 运行时保护TraceScope 公共方法均有 try-catch,追踪异常绝不影响业务代码
  4. IL 栈验证:编织完成后验证方法体 IL 栈深度正确性

与 SourceGenerator 对比

维度 Fody IL 编织 SourceGenerator 源生成器
实现方式 编译后修改 IL(方法外壳包装) 编译时生成 Wrapper 装饰器类
类级 [Trace] 覆盖范围 所有方法(含 private/protected/static) 仅 public/internal 实例方法
方法级 [Trace] 覆盖范围 所有访问级别(含 private/protected/static) 仅 public/internal 实例方法
属性级 [Trace] ✅(public/internal 属性)
静态方法 ❌(装饰器模式无法包装静态方法)
private/protected 方法 ❌(Wrapper 无法访问)
使用方式 零侵入,标记即生效 需通过 TraceFactory.Wrap() / AddTracedServices() 显式包装
DI 场景 自动(透明) 需注册 Wrapper
目标框架 .NET Standard 2.0(.NET Framework 4.6.2+ / .NET Core 2.0+ / .NET 5+) .NET 8.0+(Roslyn 增量生成器)
与对方共存 智能共存(SuppressDirectWeaving 防双重追踪) 智能共存

选型建议:优先使用 Fody(功能完整、零侵入、全平台)。SourceGenerator 作为补充,仅用于无法安装 Fody 或必须使用源生成器的场景。

与元包的关系

Hyz.Trace.Client 元包默认不包含本包,以避免与独立引用时的双重编织冲突。如需 IL 编织能力,请显式安装本包。

依赖

  • Fody 6.9.3(自动作为传递依赖引入)
  • Hyz.Trace 核心库(需使用者自行引用)

目标框架

netstandard2.0 — 兼容所有支持 .NET Standard 2.0 的运行时(.NET Framework 4.6.2+、.NET Core 2.0+、.NET 5+)。

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

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 105 8/12/2026
1.4.0 92 8/11/2026
1.3.9 87 8/11/2026
1.3.8 99 8/10/2026
1.3.7 93 8/7/2026
1.3.6 94 8/7/2026
1.3.5 93 8/7/2026
1.3.4 93 8/7/2026
1.3.3 89 8/7/2026
1.3.2 97 8/6/2026
1.3.1 101 8/6/2026
1.3.0 97 8/4/2026
1.2.7 105 8/3/2026
1.2.6 102 8/2/2026
1.2.5 101 8/2/2026
1.2.4 107 8/2/2026
1.2.3 100 8/2/2026
1.2.2 100 8/1/2026
1.2.1 105 8/1/2026
1.2.0 101 8/1/2026
Loading failed