通過(guò)Zipkin上報(bào) .NET應(yīng)用數(shù)據(jù)
通過(guò)Zipkin為應(yīng)用埋點(diǎn)并上報(bào)鏈路數(shù)據(jù)至可觀測(cè)鏈路 OpenTelemetry 版后,可觀測(cè)鏈路 OpenTelemetry 版即可開(kāi)始監(jiān)控應(yīng)用,您可以查看應(yīng)用拓?fù)洹⒄{(diào)用鏈路、異常事務(wù)、慢事務(wù)和SQL分析等一系列監(jiān)控?cái)?shù)據(jù)。本文介紹如何使用ASP.NET Core/Owin組件進(jìn)行自動(dòng)埋點(diǎn)或直接進(jìn)行手動(dòng)埋點(diǎn)。
為獲得更豐富的功能、更先進(jìn)的鏈路追蹤能力,以及最佳使用體驗(yàn),建議您使用OpenTelemetry協(xié)議將應(yīng)用接入可觀測(cè)鏈路 OpenTelemetry 版。
我們?yōu)槟峁┝嗽敿?xì)的OpenTelemetry接入指南和最佳實(shí)踐,幫助您快速上手可觀測(cè)鏈路 OpenTelemetry 版。更多信息,請(qǐng)參見(jiàn)接入應(yīng)用。
前提條件
登錄ARMS控制臺(tái),在左側(cè)導(dǎo)航欄單擊接入中心。
在服務(wù)端應(yīng)用區(qū)域單擊Zipkin卡片。
在彈出的Zipkin面板中選擇數(shù)據(jù)需要上報(bào)的地域。
說(shuō)明初次接入的地域?qū)?huì)自動(dòng)進(jìn)行資源初始化。
選擇連接方式,然后復(fù)制接入點(diǎn)信息。
說(shuō)明若您的服務(wù)部署在阿里云上,且所屬地域與選擇的接入地域一致,推薦使用阿里云內(nèi)網(wǎng)方式,否則選擇公網(wǎng)方式。
一般情況下請(qǐng)使用v2版本接入點(diǎn),v1版本接入點(diǎn)推薦對(duì)Zipkin十分了解的高階用戶(hù)使用。
背景信息
Zipkin是一款開(kāi)源的分布式實(shí)時(shí)數(shù)據(jù)追蹤系統(tǒng)(Distributed Tracking System),由Twitter公司開(kāi)發(fā)和貢獻(xiàn)。其主要功能是聚合來(lái)自各個(gè)異構(gòu)系統(tǒng)的實(shí)時(shí)監(jiān)控?cái)?shù)據(jù)。
通過(guò)ASP.NET Core組件自動(dòng)埋點(diǎn)
請(qǐng)按照以下步驟通過(guò)ASP.NET Core組件埋點(diǎn)。
下載Demo源碼,并按照Readme的說(shuō)明運(yùn)行程序。
安裝NuGet包。
// 添加以下組件。 // zipkin4net.middleware.aspnetcore(aspnetcore中間件) // zipkin4net(追蹤器) dotnet add package zipkin4net.middleware.aspnetcore dotnet add package zipkin4net
注冊(cè)和啟動(dòng)Zipkin。
lifetime.ApplicationStarted.Register(() => { TraceManager.SamplingRate = 1.0f; var logger = new TracingLogger(loggerFactory, "zipkin4net"); // 在可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)獲取Zipkin Endpoint,注意Endpoint中不包含“/api/v2/spans”。 var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer()); TraceManager.RegisterTracer(tracer); TraceManager.Start(logger); }); lifetime.ApplicationStopped.Register(() => TraceManager.Stop()); app.UseTracing(applicationName);
在發(fā)送Get/Post請(qǐng)求的HttpClient中添加tracinghandler(追蹤處理者)。
public override void ConfigureServices(IServiceCollection services) { services.AddHttpClient("Tracer").AddHttpMessageHandler(provider => TracingHandler.WithoutInnerHandler(provider.GetService<IConfiguration>()["applicationName"])); }
通過(guò)Owin組件自動(dòng)埋點(diǎn)
請(qǐng)按照以下步驟通過(guò)Owin組件埋點(diǎn)。
下載Demo源碼,并按照Readme的說(shuō)明運(yùn)行程序。
安裝NuGet包。
// 添加以下組件。 // zipkin4net.middleware.aspnetcore(aspnetcore中間件) // zipkin4net(追蹤器) dotnet add package zipkin4net.middleware.aspnetcore dotnet add package zipkin4net
注冊(cè)和啟動(dòng)Zipkin。
// 設(shè)置Tracing。 TraceManager.SamplingRate = 1.0f; var logger = new ConsoleLogger(); // 在可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)獲取Zipkin Endpoint,注意Endpoint中不包含“/api/v2/spans”。 var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer()); TraceManager.RegisterTracer(tracer); TraceManager.Start(logger); //Stop TraceManager on app dispose var properties = new AppProperties(appBuilder.Properties); var token = properties.OnAppDisposing; if (token != CancellationToken.None) { token.Register(() => { TraceManager.Stop(); }); } // Setup Owin Middleware appBuilder.UseZipkinTracer(System.Configuration.ConfigurationManager.AppSettings["applicationName"]);
在發(fā)送Get/Post請(qǐng)求的HttpClient中添加tracinghandler(追蹤處理者)。
using (var httpClient = new HttpClient(new TracingHandler(applicationName))) { var response = await httpClient.GetAsync(callServiceUrl); var content = await response.Content.ReadAsStringAsync(); await context.Response.WriteAsync(content); }
手動(dòng)埋點(diǎn)
要通過(guò)Zipkin將.Net應(yīng)用數(shù)據(jù)上報(bào)至可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái),除了利用各種現(xiàn)有插件實(shí)現(xiàn)埋點(diǎn)的目的,也可以手動(dòng)埋點(diǎn)。
下載Demo源碼,并按照Readme的說(shuō)明運(yùn)行程序。
安裝NuGet包。
// 添加zipkin4net(追蹤器)。 dotnet add package zipkin4net
注冊(cè)和啟動(dòng)Zipkin。
TraceManager.SamplingRate = 1.0f; var logger = new ConsoleLogger(); // 在可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)獲取Zipkin Endpoint,注意Endpoint中不包含“/api/v2/spans”。 var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer()); TraceManager.RegisterTracer(tracer); TraceManager.Start(logger);
記錄請(qǐng)求數(shù)據(jù)。
var trace = Trace.Create(); Trace.Current = trace; trace.Record(Annotations.ClientSend()); trace.Record(Annotations.Rpc("client")); trace.Record(Annotations.Tag("mytag", "spanFrist")); trace.Record(Annotations.ServiceName("dotnetManual")); // ...do something testCall(); trace.Record(Annotations.ClientRecv());
說(shuō)明以上代碼用于記錄請(qǐng)求的根操作,如果需要記錄請(qǐng)求的上一步和下一步操作,則需要調(diào)用ChildOf方法。示例:
var trace = Trace.Current.Child(); Trace.Current = trace; trace.Record(Annotations.ServerRecv()); trace.Record(Annotations.Rpc("server")); trace.Record(Annotations.Tag("mytag", "spanSecond")); trace.Record(Annotations.ServiceName("dotnetManual")); // ...do something trace.Record(Annotations.ServerSend());
可選:為了快速排查問(wèn)題,您可以為某個(gè)記錄添加一些自定義標(biāo)簽,例如記錄是否發(fā)生錯(cuò)誤、請(qǐng)求的返回值等。
tracer.activeSpan().setTag("http.status_code", "200");
在分布式系統(tǒng)中發(fā)送RPC請(qǐng)求時(shí)會(huì)帶上Tracing數(shù)據(jù),包括TraceId、ParentSpanId、SpanId、Sampled等。您可以在HTTP請(qǐng)求中使用Extract/Inject方法在HTTP Request Headers上透?jìng)鲾?shù)據(jù)。總體流程如下:
Client Span Server Span ┌──────────────────┐ ┌──────────────────┐ │ │ │ │ │ TraceContext │ Http Request Headers │ TraceContext │ │ ┌──────────────┐ │ ┌───────────────────┐ │ ┌──────────────┐ │ │ │ TraceId │ │ │ X-B3-TraceId │ │ │ TraceId │ │ │ │ │ │ │ │ │ │ │ │ │ │ ParentSpanId │ │ Inject │ X-B3-ParentSpanId │Extract │ │ ParentSpanId │ │ │ │ ├─┼─────────>│ ├────────┼>│ │ │ │ │ SpanId │ │ │ X-B3-SpanId │ │ │ SpanId │ │ │ │ │ │ │ │ │ │ │ │ │ │ Sampled │ │ │ X-B3-Sampled │ │ │ Sampled │ │ │ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ │ │ │ │ │ └──────────────────┘ └──────────────────┘
在客戶(hù)端調(diào)用Inject方法傳入Context信息。
_injector.Inject(clientTrace.Trace.CurrentSpan, request.Headers);
在服務(wù)端調(diào)用Extract方法解析Context信息。
Ivar traceContext = traceExtractor.Extract(context.Request.Headers); var trace = traceContext == null ? Trace.Create() : Trace.CreateFromId(traceContext);
常見(jiàn)問(wèn)題
問(wèn):Demo程序執(zhí)行成功,為什么控制臺(tái)上沒(méi)有上報(bào)數(shù)據(jù)?
答:請(qǐng)檢查senderConfiguration配置中的Endpoint是否填寫(xiě)正確。
// 在可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)獲取Zipkin Endpoint,注意Endpoint中不包含“/api/v2/spans”。
var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json");