generateAtatusAttributes function
Map<String, Object?>
generateAtatusAttributes(
- TracingContext? context,
- double samplingRate, {
- String spanKind = 'client',
Builds the _atatus.* attributes that make a RUM resource a span.
spanKind defaults to client, the kind of every outgoing request. The
root span of a manual trace wraps those requests rather than being one, so
it passes internal.
Implementation
Map<String, Object?> generateAtatusAttributes(
TracingContext? context,
double samplingRate, {
String spanKind = 'client',
}) {
var attributes = <String, Object?>{};
if (context != null) {
// ATCHG - Change package name from DDRumPlatformAttributeKey to AtatusRumPlatformAttributeKey
attributes[AtatusRumPlatformAttributeKey.rulePsr] = samplingRate / 100.0;
if (context.sampled) {
// Ids are reported in the same representation the `traceparent` header
// carries: 32 hex chars for the trace, 16 for the span.
//
// This deliberately differs from the Atatus Android agent, which reports
// `_atatus.span_id` as unsigned decimal (`DDSpanId.toString()`). Android
// can afford that because it *also* uploads a separate span payload whose
// ids are hex, so the backend has both forms to reconcile. The Flutter
// agent uploads no span payload - this RUM resource IS the client span -
// so its id has to string-match the id the receiving service records as
// its parent, which comes from `traceparent` and is hex. Reporting
// decimal here leaves the server span with a parent it cannot find, and
// the client span goes missing from the waterfall.
final traceIdStr =
context.traceId.asString(TracingIdRepresentation.hex32Chars);
final spanIdStr =
context.spanId.asString(TracingIdRepresentation.hex16Chars);
// ATCHG - Change package name from DDRumPlatformAttributeKey to AtatusRumPlatformAttributeKey
attributes[AtatusRumPlatformAttributeKey.traceID] = traceIdStr;
// ATCHG - Change package name from DDRumPlatformAttributeKey to AtatusRumPlatformAttributeKey
attributes[AtatusRumPlatformAttributeKey.spanID] = spanIdStr;
if (kDebugMode) {
// print('⚡ [Atatus Agent] Generated Trace ID: $traceIdStr, Span ID: $spanIdStr');
}
// Every request the agent reports is an outgoing call, so it is a
// `client` span - including a request that has no parent. The matching
// `server` span for the same request is produced by the backend's own
// APM agent. The Atatus Android agent tags this unconditionally too; see
// TracingInterceptor.kt
// (`span.setTag(Tags.KEY_SPAN_KIND, Tags.VALUE_SPAN_KIND_CLIENT)`).
attributes[AtatusRumPlatformAttributeKey.spanKind] = spanKind;
// A zero parent means "no parent" - it is what `TracingId.fromString`
// yields for an empty or unparseable id, e.g. from a caller-supplied
// `AtatusDioParentSpanResolver`. Reporting it would make a root span look
// like the child of a span that does not exist, so the key is omitted
// instead, which is how a root is identified.
if (context.parentSpanId != null &&
context.parentSpanId!.value != BigInt.zero) {
final parentSpanIdStr =
context.parentSpanId!.asString(TracingIdRepresentation.hex16Chars);
attributes[AtatusRumPlatformAttributeKey.parentSpanID] =
parentSpanIdStr;
if (kDebugMode) {
// print('⚡ [Atatus Agent] Parent Span ID: $parentSpanIdStr');
}
}
}
}
return attributes;
}