Line data Source code
1 : // Copyright The OpenTelemetry Authors
2 : // SPDX-License-Identifier: Apache-2.0
3 :
4 : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
5 : import '../../otel.dart';
6 : import 'sampler.dart';
7 :
8 : /// A sampler that combines multiple samplers using a specified operation.
9 : class CompositeSampler implements Sampler {
10 : final List<Sampler> _samplers;
11 : final _Operation _operation;
12 :
13 2 : @override
14 : String get description =>
15 16 : 'CompositeSampler{${_operation.name},[${_samplers.map((s) => s.description).join(',')}]}';
16 :
17 : /// Creates a CompositeSampler that requires all samplers to accept.
18 3 : const CompositeSampler.and(List<Sampler> samplers)
19 3 : : this._(samplers, _Operation.and);
20 :
21 : /// Creates a CompositeSampler that requires any sampler to accept.
22 2 : const CompositeSampler.or(List<Sampler> samplers)
23 2 : : this._(samplers, _Operation.or);
24 :
25 3 : const CompositeSampler._(this._samplers, this._operation);
26 :
27 3 : @override
28 : SamplingResult shouldSample({
29 : required Context parentContext,
30 : required String traceId,
31 : required String name,
32 : required SpanKind spanKind,
33 : required Attributes? attributes,
34 : required List<SpanLink>? links,
35 : }) {
36 6 : if (_samplers.isEmpty) {
37 1 : return SamplingResult(
38 : decision: SamplingDecision.recordAndSample,
39 : source: SamplingDecisionSource.tracerConfig,
40 1 : traceState: parentContext.spanContext?.traceState,
41 : );
42 : }
43 :
44 : Attributes? combinedAttributes;
45 :
46 6 : for (final sampler in _samplers) {
47 3 : final result = sampler.shouldSample(
48 : parentContext: parentContext,
49 : traceId: traceId,
50 : name: name,
51 : spanKind: spanKind,
52 : attributes: attributes,
53 : links: links,
54 : );
55 :
56 : // For AND, if any sampler drops, return drop
57 : // For OR, if any sampler samples, return sample
58 6 : if (_operation == _Operation.and &&
59 6 : result.decision == SamplingDecision.drop) {
60 : return result;
61 6 : } else if (_operation == _Operation.or &&
62 4 : result.decision == SamplingDecision.recordAndSample) {
63 : return result;
64 : }
65 :
66 : // Combine attributes if present
67 3 : if (result.attributes != null) {
68 1 : combinedAttributes ??= OTel.attributes();
69 2 : combinedAttributes.copyWithAttributes(result.attributes!);
70 : }
71 : }
72 :
73 : // For AND, all samplers accepted, return recordAndSample
74 : // For OR, no sampler accepted, return drop
75 3 : return SamplingResult(
76 6 : decision: _operation == _Operation.and
77 : ? SamplingDecision.recordAndSample
78 : : SamplingDecision.drop,
79 : source: SamplingDecisionSource.tracerConfig,
80 : attributes: combinedAttributes,
81 4 : traceState: parentContext.spanContext?.traceState,
82 : );
83 : }
84 : }
85 :
86 : enum _Operation { and, or }
|