全部產品
Search
文件中心

Application Real-Time Monitoring Service:通過Jaeger上報.NET應用資料

更新時間:Aug 08, 2024

通過Jaeger為應用埋點並上報鏈路資料至Managed Service for OpenTelemetry後,Managed Service for OpenTelemetry即可開始監控應用,您可以查看應用拓撲、調用鏈路、異常事務、慢事務和SQL分析等一系列監控資料。本文介紹如何使用OpenTracing/NetCore/gRPC組件進行自動埋點或通過手動埋點並上報.NET應用資料。

重要

為獲得更豐富的功能、更先進的鏈路追蹤能力,以及最佳使用體驗,建議您使用OpenTelemetry協議將應用接入Managed Service for OpenTelemetry

我們為您提供了詳細的OpenTelemetry接入指南和最佳實務,協助您快速上手Managed Service for OpenTelemetry。更多資訊,請參見接入應用

重要

目前Jaeger Client C#已不再維護,建議您使用OpenTelemetry .NET上報資料。具體操作,請參見通過OpenTelemetry上報.NET應用資料

前提條件

擷取存取點資訊

  1. 登入ARMS控制台,在左側導覽列單擊接入中心

  2. 服務端應用地區單擊Jaeger卡片。

  3. 在彈出的Jaeger面板中選擇資料需要上報的地區。

    說明

    初次接入的地區將會自動進行資源初始化。

  4. 選擇串連方式上報方式,然後複製存取點資訊。

    • 串連方式:若您的服務部署在阿里雲上,且所屬地區與選擇的接入地區一致,推薦使用阿里雲內網方式,否則選擇公網方式。

    • 上報方式:根據用戶端支援的協議類型選擇HTTP或gRPC協議上報資料。

    image.png

背景資訊

Jaeger是Uber推出的一款開源分布式追蹤系統,相容OpenTracing API,已在Uber大規模使用,且已加入CNCF開源組織。其主要功能是彙總來自各個異構系統的即時監控資料。

目前OpenTracing社區已有許多組件可支援各種.NET架構,例如:

資料是如何上報的?

  • 不通過Jaeger Agent而直接上報資料的原理如下圖所示。

  • 通過Jaeger Agent上報資料的原理如下圖所示。

樣本Demo

範例程式碼倉庫:dotnet-demo

.NET 6.0埋點

通過OpenTracing組件自動埋點

Demo源碼的運行版本要求:

  • Jaeger:1.0.2版本

  • .NET:6.0版本

  1. 在樣本專案的dotnet-demo/net6.0/Shared/JaegerServiceCollectionExtensions.cs檔案中填寫上報資料連接埠並修改上報服務名,用於實現ITracer對象的初始化和註冊邏輯。

    public static class JaegerServiceCollectionExtensions
    {
        // 參考前提條件擷取Jaeger Endpoint並填入參數
        private static readonly Uri _jaegerUri = new Uri("http://tracing-analysis-dc-sz.aliyuncs.com/adapt_your_token/api/traces");
    
        public static IServiceCollection AddJaeger(this IServiceCollection services)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services));
    
            services.AddSingleton<ITracer>(serviceProvider =>
            {
                // 可以將其修改為自訂的服務名
                string serviceName = Assembly.GetEntryAssembly().GetName().Name;
    
                ILoggerFactory loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
    
                ISampler sampler = new ConstSampler(sample: true);
    
                IReporter reporter = new RemoteReporter.Builder()
                    .WithSender(new HttpSender.Builder(_jaegerUri.ToString()).Build())
                    .Build();
    
                ITracer tracer = new Tracer.Builder(serviceName)
                    .WithLoggerFactory(loggerFactory)
                    .WithSampler(sampler)
                    .WithReporter(reporter)
                    .Build();
    
                GlobalTracer.Register(tracer);
    
                return tracer;
            });
    
            // Prevent endless loops when OpenTracing is tracking HTTP requests to Jaeger.
            services.Configure<HttpHandlerDiagnosticOptions>(options =>
            {
                options.IgnorePatterns.Add(request => _jaegerUri.IsBaseOf(request.RequestUri));
            });
    
            return services;
        }
    }
  2. 進入專案目錄dotnet-demo/net6.0/CustomersApi,然後運行以下命令。

    dotnet run --framework:net6.0
  3. 啟動本地服務,並訪問以下地址。

    http://localhost:5001/health
  4. 登入ARMS控制台後,在應用監控 > 應用列表頁面通過自訂的serviceName搜尋應用,查看上報的資料。

    說明

    語言列顯示image表徵圖的應用為接入應用監控的應用,顯示-表徵圖的應用為接入可觀測鏈路 OpenTelemetry 版的應用。

NET Core 3.1埋點

Demo源碼的運行版本要求:

  • Jaeger:1.0.2版本

  • .NET:3.1版本

通過NetCore組件自動埋點

  1. 在專案的dotnet-demo/netcoreapp3.1/Shared/JaegerServiceCollectionExtensions.cs中填寫上報資料連接埠並修改上報服務名,用於實現ITracer對象的初始化和註冊邏輯。

    public static class JaegerServiceCollectionExtensions
    {
        // 參考前提條件擷取Jaeger Endpoint並填入參數
        private static readonly Uri _jaegerUri = new Uri("http://tracing-analysis-dc-sz.aliyuncs.com/adapt_your_token/api/traces");
    
        public static IServiceCollection AddJaeger(this IServiceCollection services)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services));
    
            services.AddSingleton<ITracer>(serviceProvider =>
            {
                // 可以將其修改為自訂的服務名
                string serviceName = Assembly.GetEntryAssembly().GetName().Name;
    
                ILoggerFactory loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
    
                ISampler sampler = new ConstSampler(sample: true);
    
                IReporter reporter = new RemoteReporter.Builder()
                    .WithSender(new HttpSender.Builder(_jaegerUri.ToString()).Build())
                    .Build();
    
                ITracer tracer = new Tracer.Builder(serviceName)
                    .WithLoggerFactory(loggerFactory)
                    .WithSampler(sampler)
                    .WithReporter(reporter)
                    .Build();
    
                GlobalTracer.Register(tracer);
    
                return tracer;
            });
    
            // Prevent endless loops when OpenTracing is tracking HTTP requests to Jaeger.
            services.Configure<HttpHandlerDiagnosticOptions>(options =>
            {
                options.IgnorePatterns.Add(request => _jaegerUri.IsBaseOf(request.RequestUri));
            });
    
            return services;
        }
    }
  2. 進入專案目錄dotnet-demo/netcoreapp3.1/Shared,然後運行以下命令。

    // 添加aspnetcore中介軟體
    dotnet add  package OpenTracing.Contrib.NetCore
  3. 進入專案目錄dotnet-demo/netcoreapp3.1/CustomersApi,然後運行以下命令。

    // 添加aspnetcore中介軟體
    dotnet add  package OpenTracing.Contrib.NetCore
    // 運行樣本程式
    dotnet run --framework:netcoreapp3.1
  4. 啟動本地服務,並訪問以下地址。

    http://localhost:5001/health
  5. 登入ARMS控制台後,在應用監控 > 應用列表頁面通過自訂的serviceName搜尋應用,查看上報的資料。

    說明

    語言列顯示image表徵圖的應用為接入應用監控的應用,顯示-表徵圖的應用為接入可觀測鏈路 OpenTelemetry 版的應用。

通過gRPC組件自動埋點

  1. 安裝NuGet包。

    // 添加以下組件。
    // OpenTracing.Contrib.Grpc(gRPC中介軟體)
    // Jaeger(OpenTracing的實現組件)
    // Microsoft.Extensions.Logging.Console(日誌組件)
    
    dotnet add  package OpenTracing.Contrib.grpc
    dotnet add  package Jaeger
  2. 初始化ITracer對象。

    public static Tracer InitTracer(string serviceName, ILoggerFactory loggerFactory)
            {
                Configuration.SamplerConfiguration samplerConfiguration = new Configuration.SamplerConfiguration(loggerFactory)
                    .WithType(ConstSampler.Type)
                    .WithParam(1);
                Configuration.SenderConfiguration senderConfiguration = new Configuration.SenderConfiguration(loggerFactory)
                        // 參考前提條件擷取Jaeger Endpoint並填入參數
                       .WithEndpoint("http://tracing-analysis-dc-sz.aliyuncs.com/adapt_your_token/api/traces");
                Configuration.ReporterConfiguration reporterConfiguration = new Configuration.ReporterConfiguration(loggerFactory)
                    .WithSender(senderConfiguration);
    
                return (Tracer)new Configuration(serviceName, loggerFactory)
                    .WithSampler(samplerConfiguration)
                    .WithReporter(reporterConfiguration)
                    .GetTracer();
            }
  3. 在服務端埋點。構建用於埋點的ServerTracingInterceptor對象,並將ServerTracingInterceptor綁定到服務上。

    ILoggerFactory loggerFactory = new LoggerFactory().AddConsole();
    ITracer tracer = TracingHelper.InitTracer("dotnetGrpcServer", loggerFactory);
    ServerTracingInterceptor tracingInterceptor = new ServerTracingInterceptor(tracer);
    Server server = new Server
     {
        Services = { Greeter.BindService(new GreeterImpl()).Intercept(tracingInterceptor) },
         Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
     };
  4. 在用戶端埋點。構建用於埋點的ClientTracingInterceptor對象,並將ClientTracingInterceptor綁定到Channel上。

    ILoggerFactory loggerFactory = new LoggerFactory().AddConsole();
    ITracer tracer = TracingHelper.InitTracer("dotnetGrpcClient", loggerFactory);
    ClientTracingInterceptor tracingInterceptor = new ClientTracingInterceptor(tracer);
    Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
    
    var client = new Greeter.GreeterClient(channel.Intercept(tracingInterceptor));
  5. 進入專案目錄dotnet-demo/netcoreapp3.1/GreeterServer,然後在終端運行以下命令開啟gRPC的服務端。

    dotnet run --framework:netcoreapp3.1
  6. 進入專案目錄dotnet-demo/netcoreapp3.1/GreeterClient,然後在另一個終端運行以下命令開啟gRPC的用戶端。

    dotnet run --framework:netcoreapp3.1

    如果終端輸出Greeting: Hello you,說明服務端和用戶端之間通訊成功,在控制台可以看到樣本應用dotnetGrpcServerdotnetGrpcClient上報的資料。

手動埋點

除了利用各種現有外掛程式實現埋點外,還可以使用手動埋點的方法通過Jaeger將.NET應用資料上報至Managed Service for OpenTelemetry控制台。

  1. 安裝NuGet包。

    // Jaeger(OpenTracing的實現組件)
    // Microsoft.Extensions.Logging.Console(日誌組件)
    
    dotnet add  package Microsoft.Extensions.Logging.Console
    dotnet add  package Jaeger
  2. 構建ITracer對象。ITracer是OpenTracing定義的對象,我們用Jaeger來構建該對象(配置網關、採樣率等)。

    public static ITracer InitTracer(string serviceName, ILoggerFactory loggerFactory)
     {
        Configuration.SamplerConfiguration samplerConfiguration = new Configuration.SamplerConfiguration(loggerFactory)
              .WithType(ConstSampler.Type)
              .WithParam(1);
        Configuration.SenderConfiguration senderConfiguration = new Configuration.SenderConfiguration(loggerFactory)
               // 在可觀測鏈路 OpenTelemetry 版控制台擷取Jaeger Endpoint。
              .WithEndpoint("http://tracing-analysis-dc-sz.aliyuncs.com/adapt_your_token/api/traces");
    
       Configuration.ReporterConfiguration reporterConfiguration = new Configuration.ReporterConfiguration(loggerFactory)
              .WithSender(senderConfiguration);
    
       return (Tracer)new Configuration(serviceName, loggerFactory)
              .WithSampler(samplerConfiguration)
              .WithReporter(reporterConfiguration)
            .GetTracer();
    }
  3. 將ITracer註冊到GlobalTracer中,方便調用代碼。

    GlobalTracer.Register(InitTracer("dotnetManualDemo", loggerFactory ));
  4. 記錄請求資料。

    ITracer tracer = GlobalTracer.Instance;
    ISpan span = tracer.BuildSpan("parentSpan").WithTag("mytag","parentSapn").Start();
    tracer.ScopeManager.Activate(span, false);
    // ... do something
    span.Finish();
    說明

    以上代碼用於記錄請求的根操作,如果需要記錄請求的上一步和下一步操作,則需要調用AsChildOf方法。

    樣本:

    ITracer tracer = GlobalTracer.Instance;
    ISpan parentSpan = tracer.ActiveSpan;
    ISpan childSpan =tracer.BuildSpan("childSpan").AsChildOf(parentSpan).WithTag("mytag", "spanSecond").Start();
    tracer.ScopeManager.Activate(childSpan, false);
    // ... do something
    childSpan.Finish();
  5. 可選:為了快速排查問題,您可以為某個記錄添加一些自訂標籤,例如記錄是否發生錯誤、請求的傳回值等。

    tracer.activeSpan().setTag("http.status_code", "200");
  6. 在分布式系統中發送RPC請求時會帶上Tracing資料,包括TraceId、ParentSpanId、SpanId、Sampled等。您可以在HTTP請求中使用Extract/Inject方法在HTTP Request Headers上透傳資料。總體流程如下:

    流程圖

    1. 在用戶端調用Inject方法傳入Context資訊。

      Tracer.Inject(span.Context, BuiltinFormats.HttpHeaders, new HttpHeadersInjectAdapter(request.Headers));
    2. 在服務端調用Extract方法解析Context資訊。

      ISpanContext extractedSpanContext = _tracer.Extract(BuiltinFormats.HttpHeaders, new RequestHeadersExtractAdapter(request.Headers));
      ISpan childSpan = _tracer.BuildSpan(operationName).AsChildOf(extractedSpanContext);
  7. 進入專案目錄dotnet-demo/netcoreapp3.1/ManualDemo,然後運行以下命令,樣本程式將會上報資料。

    dotnet run --framework:netcoreapp3.1

    在控制台可以查看手動埋點的樣本應用dotnetManualDemo上報的資料。

常見問題

Q1:Demo程式執行成功,為什麼控制台上沒有上報資料?

A1:請檢查senderConfiguration配置中的Endpoint是否填寫正確。

Configuration.SenderConfiguration senderConfiguration = new Configuration.SenderConfiguration(loggerFactory)
           // 在可觀測鏈路 OpenTelemetry 版控制台擷取Jaeger Endpoint。
          .WithEndpoint("http://tracing-analysis-dc-sz.aliyuncs.com/adapt_your_token/api/traces");

Q2:如何設定採樣率?

A2:具體詳情,請參見Jaeger採樣率文檔