本文是一系列示例之一,用于说明 OpenTelemetry 的 .NET 可观测性。
除了作为Aspire的标准部分外,Aspire仪表板也可以作为独立的 Docker 容器使用,该容器提供 OTLP 终结点,能够接收发送的遥测数据。 仪表板直观显示日志、指标和跟踪。 以这种方式使用仪表板无需依赖于Aspire。仪表板可以可视化任何通过 OTLP 发送遥测数据的应用程序的遥测。 它同样适用于用 Java、GoLang 或 Python 编写的应用程序,前提是他们可以将其遥测数据发送到 OTLP 终结点。
与使用 Aspire 等开源解决方案相比,使用仪表板的配置和设置步骤更少。 但与这些工具不同, Aspire 仪表板旨在用作开发人员可视化工具,而不是用于生产监视。
1.创建项目
使用 Visual Studio 中的 ASP.NET Core 空模板或以下 .NET CLI 命令创建简单的 Web API 项目:
dotnet new web
2. 添加指标和活动定义
下面的代码为调用 API 的次数定义了新的指标 (greetings.count) 和新活动源 (Otel.Example)。
// Custom metrics for the application
var greeterMeter = new Meter("OTel.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");
// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OTel.Example");
3. 创建 API 端点
在 builder.Build(); 和 app.Run() 之间插入以下代码
app.MapGet("/", SendGreeting);
在文件底部插入以下函数:
async Task<string> SendGreeting(ILogger<Program> logger)
{
// Create a new Activity scoped to the method
using var activity = greeterActivitySource.StartActivity("GreeterActivity");
// Log a message
logger.LogInformation("Sending greeting");
// Increment the custom counter
countGreetings.Add(1);
// Add a tag to the Activity
activity?.SetTag("greeting", "Hello World!");
return "Hello World!";
}
注意
终结点定义不使用特定于 OpenTelemetry 的任何内容。 它使用 .NET API 实现可观测性。
4. 引用 OpenTelemetry 包
使用 NuGet 包管理器或命令行添加以下 NuGet 包:
<ItemGroup>
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
</ItemGroup>
注意
使用最新版本,因为 OTel API 不断发展。
5. 使用正确的提供程序配置 OpenTelemetry
在 builder.Build(); 之前插入以下代码:
// Setup logging to be exported via OpenTelemetry
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
var otel = builder.Services.AddOpenTelemetry();
// Add Metrics for ASP.NET Core and our custom metrics and export via OTLP
otel.WithMetrics(metrics =>
{
// Metrics provider from OpenTelemetry
metrics.AddAspNetCoreInstrumentation();
//Our custom metrics
metrics.AddMeter(greeterMeter.Name);
// Metrics provides by ASP.NET Core in .NET 8
metrics.AddMeter("Microsoft.AspNetCore.Hosting");
metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel");
});
// Add Tracing for ASP.NET Core and our custom ActivitySource and export via OTLP
otel.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation();
tracing.AddHttpClientInstrumentation();
tracing.AddSource(greeterActivitySource.Name);
});
// Export OpenTelemetry data via OTLP, using env vars for the configuration
var OtlpEndpoint = builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"];
if (OtlpEndpoint != null)
{
otel.UseOtlpExporter();
}
此代码使用不同的遥测源设置 OpenTelemetry:
- 它将 OTel 提供程序添加到 ILogger 以收集日志记录。
- 它为 ASP.NET 和自定义计量设置指标、注册检测提供程序和计量。
- 它设置跟踪、注册检测提供程序和自定义 ActivitySource。
然后,它将使用环境变量注册 OTLP 导出程序进行配置。
6. 配置 OTLP 环境变量
OTLP 导出程序可以通过代码中的 API 进行配置,但通过环境变量对其进行配置更为常见。 将以下内容添加到 AppSettings.Development.json
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
"OTEL_SERVICE_NAME": "OTLP-Example"
可以为 .NET OTLP 导出程序添加其他环境变量或常见的 OTel 变量(例如 OTEL_RESOURCE_ATTRIBUTES),以定义资源属性。
注意
一个常见的陷阱是混淆 AppSettings.json 和 AppSettings.Development.json。 如果存在后者,则会在 Visual Studio 中的 F5 中使用,并且将忽略 AppSettings.json 中的任何设置。
7. 启动 Aspire 仪表板容器
使用 docker 下载并运行仪表盘容器。
docker run --rm -it `
-p 18888:18888 `
-p 4317:18889 `
--name aspire-dashboard `
mcr.microsoft.com/dotnet/aspire-dashboard:latest
仪表板中显示的数据可能是敏感数据。 默认情况下,仪表板受到身份验证保护,需要令牌登录。 运行容器时,令牌会显示在生成的输出中。
复制显示的 URL,并替换为0.0.0.0localhost(例如http://localhost:18888/login?t=123456780abcdef123456780)并在浏览器中打开该 URL。 或者,您也可以在登录对话框显示后将密钥粘贴在 /login?t= 之后。 每次启动容器时,令牌都会更改。
8. 运行项目
运行项目,然后使用浏览器或 curl 访问 API。
curl -k http://localhost:7275
每次请求页面时,它都会增加已发出问候语的数量。
8.1 日志输出
代码中的日志记录语句使用 ILogger 输出。 默认情况下,将启用控制台提供程序,以便将输出定向到控制台。
有几种方式来从 .NET 导出日志:
-
stdout和stderr输出由容器系统(如 Kubernetes)重定向到日志文件。 - 使用与 ILogger 集成的日志记录库。 这些库包括 Serilog 和 NLog。
- 为 OTel 使用日志记录提供程序(如 OTLP)。 步骤 5 中的代码日志部分添加了 OTel 提供者。
日志以结构化日志的形式显示在仪表板中 - 日志消息中设置的任何属性都将提取为日志记录中的字段。
8.2 查看指标
Aspire 仪表板显示每个资源的指标(资源是 OTel 谈论遥测源 [例如进程] 的方式)。 选择资源后,仪表板会枚举资源发送到其 OTLP 终结点的每个指标。 指标列表是动态的,并在收到新指标时更新。
指标的视图取决于正在使用的指标类型:
- 计数器直接显示。
- 跟踪每个请求的值(例如每个请求发送的时间范围或字节)的直方图将收集到一系列存储桶中。 仪表板绘制 P50、P90 和 P99 百分位数。 直方图结果可以包括示例,这些示例是单个数据点,以及该请求的 trace/spanId。 这些点在图形上显示为点。 选择一项会导航到相应的跟踪,以便查看导致该值的情况。 这可用于诊断离群值。
- 指标可以包含维度,这些维度是与单个值关联的键/值对。 这些值按维度聚合。 使用视图中的下拉列表,可以筛选结果以查看特定维度,例如仅
GET请求或 ASP.NET 中特定 URL 路由的请求。
8.3 查看跟踪
追踪视图显示追踪列表。 每个跟踪记录是一组共享同一 traceId 的活动。 使用表示工作单位的范围跟踪工作。 处理 ASP.NET 请求会创建一个区间。 发出 HttpClient 请求是一个范围。 通过跟踪区段的上级,可以对区段的层次结构进行可视化。 通过从每个资源(进程)收集范围,可以跟踪一系列服务中发生的工作。 HTTP 请求具有一个标头,用于将 traceId 和父 spanId 传递给下一个服务。 每个资源都需要收集遥测数据并将其发送到同一收集器。 然后,它将聚合并呈现范围的层次结构。
仪表板显示包含摘要信息的跟踪列表。 每当看到具有新 traceId 的范围时,它们都会在表中获取一行。 单击查看会显示跟踪中的所有范围。
选择段会显示其详细信息,包括段上的任何属性,例如您在步骤 3 中设置的greeting标记。