通過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應用資料。
前提條件
背景資訊
Jaeger是Uber推出的一款開源分布式追蹤系統,相容OpenTracing API,已在Uber大規模使用,且已加入CNCF開源組織。其主要功能是彙總來自各個異構系統的即時監控資料。
目前OpenTracing社區已有許多組件可支援各種.NET架構,例如:
樣本Demo
範例程式碼倉庫:dotnet-demo
.NET 6.0埋點
通過OpenTracing組件自動埋點
Demo源碼的運行版本要求:
Jaeger:1.0.2版本
.NET:6.0版本
在樣本專案的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; } }
進入專案目錄dotnet-demo/net6.0/CustomersApi,然後運行以下命令。
dotnet run --framework:net6.0
啟動本地服務,並訪問以下地址。
http://localhost:5001/health
登入ARMS控制台後,在 頁面通過自訂的serviceName搜尋應用,查看上報的資料。
說明語言列顯示表徵圖的應用為接入應用監控的應用,顯示-表徵圖的應用為接入可觀測鏈路 OpenTelemetry 版的應用。
NET Core 3.1埋點
Demo源碼的運行版本要求:
Jaeger:1.0.2版本
.NET:3.1版本
通過NetCore組件自動埋點
在專案的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; } }
進入專案目錄dotnet-demo/netcoreapp3.1/Shared,然後運行以下命令。
// 添加aspnetcore中介軟體 dotnet add package OpenTracing.Contrib.NetCore
進入專案目錄dotnet-demo/netcoreapp3.1/CustomersApi,然後運行以下命令。
// 添加aspnetcore中介軟體 dotnet add package OpenTracing.Contrib.NetCore // 運行樣本程式 dotnet run --framework:netcoreapp3.1
啟動本地服務,並訪問以下地址。
http://localhost:5001/health
登入ARMS控制台後,在 頁面通過自訂的serviceName搜尋應用,查看上報的資料。
說明語言列顯示表徵圖的應用為接入應用監控的應用,顯示-表徵圖的應用為接入可觀測鏈路 OpenTelemetry 版的應用。
通過gRPC組件自動埋點
安裝NuGet包。
// 添加以下組件。 // OpenTracing.Contrib.Grpc(gRPC中介軟體) // Jaeger(OpenTracing的實現組件) // Microsoft.Extensions.Logging.Console(日誌組件) dotnet add package OpenTracing.Contrib.grpc dotnet add package Jaeger
初始化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(); }
在服務端埋點。構建用於埋點的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) } };
在用戶端埋點。構建用於埋點的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));
進入專案目錄dotnet-demo/netcoreapp3.1/GreeterServer,然後在終端運行以下命令開啟gRPC的服務端。
dotnet run --framework:netcoreapp3.1
進入專案目錄dotnet-demo/netcoreapp3.1/GreeterClient,然後在另一個終端運行以下命令開啟gRPC的用戶端。
dotnet run --framework:netcoreapp3.1
如果終端輸出
Greeting: Hello you
,說明服務端和用戶端之間通訊成功,在控制台可以看到樣本應用dotnetGrpcServer和dotnetGrpcClient上報的資料。
手動埋點
除了利用各種現有外掛程式實現埋點外,還可以使用手動埋點的方法通過Jaeger將.NET應用資料上報至Managed Service for OpenTelemetry控制台。
安裝NuGet包。
// Jaeger(OpenTracing的實現組件) // Microsoft.Extensions.Logging.Console(日誌組件) dotnet add package Microsoft.Extensions.Logging.Console dotnet add package Jaeger
構建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(); }
將ITracer註冊到GlobalTracer中,方便調用代碼。
GlobalTracer.Register(InitTracer("dotnetManualDemo", loggerFactory ));
記錄請求資料。
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();
可選:為了快速排查問題,您可以為某個記錄添加一些自訂標籤,例如記錄是否發生錯誤、請求的傳回值等。
tracer.activeSpan().setTag("http.status_code", "200");
在分布式系統中發送RPC請求時會帶上Tracing資料,包括TraceId、ParentSpanId、SpanId、Sampled等。您可以在HTTP請求中使用Extract/Inject方法在HTTP Request Headers上透傳資料。總體流程如下:
在用戶端調用Inject方法傳入Context資訊。
Tracer.Inject(span.Context, BuiltinFormats.HttpHeaders, new HttpHeadersInjectAdapter(request.Headers));
在服務端調用Extract方法解析Context資訊。
ISpanContext extractedSpanContext = _tracer.Extract(BuiltinFormats.HttpHeaders, new RequestHeadersExtractAdapter(request.Headers)); ISpan childSpan = _tracer.BuildSpan(operationName).AsChildOf(extractedSpanContext);
進入專案目錄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採樣率文檔。