Recolher um rastreio distribuído
Este artigo aplica-se a: ✔️ .NET Core 2.1 e versões posteriores ✔️ .NET Framework 4.5 e versões posteriores
O código instrumentado pode criar Activity objetos como parte de um rastreio distribuído, mas as informações nestes objetos têm de ser recolhidas no armazenamento centralizado para que todo o rastreio possa ser revisto mais tarde. Neste tutorial, irá recolher a telemetria de rastreio distribuído de diferentes formas para que esteja disponível para diagnosticar problemas da aplicação quando necessário. Veja o tutorial de instrumentação se precisar de adicionar uma nova instrumentação.
Recolher rastreios com o OpenTelemetry
O OpenTelemetry é um projeto open source neutro para fornecedores suportado pela Cloud Native Computing Foundation que tem como objetivo uniformizar a geração e recolha de telemetria para software nativo da cloud. Nestes exemplos, irá recolher e apresentar informações de rastreio distribuído na consola do . Para saber como configurar o OpenTelemetry para enviar informações para outro local, consulte o Guia de introdução ao OpenTelemetry.
ASP.NET exemplo
Pré-requisitos
- SDK .NET Core 7.0 ou uma versão posterior
Criar uma aplicação de exemplo
Em primeiro lugar, crie um novo ASP.NET aplicação Web para utilizar como a aplicação de demonstração.
dotnet new webapp
Esta aplicação apresenta uma página Web, mas ainda não são recolhidas informações de rastreio distribuídas se navegarmos na página Web.
Configurar coleção
Para utilizar o OpenTelemetry, tem de adicionar referências a vários pacotes NuGet.
dotnet add package OpenTelemetry --version 1.4.0-rc1
dotnet add package OpenTelemetry.Exporter.Console --version 1.4.0-rc1
dotnet add package OpenTelemetry.Extensions.Hosting --version 1.4.0-rc1
dotnet add package OpenTelemetry.Instrumentation.AspNetCore --version 1.0.0-rc9.10
Nota
No momento da escrita, a compilação 1.4.0 Release Candidate 1 era a versão mais recente do OpenTelemetry disponível. Assim que estiver disponível uma versão final, utilize-a.
Em seguida, modifique o código fonte em Program.cs para que tenha o seguinte aspeto:
using OpenTelemetry;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddOpenTelemetry()
.WithTracing(builder =>
{
builder.AddAspNetCoreInstrumentation();
builder.AddConsoleExporter();
}).StartWithHost();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Execute a aplicação e utilize um browser para navegar para a página Web que está a ser alojada. Agora que ativou o rastreio distribuído do OpenTelemetry, deverá ver informações sobre os pedidos Web do browser impressos na consola do :
Activity.TraceId: 9c4519ce65a667280daedb3808d376f0
Activity.SpanId: 727c6a8a6cff664f
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName: /
Activity.Kind: Server
Activity.StartTime: 2023-01-08T01:56:05.4529879Z
Activity.Duration: 00:00:00.1048255
Activity.Tags:
net.host.name: localhost
net.host.port: 5163
http.method: GET
http.scheme: http
http.target: /
http.url: http://localhost:5163/
http.flavor: 1.1
http.user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76
http.status_code: 200
Resource associated with Activity:
service.name: unknown_service:demo
Toda a configuração do OpenTelemetry ocorre nas novas linhas de origem que começam com builder.Services.AddOpenTelemetry()
. Utilizou .WithTracing(...)
para ativar o rastreio distribuído. AddAspNetCoreInstrumentation()
ativou o OpenTelemetry para recolher todas as Atividades de rastreio distribuído produzidas pelo servidor Web ASP.NET Core e AddConsoleExporter()
instrui o OpenTelemetry a enviar essas informações para a consola do . Para uma aplicação menos trivial, pode adicionar mais bibliotecas de instrumentação para recolher também o rastreio para consultas de base de dados ou pedidos HTTP de saída. Também substituiria o exportador de consolas por um exportador para o Zipken, Zipken ou outro serviço de monitorização que tenha optado por utilizar.
Exemplo de aplicação de consola
Pré-requisitos
- SDK .NET Core 2.1 ou uma versão posterior
Criar uma aplicação de exemplo
Para que qualquer telemetria de rastreio distribuído possa ser recolhida, tem de a produzir. Muitas vezes, esta instrumentação está em bibliotecas, mas, para simplificar, irá criar uma pequena aplicação que tem algum exemplo de instrumentação com StartActivity. Neste momento, não ocorreu nenhuma coleção e StartActivity() não tem efeito colaterativo e devolve nulo. Veja o tutorial de instrumentação para obter mais detalhes.
dotnet new console
As aplicações que visam o .NET 5 e posterior já têm as APIs de rastreio distribuídas necessárias incluídas. Para aplicações destinadas a versões mais antigas do .NET, adicione a versão 5 ou superior do pacote NuGet System.Diagnostics.DiagnosticSource .
dotnet add package System.Diagnostics.DiagnosticSource
Substitua o conteúdo do Program.cs gerado por esta origem de exemplo:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Sample.DistributedTracing
{
class Program
{
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
static async Task Main(string[] args)
{
await DoSomeWork();
Console.WriteLine("Example work done");
}
static async Task DoSomeWork()
{
using (Activity a = s_source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
}
}
static async Task StepOne()
{
using (Activity a = s_source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}
static async Task StepTwo()
{
using (Activity a = s_source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
}
}
}
A execução da aplicação ainda não recolhe quaisquer dados de rastreio:
> dotnet run
Example work done
Configurar coleção
Adicione o pacote NuGet OpenTelemetry.Exporter.Console .
dotnet add package OpenTelemetry.Exporter.Console
Atualize Program.cs com diretivas de OpenTelemetry using
adicionais:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
Atualize Main()
para criar o OpenTelemetry TracerProvider:
public static async Task Main()
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample"))
.AddSource("Sample.DistributedTracing")
.AddConsoleExporter()
.Build();
await DoSomeWork();
Console.WriteLine("Example work done");
}
Agora, a aplicação recolhe informações de rastreio distribuído e apresenta-as na consola do :
> dotnet run
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-6081a9b8041cd840-01
Activity.ParentId: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: StepOne
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:46.8649754Z
Activity.Duration: 00:00:00.5069226
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-d2b283db91cf774c-01
Activity.ParentId: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: StepTwo
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:47.3838737Z
Activity.Duration: 00:00:01.0142278
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Activity.Id: 00-7759221f2c5599489d455b84fa0f90f4-9a52f72c08a9d447-01
Activity.DisplayName: SomeWork
Activity.Kind: Internal
Activity.StartTime: 2021-03-18T10:46:46.8634510Z
Activity.Duration: 00:00:01.5402045
Resource associated with Activity:
service.name: MySample
service.instance.id: 909a4624-3b2e-40e4-a86b-4a2c8003219e
Example work done
Origens
No código de exemplo, invocou AddSource("Sample.DistributedTracing")
para que o OpenTelemetry capturasse as Atividades produzidas pelo ActivitySource que já estava presente no código:
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
A telemetria de qualquer ActivitySource pode ser capturada ao chamar AddSource()
com o nome da origem.
Exportadores
O exportador da consola é útil para exemplos rápidos ou desenvolvimento local, mas numa implementação de produção provavelmente irá querer enviar rastreios para um arquivo centralizado. O OpenTelemetry suporta vários destinos com diferentes exportadores. Para obter mais informações sobre como configurar o OpenTelemetry, veja o Guia de introdução ao OpenTelemetry.
Recolher rastreios com o Application Insights
A telemetria de rastreio distribuído é capturada automaticamente após configurar o SDK do Application Insights para ASP.NET ou ASP.NET Core aplicações ou ao ativar a instrumentação sem código.
Para obter mais informações, veja a documentação de rastreio distribuído do Application Insights.
Nota
Atualmente, o Application Insights só suporta a recolha de instrumentação de Atividade conhecida específica e ignora as novas Atividades adicionadas pelo utilizador. O Application Insights oferece TrackDependency como uma API específica do fornecedor para adicionar informações de rastreio distribuídas personalizadas.
Recolher rastreios com lógica personalizada
Os programadores são livres de criar a sua própria lógica de recolha personalizada para dados de rastreio de atividade. Este exemplo recolhe a telemetria com a System.Diagnostics.ActivityListener API fornecida pelo .NET e imprime-a na consola do .
Pré-requisitos
- SDK .NET Core 2.1 ou uma versão posterior
Criar uma aplicação de exemplo
Em primeiro lugar, vai criar uma aplicação de exemplo que tem alguma instrumentação de rastreio distribuído, mas que não estão a ser recolhidos dados de rastreio.
dotnet new console
As aplicações que visam o .NET 5 e posterior já têm as APIs de rastreio distribuídas necessárias incluídas. Para aplicações destinadas a versões mais antigas do .NET, adicione a versão 5 ou superior do pacote NuGet System.Diagnostics.DiagnosticSource .
dotnet add package System.Diagnostics.DiagnosticSource
Substitua o conteúdo do Program.cs gerado por esta origem de exemplo:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Sample.DistributedTracing
{
class Program
{
static ActivitySource s_source = new ActivitySource("Sample.DistributedTracing");
static async Task Main(string[] args)
{
await DoSomeWork();
Console.WriteLine("Example work done");
}
static async Task DoSomeWork()
{
using (Activity a = s_source.StartActivity("SomeWork"))
{
await StepOne();
await StepTwo();
}
}
static async Task StepOne()
{
using (Activity a = s_source.StartActivity("StepOne"))
{
await Task.Delay(500);
}
}
static async Task StepTwo()
{
using (Activity a = s_source.StartActivity("StepTwo"))
{
await Task.Delay(1000);
}
}
}
}
A execução da aplicação ainda não recolhe quaisquer dados de rastreio:
> dotnet run
Example work done
Adicionar código para recolher os rastreios
Atualize Main() com este código:
static async Task Main(string[] args)
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;
Console.WriteLine(" {0,-15} {1,-60} {2,-15}", "OperationName", "Id", "Duration");
ActivitySource.AddActivityListener(new ActivityListener()
{
ShouldListenTo = (source) => true,
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllDataAndRecorded,
ActivityStarted = activity => Console.WriteLine("Started: {0,-15} {1,-60}", activity.OperationName, activity.Id),
ActivityStopped = activity => Console.WriteLine("Stopped: {0,-15} {1,-60} {2,-15}", activity.OperationName, activity.Id, activity.Duration)
});
await DoSomeWork();
Console.WriteLine("Example work done");
}
O resultado inclui agora o registo:
> dotnet run
OperationName Id Duration
Started: SomeWork 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-c447fb302059784f-01
Started: StepOne 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-a7c77a4e9a02dc4a-01
Stopped: StepOne 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-a7c77a4e9a02dc4a-01 00:00:00.5093849
Started: StepTwo 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-9210ad536cae9e4e-01
Stopped: StepTwo 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-9210ad536cae9e4e-01 00:00:01.0111847
Stopped: SomeWork 00-bdb5faffc2fc1548b6ba49a31c4a0ae0-c447fb302059784f-01 00:00:01.5236391
Example work done
Definir DefaultIdFormat e ForceDefaultIdFormat é opcional, mas ajuda a garantir que o exemplo produz resultados semelhantes em diferentes versões de runtime do .NET. O .NET 5 utiliza o formato W3C TraceContext ID por predefinição, mas as versões anteriores do .NET são predefinidas para utilizar Hierarchical o formato de ID. Para obter mais informações, veja IDs de Atividade.
System.Diagnostics.ActivityListener é utilizado para receber chamadas de retorno durante a duração de uma Atividade.
- ShouldListenTo - Cada Atividade está associada a uma ActivitySource, que atua como o respetivo espaço de nomes e produtor. Esta chamada de retorno é invocada uma vez para cada ActivitySource no processo. Devolver verdadeiro se estiver interessado em efetuar a amostragem ou ser notificado sobre eventos de início/paragem para Atividades produzidas por esta origem.
- Sample - Por predefinição StartActivity , não cria um objeto Atividade, a menos que algum ActivityListener indique que deve ser amostrado. A devolução AllDataAndRecorded indica que a Atividade deve ser criada, IsAllDataRequested deve ser definida como verdadeira e ActivityTraceFlags terá o Recorded sinalizador definido. IsAllDataRequested pode ser observado pelo código instrumentado como uma sugestão de que um serviço de escuta quer garantir que as informações da Atividade auxiliar, como Etiquetas e Eventos, são preenchidas. O sinalizador Registado está codificado no ID W3C TraceContext e é uma sugestão para outros processos envolvidos no rastreio distribuído que este rastreio deve ser amostrado.
- ActivityStarted e ActivityStopped são chamados quando uma Atividade é iniciada e parada, respetivamente. Estas chamadas de retorno proporcionam uma oportunidade para registar informações relevantes sobre a Atividade ou potencialmente modificá-la. Quando uma Atividade acaba de começar, a maior parte dos dados ainda podem estar incompletos e serão preenchidos antes de a Atividade parar.
Assim que um ActivityListener tiver sido criado e as chamadas de retorno forem preenchidas, a chamada ActivitySource.AddActivityListener(ActivityListener) inicia a invocação das chamadas de retorno. Chame ActivityListener.Dispose() para parar o fluxo de chamadas de retorno. Tenha em atenção que, no código com vários threads, as notificações de chamada de retorno em curso podem ser recebidas enquanto Dispose()
está em execução ou mesmo pouco depois de ter sido devolvida.