【问题标题】:OpenTracing in .NET core without taking dependency on specific solution library.NET 核心中的 OpenTracing,不依赖特定的解决方案库
【发布时间】:2019-05-03 03:36:37
【问题描述】:

为了登录我们的微服务应用程序,我们只需登录到 stdout/console,docker logging 驱动程序会处理并将这些日志重定向到某个地方,例如gelf/logstash、fluentd 等。基本上,我们遵循12 factor 日志记录指南。这意味着开发应用程序代码的开发人员不需要了解底层日志记录解决方案(例如 Elasticsearch、Graylog、Splunk 等)——这完全是一个操作/配置问题。理论上,我们应该能够在不更改任何代码的情况下更改底层日志记录解决方案。

我想要类似的跟踪信息,我的研究使我选择了 OpenTracing。开发人员不需要了解底层跟踪解决方案(例如 Jaeger、Zipkin、Elastic APM 等)和日志记录;理论上,我们应该能够在不更改任何代码的情况下更改底层跟踪解决方案。

我已经使用 opentracing/opentracing-csharpjaegertracing/jaeger-client-csharp 库成功地获得了一个 .NET 核心 POC 向 Jaeger 发送跟踪信息。

我仍在尝试完全了解 OpenTracing,但我想知道是否有一种方法可以将跟踪发送到符合 OpenTracing 的 API,而不必硬依赖 Jaeger 等特定解决方案(即jaeger-client-csharp 库)。根据我的理解,OpenTracing 只是一个标准。难道我不需要 jaeger-client-csharp 库就可以使用一些采样选项配置 OpenTracing 端点吗?还是 jaeger-client-csharp 实际上不是 Jaeger 特定的,实际上可以将跟踪发送到任何 OpenTracing API?

下图示例配置,使用了 jaeger 客户端库:

services.AddOpenTracing();

if (appSettings.TracerEnabled)
{
   services.AddSingleton(serviceProvider =>
   {
      var loggerFactory = new LoggerFactory();
      var config = Jaeger.Configuration.FromEnv(loggerFactory);

      var tracer = config.GetTracer();

      GlobalTracer.Register(tracer);

      return tracer;
   });
}

【问题讨论】:

    标签: .net-core microservices opentracing 12factor jaeger


    【解决方案1】:

    OpenTracingis a set of standard APIs that consistently model and describe the behavior of distributed systems)

    OpenTracing 没有描述如何收集、报告、存储或表示相互关联的跟踪和跨度的数据。是实现细节(如jaegerwavefront)。

    jaeger-client-csharp 是非常特定于 jaeger 的。但是有一个例外,称为zipkin,它又不完全符合 OpenTracing,即使它有类似的术语。

    如果你对opentracing-contrib/csharp-netcore 没问题(希望你正在使用这个库)那么如果你想实现“无代码更改”(在目标微服务中)以配置跟踪子系统,你应该使用一些插件模型.

    好消息,aspnetcore 有hosted startup assemblies 的概念,它允许您配置跟踪系统。因此,您可以拥有一些名为 JaegerStartup 的库,您将在其中实现 IHostedStartup,如下所示:

    public class JaegerStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureServices((ctx, services) =>
            {
                services.AddOpenTracing();
    
                if (ctx.Configuration.IsTracerEnabled()) // implement it by observing your section in configuration.
                {
                    services.AddSingleton(serviceProvider =>
                    {
                        var loggerFactory = new LoggerFactory();
                        var config = Jaeger.Configuration.FromEnv(loggerFactory);
    
                        var tracer = config.GetTracer();
    
                        GlobalTracer.Register(tracer);
    
                        return tracer;
                    });
                }
            });
        }
    }
    

    当你决定切换跟踪系统时——你需要创建另一个库,它可以自动加载,并且不会触及目标微服务代码。

    【讨论】:

    • 感谢您的好评。 IHostingStartup 是一种比我目前拥有的更好的方法 - 让我想起了 MEF。最终,我希望能够通过配置在 Open-Tracing/Telemetry 兼容的跟踪器(例如 ElasticAPM、Jaeger 等)之间切换。如果我错了,请纠正我,但 IHostingStartup 方法仍然需要重新编译(或至少重建 docker 映像)。理想情况下,更改跟踪器将是一个 OPS 问题。
    • 还有;是的 - 使用 opentracing-contrib/csharp-netcore 库:) 我想我想要的是 reporting API 的一些标准化。这意味着您可以使用您想要的任何(OT 兼容)客户端库/代理,例如elastic/apm-agent-dotnet 和底层跟踪器解决方案可能是其他东西,例如Datadog 或 Wavefront 等。我怀疑 OpenTracing 还没有达到这个成熟度,或者没有尝试解决这个问题......
    • 您不需要重新编译或重建。您需要创建新的单独库(仅在此处需要编译),其中包含新跟踪器的注入逻辑。当您拥有新库时,OPS 人员将获取新库并更改 environment variable called ASPNETCORE_HOSTINGSTARTUPASSEMBLIES。报告 API 是实现细节。您应该直接使用 DiagnosticsSource 或 ITracer 来收集和报告跟踪和跨度。
    【解决方案2】:

    我认为这应该更新,现在我们有 ELlastic APM 服务器支持的 Opentelemtry dirrect 以及 NetCore Activity 类中的 nativ 支持..

    public static partial class ServiceExtension {
    
            public static IServiceCollection AddTelemerty(
                this IServiceCollection serviceCollection,
                IConfiguration Configuration, IWebHostEnvironment Environment) {
    
                serviceCollection.AddOpenTelemetryTracing((builder) => {
                    // Sources
                    builder.AddSource(Sources.DemoSource.Name);
    
                    builder.SetResourceBuilder(ResourceBuilder
                      .CreateDefault()
                        //.AddAttributes( new List<KeyValuePair<String, object>> { 
                        //   new KeyValuePair<String, object>("SomeKey", "This is String Value")
                        //  })
                      .AddService(Environment.ApplicationName));
    
                    builder.AddAspNetCoreInstrumentation(opts => {
                        opts.RecordException = true;
                    });
    
                    builder.AddElasticsearchClientInstrumentation();
    
                    builder.AddSqlClientInstrumentation();
    
                    builder.AddHttpClientInstrumentation(opts => opts.RecordException = true);
    
                    if (Uri.TryCreate(Configuration.GetConnectionString("Jaeger"), UriKind.Absolute, out var uri)) {
                        builder.AddJaegerExporter(opts => {
                            opts.AgentHost = uri.Host;
                            opts.AgentPort = uri.Port;
                            opts.BatchExportProcessorOptions = new OpenTelemetry.BatchExportProcessorOptions<Activity>() {
                            };
                        });
                    
                        // builder.AddZipkinExporter(opts => {
                        //     opts.Endpoint = new Uri("http://localhost:9412/api/v2/spans");
                        // });
                    }
                });
    
                return serviceCollection;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 2017-09-28
      相关资源
      最近更新 更多