LCOV - code coverage report
Current view: top level - src/trace/sampling - trace_id_ratio_sampler.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 16 16
Test Date: 2025-11-15 13:23:01 Functions: - 0 0

            Line data    Source code
       1              : // Licensed under the Apache License, Version 2.0
       2              : // Copyright 2025, Michael Bushe, All rights reserved.
       3              : 
       4              : import 'dart:math' as math;
       5              : 
       6              : import '../../../dartastic_opentelemetry.dart';
       7              : 
       8              : /// A sampler that samples traces based on a probability defined by the ratio of
       9              : /// traces that should be sampled. The ratio must be in the range [0.0, 1.0].
      10              : ///
      11              : /// Uses the lowest 8 bytes of the trace ID to make a sampling decision.
      12              : class TraceIdRatioSampler implements Sampler {
      13              :   /// The sampling ratio, a value between 0.0 and 1.0 that determines
      14              :   /// the probability that a trace will be sampled.
      15              :   final double ratio;
      16              : 
      17            2 :   @override
      18            4 :   String get description => 'TraceIdRatioSampler{$ratio}';
      19              : 
      20              :   /// Creates a TraceIdRatioSampler with the given ratio.
      21              :   /// [ratio] must be in the range [0.0, 1.0].
      22            3 :   TraceIdRatioSampler(this.ratio) {
      23           12 :     if (ratio < 0.0 || ratio > 1.0) {
      24            1 :       throw ArgumentError('ratio must be in range [0.0, 1.0]');
      25              :     }
      26              :   }
      27              : 
      28              :   /// Converts a trace ID to a value between 0.0 and 1.0 for sampling decisions.
      29              :   /// Uses the lowest 8 bytes (16 hex characters) of the trace ID as per the specification.
      30              :   ///
      31              :   /// @param traceId The trace ID as a hex string
      32              :   /// @return A value between 0.0 and 1.0 based on the trace ID
      33            3 :   double _traceIdToValue(String traceId) {
      34              :     // Get the last 16 hex chars (8 bytes) of trace ID
      35           12 :     final lastBytes = traceId.substring(math.max(0, traceId.length - 16));
      36              : 
      37              :     // Parse hex string to integer with BigInt to avoid precision issues
      38            3 :     final value = BigInt.parse(lastBytes, radix: 16);
      39              : 
      40              :     // Maximum possible value for 8 bytes (64 bits) is 2^64 - 1
      41            3 :     final maxValue = BigInt.parse('ffffffffffffffff', radix: 16);
      42              : 
      43              :     // Convert to a double between 0.0 and 1.0
      44            9 :     return value.toDouble() / maxValue.toDouble();
      45              :   }
      46              : 
      47            3 :   @override
      48              :   SamplingResult shouldSample({
      49              :     required Context parentContext,
      50              :     required String traceId,
      51              :     required String name,
      52              :     required SpanKind spanKind,
      53              :     required Attributes? attributes,
      54              :     required List<SpanLink>? links,
      55              :   }) {
      56              :     // If ratio is 0, never sample
      57            6 :     if (ratio == 0.0) {
      58              :       return const SamplingResult(
      59              :         decision: SamplingDecision.drop,
      60              :         source: SamplingDecisionSource.tracerConfig,
      61              :       );
      62              :     }
      63              : 
      64              :     // If ratio is 1, always sample
      65            6 :     if (ratio == 1.0) {
      66              :       return const SamplingResult(
      67              :         decision: SamplingDecision.recordAndSample,
      68              :         source: SamplingDecisionSource.tracerConfig,
      69              :       );
      70              :     }
      71              : 
      72              :     // Convert trace ID to a value between 0.0 and 1.0
      73            3 :     final value = _traceIdToValue(traceId);
      74              : 
      75              :     // If the value is less than our ratio, we should sample
      76            6 :     final shouldSample = value < ratio;
      77              : 
      78            3 :     return SamplingResult(
      79              :       decision: shouldSample
      80              :           ? SamplingDecision.recordAndSample
      81              :           : SamplingDecision.drop,
      82              :       source: SamplingDecisionSource.tracerConfig,
      83              :     );
      84              :   }
      85              : }
        

Generated by: LCOV version 2.0-1