LCOV - code coverage report
Current view: top level - src/trace/sampling - parent_based_sampler.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 13 13
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 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
       5              : 
       6              : import 'always_off_sampler.dart';
       7              : import 'always_on_sampler.dart';
       8              : import 'sampler.dart';
       9              : 
      10              : /// A sampler that respects the parent span's sampling decision.
      11              : ///
      12              : /// This sampler implements a composite sampling strategy that bases its
      13              : /// decision on the parent span's sampling decision. If there is no parent
      14              : /// span, or if the parent is not valid, it uses a root sampler to make
      15              : /// the decision.
      16              : ///
      17              : /// This is particularly important for maintaining complete traces across
      18              : /// service boundaries, ensuring that a trace is either fully sampled or
      19              : /// not sampled at all across its entire path.
      20              : ///
      21              : /// More information:
      22              : /// https://opentelemetry.io/docs/specs/otel/trace/sdk/#parentbased
      23              : class ParentBasedSampler implements Sampler {
      24              :   final Sampler _root;
      25              :   final Sampler _remoteParentSampled;
      26              :   final Sampler _remoteParentNotSampled;
      27              :   final Sampler _localParentSampled;
      28              :   final Sampler _localParentNotSampled;
      29              : 
      30              :   /// Gets a description of this sampler.
      31              :   ///
      32              :   /// @return A description including the root sampler's description
      33            1 :   @override
      34            3 :   String get description => 'ParentBased{root=${_root.description}}';
      35              : 
      36              :   /// Creates a parent-based sampler with the specified configuration.
      37              :   ///
      38              :   /// @param root The sampler to use when there is no parent span
      39              :   /// @param remoteParentSampled The sampler to use when the remote parent is sampled (defaults to AlwaysOnSampler)
      40              :   /// @param remoteParentNotSampled The sampler to use when the remote parent is not sampled (defaults to AlwaysOffSampler)
      41              :   /// @param localParentSampled The sampler to use when the local parent is sampled (defaults to AlwaysOnSampler)
      42              :   /// @param localParentNotSampled The sampler to use when the local parent is not sampled (defaults to AlwaysOffSampler)
      43            4 :   ParentBasedSampler(
      44              :     this._root, {
      45              :     Sampler? remoteParentSampled,
      46              :     Sampler? remoteParentNotSampled,
      47              :     Sampler? localParentSampled,
      48              :     Sampler? localParentNotSampled,
      49              :   })  : _remoteParentSampled = remoteParentSampled ?? const AlwaysOnSampler(),
      50              :         _remoteParentNotSampled =
      51              :             remoteParentNotSampled ?? const AlwaysOffSampler(),
      52              :         _localParentSampled = localParentSampled ?? const AlwaysOnSampler(),
      53              :         _localParentNotSampled =
      54              :             localParentNotSampled ?? const AlwaysOffSampler();
      55              : 
      56              :   /// Makes a sampling decision based on the parent context.
      57              :   ///
      58              :   /// This method checks if there's a valid parent span context in the parent context.
      59              :   /// If there is, it uses the appropriate sampler based on whether the parent is
      60              :   /// remote or local, and whether it is sampled or not. If there's no valid parent,
      61              :   /// it uses the root sampler.
      62              :   ///
      63              :   /// @param parentContext The parent context containing the parent span
      64              :   /// @param traceId The trace ID of the span
      65              :   /// @param name The name of the span
      66              :   /// @param spanKind The kind of the span
      67              :   /// @param attributes The attributes of the span
      68              :   /// @param links The links to other spans
      69              :   /// @return A sampling result based on the appropriate sampler's decision
      70            4 :   @override
      71              :   SamplingResult shouldSample({
      72              :     required Context parentContext,
      73              :     required String traceId,
      74              :     required String name,
      75              :     required SpanKind spanKind,
      76              :     required Attributes? attributes,
      77              :     required List<SpanLink>? links,
      78              :   }) {
      79              :     // Extract SpanContext from the parent context
      80            4 :     final parentSpanContext = parentContext.spanContext;
      81              : 
      82              :     // If no parent, use root sampler
      83            4 :     if (parentSpanContext == null || !parentSpanContext.isValid) {
      84            8 :       return _root.shouldSample(
      85              :         parentContext: parentContext,
      86              :         traceId: traceId,
      87              :         name: name,
      88              :         spanKind: spanKind,
      89              :         attributes: attributes,
      90              :         links: links,
      91              :       );
      92              :     }
      93              : 
      94              :     // Parent exists, use appropriate sampler based on parent's state
      95            4 :     final isRemote = parentSpanContext.isRemote;
      96            8 :     final isSampled = parentSpanContext.traceFlags.isSampled;
      97              : 
      98              :     if (isRemote) {
      99              :       return isSampled
     100            4 :           ? _remoteParentSampled.shouldSample(
     101              :               parentContext: parentContext,
     102              :               traceId: traceId,
     103              :               name: name,
     104              :               spanKind: spanKind,
     105              :               attributes: attributes,
     106              :               links: links,
     107              :             )
     108            4 :           : _remoteParentNotSampled.shouldSample(
     109              :               parentContext: parentContext,
     110              :               traceId: traceId,
     111              :               name: name,
     112              :               spanKind: spanKind,
     113              :               attributes: attributes,
     114              :               links: links,
     115              :             );
     116              :     } else {
     117              :       return isSampled
     118            8 :           ? _localParentSampled.shouldSample(
     119              :               parentContext: parentContext,
     120              :               traceId: traceId,
     121              :               name: name,
     122              :               spanKind: spanKind,
     123              :               attributes: attributes,
     124              :               links: links,
     125              :             )
     126            4 :           : _localParentNotSampled.shouldSample(
     127              :               parentContext: parentContext,
     128              :               traceId: traceId,
     129              :               name: name,
     130              :               spanKind: spanKind,
     131              :               attributes: attributes,
     132              :               links: links,
     133              :             );
     134              :     }
     135              :   }
     136              : }
        

Generated by: LCOV version 2.0-1