我有一个 Razor Web 应用程序 (.NET 8) 客户端,我想获取执行指标和对其他 API 的调用。
我安装了以下 NuGet 软件包:
在Program.Main中我配置它
TracerProvider tracer = null;
try
{
...
app.MapRazorPages();
// Using ResourceBuilder.CreateDefault doesn't have any effect, nor does moving init to the top
tracer = Sdk.CreateTracerProviderBuilder()
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.SetResourceBuilder(ResourceBuilder.CreateEmpty())
.AddSource("test")
.AddConsoleExporter()
.Build();
app.Run();
}
finally
{
tracer?.Dispose();
}
我有一个服务,我需要调用一个我想要跟踪的 API。我现在使用静态
ActivitySource
,但目标是为我的应用程序创建一个(或几个)并重复使用(不是每个类一个)
class MyService : IDisposable
{
private static readonly ActivitySource _source1= new ActivitySource("test");
async Task<HttpResponseMessage> MyMethod()
{
using var activity1 = _source1.StartActivity("action");
var source2 = new ActivitySource("test");
using var activity2 = source2.StartActivity("action");
...
}
void Dispose()
{
_source1?.Dispose();
}
}
我看到了
_source1
没有任何侦听器并且 activity1
为 nullsource2
有一个监听器,并且 activity2
是一个有效的对象我试图根据最佳实践仅构造一个 ActivitySource,但它不起作用。我的设置做错了什么或遗漏了什么?
问题在于,执行
builder.Services.AddScoped<MyService>
会导致在页面第一次渲染时构建服务,并在渲染后调用dispose。当我单击按钮触发操作时,它会再次构造,但 ActivitySource 不会被重建。
我需要更好地理解
AddScoped
,但现在切换到 AddSingleton
适合我的目的。
关于您的解决方案的一些评论。
根据您的示例,看起来我们正在处理一个 ASP.NET Core 项目(由于
app.MapRazorPages()
的东西)。鉴于此,我强烈建议利用 OpenTelemetry.Extensions.Hosting
包,而不是手动处理 SDK 创建。
其次,最好不要使用
ResourceBuilder.CreateEmpty()
,而是使用 ResourceBuilder.CreateDefault()
,但同样,这也由托管扩展来处理,您不需要添加它。不过,我建议至少在 AddService()
上添加一些带有 ResourceBuilder
的服务信息。
第三,看来您需要先将
ActivitySource
放置到位,然后才能致电AddSource
,否则OTEL将无法找到您的活动来源。这解释了为什么您切换到单例有效(我假设您传入了一个预先创建的实例,这会触发静态字段被更新,从而可供 OTEL 拾取它)。
尝试这样的事情:
builder.Services.AddOpenTelemetry()
.ConfigureResource(c => c.AddService("YourServiceNameHere"))
.WithTracing(c => c
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("test")
.AddConsoleExporter();
...
app.MapRazorPages();
app.Run();
对于
ActivitySource
,Microsoft 在其主要文章中定义了一些最佳实践:
创建 ActivitySource 一次,将其存储在静态变量中,并根据需要使用该实例。每个库或库子组件都可以(并且通常应该)创建自己的源。
您已经在使用
static
字段来存储源代码,但它位于一个仅在流程稍后实例化的类中。相反,请考虑将 ActivitySource
初始化移动到应用程序本身的开头,然后将其传递(如果需要,您甚至可以使用 DI)。
要在 Web 应用程序中检测 OpenTelemetry HttpClient,请按照以下步骤操作:
安装必要的包:首先,您需要将 OpenTelemetry.Instrumentation.Http 包添加到您的项目中。该包提供了 HttpClient 和 HttpWebRequest 的工具。您可以使用 .NET CLI 并使用以下命令来添加它:
dotnet add package OpenTelemetry.Instrumentation.Http
此外,确保您安装了其他必要的 OpenTelemetry 软件包,例如导出器和您可能需要的任何其他工具 [2]。
在应用程序启动时启用 HTTP 检测:在应用程序的启动配置中,启用 HttpClient 检测。这可以通过将检测添加到 TracerProviderBuilder 或 MeterProviderBuilder 来完成,具体取决于您关注的是跟踪还是指标。对于跟踪,请使用 TracerProviderBuilder 上的
.AddHttpClientInstrumentation()
方法。对于指标,请使用 MeterProviderBuilder 上的 .AddHttpClientInstrumentation()
方法。这是痕迹的示例:
using OpenTelemetry;
using OpenTelemetry.Trace;
public class Program
{
public static void Main(string[] args)
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddHttpClientInstrumentation()
.AddConsoleExporter()
.Build();
}
}
对于指标:
using OpenTelemetry;
using OpenTelemetry.Metrics;
public class Program
{
public static void Main(string[] args)
{
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddHttpClientInstrumentation()
.AddConsoleExporter()
.Build();
}
}
这些示例还包括用于演示目的的 OpenTelemetry Console Exporter,您可以将其替换为您首选的导出器 [2]。
过滤 HttpClient 请求(可选):如果需要过滤检测的 HttpClient 请求,可以使用
FilterHttpRequestMessage
选项。这允许您指定应检测请求的条件。例如,仅检测 GET 请求:
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddHttpClientInstrumentation(options => options.FilterHttpRequestMessage = httpRequestMessage =>
{
return httpRequestMessage.Method.Equals(HttpMethod.Get);
})
.AddConsoleExporter()
.Build();
此选项对于减少从 HttpClient 请求收集的遥测数据量很有用 [2]。
高级配置:对于 .NET 8.0 及更高版本,HttpClient 库内置了对遵循 OpenTelemetry 语义约定的指标的支持。您可以使用
.AddHttpClientInstrumentation()
通过一行代码启用所有内置指标。要对指标进行更精细的控制,您可以使用 .AddMeter()
上的
MeterProviderBuilder
扩展