深入研究.NET 5的开放式遥测
OpenTelemetry 介绍
OpenTelemetry是一种开放的源代码规范,工具和SDK,用于检测,生成,收集和导出遥测数据(指标,日志和跟踪),开放遥测技术得到了Cloud Native Computing Foundation(CNCF)的支持,该基金会支持一系列流行的优秀的开源项目,你可以去看一下CNCF景观图,https://landscape.cncf.io/ ,就明白了我的意思,这个SDK支持所有主要的编程语言,包括C#和ASP.NET Core。
在这篇文章中,我将讨论OpenTelemetry的全部含义,为什么要使用它以及如何在.NET中使用,对于典型的应用程序,通常需要记录三组数据:指标,日志和跟踪。
Logging 日志
可以监听程序的进程发出的消息日志,在.NET应用程序中,如果您使用NuGet包ILogger中的日志记录功能,就可以轻松的让OpenTelemetry支持 Microsoft.Extensions.Logging, 如果要构建ASP.NET Core应用程序,通常已经使用了此功能。
Metrics 指标
提供运行进程的指标信息,包括计数器,仪表盘和直方图,对OpenTelemetry中指标的支持仍在开发中, 但是已经确定下来了,指标包括以下:
- CPU 使用百分比
- 进程内存使用量
- Http的请求数量
Tracing 追踪
也叫做分布式跟踪,它记录单个操作的开始和结束时间以及与该操作相关的参数,比如在ASP.NET Core中记录HTTP请求的跟踪,您可能会记录请求和响应的开始和结束时间,参数将是 Http的请求方式,请求参数,请求地址等,请求调用会形成链路,您可以深入了解时间耗费在哪个服务,或者服务中有异常报错发生。
Jaeger
收集指标,日志,追踪信息只是一部分,如何进行数据处理,展示是APM系统的功能,因为收集的数据遵循OpenTelemetry标准,所以可以和APM系统完美结合。
Jaeger和Zipkin是可以收集和显示并且与Open Telemetry兼容APM, Zipkin的话比较久了,并且没有很好的UI,因此我个人推荐Jaeger,看起来像这样:
上图显示了应用程序的跟踪,您可以看到它如何使用HTTP请求对MySQL,Redis和外部API进行调用, 每行的长度显示了执行所需的时间,您可以轻松地从头到尾查看跟踪中执行的所有主要操作,您还可以深入研究每一行,并查看与该部分跟踪有关的其他信息。
Spans 跨度
上面Jaeger图中的每一行都称为 Span,在.NET中的每一行均由System.Activities.Activity类型表示,它也具有唯一的标识符,开始和结束时间以及父范围的唯一标识符,所以这些可以形成调用链,并且Span还可以包含其他参数。
不幸的是,.NET团队的命名大大偏离了官方的OpenTelemetry规范,我有点疑惑,不过我现在已经明白了大概。
我的理解是.NET已经包含一个Activity的类型,因此.NET团队决定重用它,而不是重新创建一个 Span的新类型,这意味着很多命名与open-telemetry规范不匹配,在.NET中,你现在可以把 Span 和 Activity身份互换。
注意:在.NET 5中才有ActivitySource,在之前可以用 Activity。
使用Span记录行为非常简单,首先,我们必须创建一个ActivitySource可以记录Span或活动的对象:
private static ActivitySource activitySource = new ActivitySource(
"companyname.product.library",
"semver1.0.0");
然后,我们可以调用StartActivity开始记录,最后调用Dispose停止记录Span:
using (var activity = activitySource.StartActivity("ActivityName")
{
// Pretend to do some work.
await LongRunningAsync().ConfigureAwait(false);
} // Activity gets stopped automatically at end of this block during dispose.
Events 事件
当Span开启记录后,我们也可以在这期间记录事件,这些事件包含了时间戳信息:
using (var activity = activitySource.StartActivity("ActivityName")
{
await LongRunningOperation().ConfigureAwait(false);
}
public async Task LongRunningOperationAsync()
{
await Task.Delay(1000).ConfigureAwait(false);
// Log timestamped events that can take place during an activity.
Activity.Current?.AddEvent(new ActivityEvent("Something happened."));
}
在LongRunningOperationAsync方法中,有一个问题是,如何把activity传入这个方法,如果我们定义了一个参数,这体验也太差了,但是,将两个操作分离的一个好的方法是使用Activity.Current。
一个常见的错误,我可以预见的是,Activity.Current可能是null,所以这里我加了null判断。
Attributes 属性
属性是数据的键值对,您可以将其记录为单个Span的一部分,比如Http的请求方式,请求状态码等。
注意,在Open Telemetry规范中叫 Attributes,在 我们.NET 中叫Tag
using (var activity = activitySource.StartActivity("ActivityName")
{
await LongRunningOperation().ConfigureAwait(false);
}
public async Task LongRunningOperationAsync()
{
await Task.Delay(1000).ConfigureAwait(false);
// Log an attribute containing arbitrary data.
Activity.Current?.SetTag("http.method", "GET");
}
IsRecording 记录
IsRecording是Span上的一个标志,如果返回false,表明该Span已结束,另外,如果你的数据量比较大的话,你需要抽样采集,比如10%,那么你也可以手动把这些span设置为false,它不会采集。
注意:在open-telemetryg规范中叫IsRecording,在.NET Core 3.1中是 Recorded,在.NET 5 中是 IsAllDataRequested。
using (var activity = activitySource.StartActivity("ActivityName")
{
await LongRunningOperation().ConfigureAwait(false);
}
public async Task LongRunningOperationAsync()
{
await Task.Delay(1000).ConfigureAwait(false);
// It's possible to optionally request more data from a particular span.
var activity = Activity.Current;
if (activity != null && activity.IsAllDataRequested)
{
activity.SetTag("http.url", "http://www.mywebsite.com");
}
}
Trace的语义约定
注意属性名称http.method,http.url,我在以上示例中使用了该属性,因为在open-telemetry规范中已经标准化了某些常用的属性名称,标准化常用属性名称可以在Jaeger等APM中很好的展示它们,属性名称已分类为几个不同的类别,你可以花点时间看一下:
- General: 可用于描述不同种类的操作的常规语义属性
- HTTP: 客户端和服务器的Http调用
- Database: SQL 和 NoSql的调用
- RPC/RMI: 远程调用,比如gRPC等
- Messaging: 用于与消息传递系统(队列,发布/订阅等)
- Exceptions: 用于记录与Span关联的异常的属性
Exporting 导出
有很多用于导出使用OpenTelemetry收集的数据的插件,我将在我的下一篇博客文章中讨论有关在ASP.NET Core中使用Open Telemetry的信息, 可以很方便的处理这些数据,您可以轻松地订阅然后消费OpenTelemetry数据,如下所示:
using var subscriber = DiagnosticListener.AllListeners.Subscribe(
listener =>
{
Console.WriteLine($"Listener name {listener.Name}");
listener.Subscribe(kvp => Console.WriteLine($"Received event {kvp.Key}:{kvp.Value}"));
});
跨进程的追踪
为什么这些程序会形成调用链,它们是不同的进程,这个怎么实现的呢?
这就是W3C跟踪上下文
标准,它定义了一系列HTTP Header,这些Header将有关当前正在记录的任何跟踪的信息从一个进程传递到另一个进程,它通过Http的Header来传递信息,规范中定义了两个HTTP Header:
traceparent-包含version,trace-id,parent-id和trace-flags
- version - 在open-telemetry规范中,它始终是00
- trace-id - 跟踪的唯一标识符。
- parent-id -作为当前 patent span 的唯一标识符。
- trace-flags -当前跟踪的一组标志,用于确定是否正在采样当前跟踪以及跟踪级别。
tracestate -由一组名称/值对表示的特定于供应商的数据。
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
tracestate: asp=00f067aa0ba902b7,redis=t61rcWkgMzE
Baggage
与Attributes类似,Baggage是我们可以将数据作为键值对添加到跟踪的另一种方式,不同之处在于,Baggage使用W3C规范中baggage定义的HTTP Header跨进程边界传递,但是Attributes的值数据只在当前Span中可用
baggage: userId=alice,serverNode=DF:28,isProduction=false
使用的话,也有些相同之处:
using (var activity = activitySource.StartActivity("ActivityName")
{
await LongRunningOperation().ConfigureAwait(false);
}
public async Task LongRunningOperationAsync()
{
await Task.Delay(1000).ConfigureAwait(false);
// Log an attribute containing arbitrary data.
Activity.Current?.AddBaggage("http.method", "GET");
}
它的用途在于,比如说我需要传递一个订单ID,我就可以放到 Baggage 数据中,它在整个请求链路中都可以访问。
总结
.NET团队对OpenTelemetry非常重视,你可以看到Activity类型在.NET 5 中的增强,并且默认 HttpClient 调用时,它会自动传输W3C跟踪上下文HTTP Header, 基于ILogger的统一日志,也可以很好的收集和OpenTelemetry兼容的日志。
原文作者: Rehan Saeed
原文链接: https://rehansaeed.com/deep-dive-into-open-telemetry-for-net/
最后
欢迎扫码关注我们的公众号 【全球技术精选】,专注国外优秀博客的翻译和开源项目分享,也可以添加QQ群 897216102
深入研究.NET 5的开放式遥测的更多相关文章
- 当 .NET 5 遇上OpenTelemetry,会碰撞出怎样的火花?
OpenTelemetry 介绍 我在之前的几篇文章都介绍了 OpenTelemetry, 你可以在这里找到 OpenTelemetry - 云原生下可观测性的新标准 深入研究 .NET 5 的开放式 ...
- 微软开源rDSN分布式系统开发框架
摘要:微软亚洲研究院系统组开发的分布式系统开发框架——Robust Distributed System Nucleus(rDSN)正式在GitHub平台开源.据悉,rDSN是一个旨在为广大分布式系统 ...
- 关于开放式CNC系统实时软件控制系统的一些简单分析
随笔: 黄杰U201310771 首先,我们一起了解或复习两个概念:开放式CNC和开放式CNC体系结构.按照工EEE规定:一个开放式的系统必须具备不同应用程序能很好地运行于不同供应商提供的不同平台之上 ...
- 基于Android 平台简易即时通讯的研究与设计[转]
摘要:论文简单介绍Android 平台的特性,主要阐述了基于Android 平台简易即时通讯(IM)的作用和功能以及实现方法.(复杂的通讯如引入视频音频等可以考虑AnyChat SDK~)关键词:An ...
- 基于.NET平台的分布式应用程序的研究
摘 要:.NET框架是Microsoft用于生成分布式Web应用程序和Web服务的下一代平台.概述了用于生成分布式应用程序的.NET框架的基本原理.重点讲述了.NET框架的基础:公共语言运行时(CLR ...
- GNU Autotools的研究(转)
最近对Linux下软件项目的构建过程研究了一番.Linux下的软件项目通常用Autotools工具集和make工具来构建,我们通常使用./configure.make.make install这样的命 ...
- Azure IoT 技术研究系列3-设备到云、云到设备通信
上篇博文中我们将模拟设备注册到Azure IoT Hub中:我们得到了设备的唯一标识. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub 本文中我们继续深入研究,设备到云.云到 ...
- Azure IoT 技术研究系列5-Azure IoT Hub与Event Hub比较
上篇博文中,我们介绍了Azure IoT Hub的使用配额和缩放级别: Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别 本文中,我们比较一下Azure IoT Hub和 ...
- Azure Event Bus 技术研究系列1-Event Hub入门篇
前两个系列研究了Azure IoT Hub和Azure Messaging.最近准备继续研究Azure Event Bus,即Azure的事件中心.首先, Azure Event Hub的官方介绍: ...
随机推荐
- VMware提示Device/Credential Guard不兼容
问题环境 win10系统版本 win10 2004企业版 vmware 版本 vmware 15 pro 问题 虚拟机开启时候弹窗提示:"VMware与Device/Credential G ...
- DRF类视图让你的代码DRY起来
刚开始写views.py模块的代码,一般都是用def定义的函数视图,不过DRF更推荐使用class定义的类视图,这能让我们的代码更符合DRY(Don't Repeat Yourself)设计原则: 使 ...
- Spring中BeanFactory与FactoryBean到底有什么区别?
一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean().containsBean()等管理Bea ...
- php学习之sqlite查询语句之多条件查询
一.PHP+Mysql多条件-多值查询示例代码: index.html代码:<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitio ...
- 【进程/作业】篇章一:Linux进程及其管理(进程的管理基础)
概述:监控系统各方面的性能,保障各类服务的有序运行,是运维工作的重要组成部分,本篇就介绍一次常用的系统监控命令和相关的参数说明 具体包含以下几部分: 1.进程的管理基础 ,主要是讲一下概念性的东西 2 ...
- 手把手教你搭饥荒专用服务器(五)—MOD自动下载安装(Windows+Linux)
想了解更详细内容,请点击原文地址:https://wuter.cn/1985.html/ 饥荒专用服务器的mod设置总共有两种方法. 方法一 在本地游戏中更新mod,然后把mod上传到服务器,但是这种 ...
- CentOS7下常用安装软件服务rpm方式的介绍
简介:介绍rpm软件包的管理 rpm安装:安装别人编译好的软件包,rpm即Redhat Package Manager,是Redhat的软件包管理方式 rpm安装优点: 软件已经编译打包,所以传输 ...
- .netcore 微服务快速开发框架 Anno&Viper -分布式锁是个什么鬼
1.什么是锁 锁是为了解决多线程或者多进程资源竞争的问题. 同一进程的多个线程资源竞争可以用lock解决. lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区. 如果其他线 ...
- tcp上传学习二--文本文件上传
//暮雪超霸.加油!!!package tcp文本上传; import java.io.BufferedReader; import java.io.FileReader; import java.i ...
- springboot 启动jar正确方式
首先需要pom.xml配置一个插件: IDEA 在右侧执行顶上m图片按钮 在command Line 中执行clean package命令 执行打包注意 打完jar包后最好解压jar查看一下META- ...