">
 

.NET 10 ActivitySamplingResult PropagationData: Why Recorded Turns False

Iniciado por joomlamz, Hoje at 18:25

Respostas: 1   |   Visualizações: 1

Tópico anterior - Tópico seguinte

0 Membros e 1 Visitante estão a ver este tópico.

Olá, caros colegas do **webmastersmz.com**! Como especialista em tecnologia, analisei recentemente um tópico bastante interessante e técnico da comunidade de desenvolvimento: **".NET 10 ActivitySamplingResult PropagationData: Why Recorded Turns False"**.

Este é um assunto crucial para quem trabalha com observabilidade, rastreio distribuído (*distributed tracing*) e telemetria no ecossistema .NET, especialmente agora com a evolução para o .NET 10.

Abaixo, destaco os pontos principais discutidos no tópico:

1. **O papel do `ActivitySamplingResult`:** No ecossistema de diagnóstico do .NET, o mecanismo de amostragem decide se uma atividade (`Activity`) deve ser recolhida e se os seus dados de contexto devem ser propagados para outros serviços a jusante (*downstream*).
2. **O enigma do `PropagationData`:** O cerne da questão abordada no tópico prende-se com o facto de a propriedade `Recorded` mudar inesperadamente para `false`. Isto acontece muitas vezes porque, mesmo que o coletor decida não gravar os dados localmente (por questões de otimização de desempenho ou limite de largura de banda de telemetria), a decisão de amostragem pode afetar a forma como os cabeçalhos de correlação (como o W3C Trace Context) são propagados.
3. **Impacto no Rastreio Distribuído:** Se o `Recorded` passa a falso de forma incorreta, perde-se a visibilidade do fluxo de requisições entre microsserviços, dificultando o *debugging* de aplicações complexas em produção. A discussão aprofunda as diretrizes que os desenvolvedores devem seguir para ajustar os *samplers* personalizados e garantir que a propagação de contexto funcione conforme o esperado sem sobrecarregar o sistema.

Este tipo de comportamento exige uma fineza técnica considerável na configuração do `DiagnosticListener` e das ferramentas de OpenTelemetry no .NET 10. Como é que vocês têm lidado com a telemetria e o rastreio nas vossas aplicações mais recentes? Já se depararam com este comportamento no `ActivitySamplingResult`? **Deixem as vossas opiniões e experiências aqui nos comentários do fórum webmastersmz.com para enriquecermos este debate!**

---

Para garantir que os vossos projetos e fóruns rodam sem falhas, convido-vos a conhecer as soluções de alojamento de alta performance da **AplicHost** em [https://aplichost.com](https://aplichost.com).

.NET 10 ActivitySamplingResult PropagationData: Why Recorded Turns False



Tópico: .NET 10 ActivitySamplingResult PropagationData: Why Recorded Turns False
Categoria: Tutoriais | Programação & Tecnologia
Idioma Principal: Português (Conteúdo de Tecnologia)

Descrição do Conteúdo / Informações:
-------------------------------------------------------------------------
.NET 10 changed a small tracing rule that can quietly invalidate a custom sampler. With .NET 10 ActivitySamplingResult PropagationData, a child activity no longer becomes Recorded just because its parent carries the recorded flag. The trace identity still flows, but the local sampling decision now wins.

I treat that decision as a contract worth testing. A collector is not required to reproduce it, and an exporter can actually hide the important part behind more configuration. A fixed ActivityContext, one ActivityListener, and a few assertions are enough.



Why .NET 10 ActivitySamplingResult PropagationData changed


ActivitySource.StartActivity only creates an activity when a registered listener asks for one. The listener's sampling result also says how much data the activity should collect.

The relevant choices are:


None: do not create the activity.


PropagationData: create it with propagation state, but do not request enrichment or recording.


AllData: request tags, links, and events without setting Recorded.


AllDataAndRecorded: request enrichment and set the recorded flag.

Before .NET 10, PropagationData had an exception to that table. If the parent was recorded, the child also became recorded. Microsoft changed this because the inherited flag did not match the sampling result or the OpenTelemetry contract. The .NET 10 compatibility note now states that a PropagationData child has both Recorded == false and IsAllDataRequested == false, even under a recorded parent.

That distinction matters in custom listeners. Recorded controls the W3C recorded bit propagated downstream. IsAllDataRequested tells instrumentation whether detailed data should be attached. They answer different questions, so forcing one does not automatically enable the other. The ActivitySamplingResult API documentation is a useful compact reference for those four choices.



Reproduce the Recorded flag in one process


I start with a listener whose decision is explicit and a remote parent whose IDs are fixed test data:

var decision = ActivitySamplingResult.PropagationData;
using var source = new ActivitySource("ActivityPropagationSampling", "1.0.0");
using var listener = new ActivityListener
{
ShouldListenTo = candidate => candidate.Name == source.Name,
Sample = (ref ActivityCreationOptions<ActivityContext> _) => decision
};

ActivitySource.AddActivityListener(listener);

var parent = new ActivityContext(
ActivityTraceId.CreateFromString("11111111111111111111111111111111"),
ActivitySpanId.CreateFromString("2222222222222222"),
ActivityTraceFlags.Recorded,
traceState: null,
isRemote: true);

using var child = source.StartActivity(
"receive-message",
ActivityKind.Consumer,
parent);

The important assertions are about the contract, not generated identifiers or wall-clock timing:

Debug.Assert(child is not null);
Debug.Assert(child.TraceId == parent.TraceId);
Debug.Assert(child.ParentSpanId == parent.SpanId);
Debug.Assert(child.Recorded is false);
Debug.Assert(child.IsAllDataRequested is false);

The child exists and continues the trace, which is exactly what PropagationData requests. It simply does not claim that this process chose to record or enrich it.

The complete sample on main turns these checks into a deterministic console verifier. It runs without credentials, network calls, model calls, an OpenTelemetry package, or a collector. The merged pull request also records the validation commands and results.

Run it with:

dotnet restore
dotnet format --verify-no-changes --no-restore
dotnet build -c Release --no-restore
dotnet run -c Release --no-build

The verifier ends with PASS: 10/10 checks. Five repeated runs produced byte-identical output in the sample validation, but I am not presenting that as a performance benchmark. It only proves that the fixture itself is stable.



Choose the sampling result deliberately


If I only need trace identity and baggage to cross a boundary, PropagationData is still the right answer. Changing it to AllDataAndRecorded merely to preserve pre-.NET 10 behavior can increase the amount of telemetry collected.

If the listener truly intends to record and enrich the activity, I return AllDataAndRecorded and test both flags. If I need the old recorded bit temporarily, Microsoft's documented compatibility measure is explicit:

child.ActivityTraceFlags |= ActivityTraceFlags.Recorded;

That line makes child.Recorded true and propagates the bit downstream. It does not make IsAllDataRequested true. Code that sets tags or events based on that property will still skip enrichment, so this is a narrow bridge rather than a replacement sampling policy.

I also keep the framework baseline visible. The sample was verified on the stable .NET 10.0.11 runtime included with SDK 10.0.303; Microsoft's 10.0.11 release notes list that supported SDK/runtime pairing.



Limits and when not to change anything


This behavior targets code that directly implements ActivityListener.Sample and returns PropagationData. Microsoft notes that the default OpenTelemetry .NET parent-based sampler is not affected. If that is your setup, do not add a flag override for a problem you do not have.

The sample also stops at the in-process contract. It does not prove exporter batching, collector sampling, backend retention, or billing behavior. Those belong in separate integration checks because they depend on the telemetry stack you deploy.

For custom samplers, though, this small test catches the exact upgrade boundary without external infrastructure. How are you regression-testing sampling decisions in your tracing code?

Happy coding!


Joomlamz
Consultoria em Informática
-------------------------------------------------------
Especialista em Sistemas Web & Manutenção de Servidores.
A desenvolver o novo AplPortal com suporte a PHP 8.
Precisa de ajuda profissional? Contacte-me.

Tags: