Skip to content

inversionhourglass/Rougamo.OpenTelemetry

Repository files navigation

Rougamo.OpenTelemetry

Rougamo.OpenTelemetry是用来丰富OpenTelemetry非IO埋点的组件, 其借助于Rougamo静态织入的功能,对指定方法增加Trace埋点

快速开始

在启动项目安装Rougamo.OpenTelemetry.Hosting, 然后在需要埋点的项目安装Rougamo.OpenTelemetry

dotnet add package Rougamo.OpenTelemetry.Hosting
dotnet add package Rougamo.OpenTelemetry

在启动项目Startup.cs中初始化Rougamo.OpenTelemetry

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // ...

        services.AddOpenTelemetryTracing(builder =>
        {
            builder
                .AddRougamoSource() // 初始化Rougamo.OpenTelemetry
                .AddAspNetCoreInstrumentation()
                .AddJaegerExporter();
        });

        // 修改Rougamo.OpenTelemetry默认配置
        services.AddOpenTelemetryRougamo(options =>
        {
            options.ArgumentsStoreType = ArgumentsStoreType.Tag;
        });
    }
}

之后便可以到项目中添加埋点,最简单的方式是通过在方法上添加OtelAttributePureOtelAttribute来为该方法添加埋点,两个Attribute的区别在于 OtelAttribute默认会记录参数和返回值,而PureOtelAttribute默认不会记录,当然,也可以分别配合ApmIgnoreAttributeApmRecordAttribute 忽略或记录指定参数或返回值

class Service
{
    [return: ApmIgnore]     // 返回值不记录
    [Otel] // 默认记录参数和返回值,需要通过ApmIgnoreAttribute来忽略不需要记录的参数或返回值
    public async Task<string> M1(
            [ApmIgnore] string uid, // 该参数不记录
            DateTime time)
    {
        // do something
        return string.Empty;
    }

    [PureOtel] // 默认不记录参数和返回值,需要通过ApmRecordAttribute来记录指定的参数或返回值
    public void M2(
            [ApmRecord] double d1,  // 记录该参数
            double d2)
    {
        // do something
    }
}

默认情况下,参数和返回值会记录到当前Span的Event中,可以像上面Startup示例代码那样修改参数和返回值存放位置, 当上面M1或M2方法被调用时便会生成一个对应的Span记录

通过接口批量织入

OpenTelemetry的本地埋点是通过Rougamo进行静态织入的,这也就表示我们可以使用Rougamo提供的各种 代码织入方法,所以我们可以使用实现空接口的方式进行织入

public interface ITestService : IRougamo<OtelAttribute>
{
    // ...
}
public class TestService : ITestService
{
    // ...
}

上面的代码中,由于ITestService实现了IRougamo<>泛型接口,并且制定OtelAttribute为泛型类型,所以ITestService的实现类TestService的 所有公开(public)实例(非static)方法将自动织入OtelAttribute的实现,这里之所以是公开实例方法,是因为OtelAttribute.Flags属性值默认为AccessFlags.InstancePublic, 除了公开实例的可访问性注入,下面列出了其他可访问性的Attribute,如果下面的可访问性还不能满足要求,可以根据自己的需求自己继承OtelAttributePureOtelAttribute, 然后重写Flags属性

最小版本要求 默认记录参数和返回值 默认不记录参数和返回值 可访问性
0.1.2 PublicOtelAttribute PublicPureOtelAttribute 所有public方法,无论是静态方法还是实例方法
0.1.2 StaticOtelAttribute StaticPureOtelAttribute 所有public static方法
0.1.2 FullOtelAttribute FullPureOtelAttribute 所有方法,不论可访问性如何

通过代理Attribute织入

代理Attribute织入同样是Rougamo提供的织入方式, 其中一种使用场景是结合Rougamo.APM.Abstractions使用,埋点的Attribute使用Rougamo.APM.Abstractions 提供的SpanAttributePureSpanAttribute,这两个Attribute并不会织入代码,仅仅用于标记,之后在通过代理的方式进行真正的织入

// Startup.cs或者AssemblyInfo.cs等项目其他任意位置添加下面的程序集级别的Attribute
[assembly: MoProxy(typeof(SpanAttribute), typeof(OtelAttribute))]
[assembly: MoProxy(typeof(PureSpanAttribute), typeof(PureOtelAttribute))]

public class Cls
{
    [Span]  // 最终通过代理织入OtelAttribute的代码实现
    public int M1()
    {
        // ...
        return 123;
    }

    [PureSpan]  // 最终通过代理织入PureOtelAttribute的代码实现
    private async Task<string> M2Async()
    {
        // ...
        return string.Empty;
    }
}

通过代理的方式无法使用接口织入,也无法自定义参数(OtelAttribute.Name),但使用这种方式的优势在于,如果你还不确定你的APM最终使用什么或者可能会换其他OpenTelemetry不支持的APM, 那么你使用这种代理的方式就可以仅仅修改上面实例代码中MoProxyAttribute指定代理类型的代码。

todo

  • English document

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published