链路追踪可以帮助开发者快速定位分布式应用架构下的性能瓶颈 , 提高微服务时代的开发诊断效率 。
OpenTracing
前面提到的 Trace 、Debug 是 .NET Core 中提供给开发者用于诊断程序和输出信息的 API , 而接着提到的 trace 只 OpenTracing API 中的 链路跟踪(trace) 。
普通的日志记录有很大的缺点 , 就是每个方法记录一个日志 , 我们无法将一个流程中被调用的多个方法联系起来 。 当一个方法出现异常时 , 我们很难知道是哪个任务过程出现的异常 。 我们只能看到哪个方法出现错误 , 已经它的调用者 。
在 OpenTracing 中 , Trace 是具有 Span(跨度) 的有向无环图 。 一个 Span 代表应用程序中完成某些工作的逻辑表示 , 每个 Span 都具有以下属性:
为了弄清楚 , Trace 和 Span 是什么 , OpenTracing 又是什么 , 请在 Nuget 中引入 OpenTracing 。
编写 Hello 类如下:
publicclassHello{privatereadonlyITracer _tracer; privatereadonlyILogger<Hello> _logger; publicHello( ITracer tracer, ILoggerFactory loggerFactory) {_tracer = tracer;_logger = loggerFactory.CreateLogger<Hello>;}publicvoidSayHello( stringcontent ) {// 创建一个 Span 并开始varspanBuilder = _tracer.BuildSpan( "say-hello"); // -------------------------------varspan = spanBuilder.Start; // |varstr = $"Hello, {content}" ; // |_logger.LogInformation(str); // |span.Finish; // |// ---------------------------------}}
启动程序 , 并开始追踪:
staticvoidMain( string[] args ) {usingILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole); Hello hello = newHello(GlobalTracer.Instance, loggerFactory); hello.SayHello( "This trace"); Console.Read;}
在以上过程中 , 我们使用了 OpenTracing API , 下面是关于代码中一些元素的说明:
- ITracer 是一个链路追踪实例 , BuildSpan 可以创建其中一个 Span;
- 每个 ISpan 都有一个操作名称 , 例如 say-hello;
- 使用 Start 开始一个 Span;使用 Finish 结束一个 Span;
- 跟踪程序会自动记录时间戳;
当然 , 我们运行上面的程序时 , 是没有出现别的信息以及 UI 界面 , 这是因为 GlobalTracer.Instance 会返回一个无操作的 tracer 。 当我们定义一个 Tracer 时 , 可以观察到链路追踪的过程 。
在 Nuget 中 , 引入 Jaeger 。
在 Program 中 , 添加一个静态函数 , 这个函数返回了一个自定义的 Tracer:
privatestaticTracer InitTracer( stringserviceName, ILoggerFactory loggerFactory ) {varsamplerConfiguration = newConfiguration.SamplerConfiguration(loggerFactory) .WithType(ConstSampler.Type).WithParam( 1); varreporterConfiguration = newConfiguration.ReporterConfiguration(loggerFactory) .WithLogSpans( true);
return(Tracer) newConfiguration(serviceName, loggerFactory) .WithSampler(samplerConfiguration).WithReporter(reporterConfiguration).GetTracer;}
修改 Main 函数内容如下:
staticvoidMain( string[] args ) {usingILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole); vartracer = InitTracer( "hello-world", loggerFactory); Hello hello = newHello(tracer, loggerFactory); hello.SayHello( "This trace"); Console.Read;}完整代码:
上下文和跟踪功能
但是 , 日志直接输出 string 是很不友好的 , 这时 , 我们需要结构化日志 。
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。