opentelemetry-sdk 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +23 -0
  4. data/LICENSE +1 -1
  5. data/README.md +73 -0
  6. data/lib/opentelemetry-sdk.rb +7 -0
  7. data/lib/opentelemetry/sdk.rb +51 -0
  8. data/lib/opentelemetry/sdk/baggage.rb +16 -0
  9. data/lib/opentelemetry/sdk/baggage/builder.rb +40 -0
  10. data/lib/opentelemetry/sdk/baggage/manager.rb +97 -0
  11. data/lib/opentelemetry/sdk/configurator.rb +172 -0
  12. data/lib/opentelemetry/sdk/instrumentation_library.rb +13 -0
  13. data/lib/opentelemetry/sdk/internal.rb +21 -1
  14. data/lib/opentelemetry/sdk/resources.rb +1 -0
  15. data/lib/opentelemetry/sdk/resources/constants.rb +124 -0
  16. data/lib/opentelemetry/sdk/resources/resource.rb +39 -19
  17. data/lib/opentelemetry/sdk/trace.rb +2 -1
  18. data/lib/opentelemetry/sdk/trace/config/trace_config.rb +3 -3
  19. data/lib/opentelemetry/sdk/trace/event.rb +48 -0
  20. data/lib/opentelemetry/sdk/trace/export.rb +2 -7
  21. data/lib/opentelemetry/sdk/trace/export/batch_span_processor.rb +41 -35
  22. data/lib/opentelemetry/sdk/trace/export/console_span_exporter.rb +1 -1
  23. data/lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb +7 -7
  24. data/lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb +8 -14
  25. data/lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb +4 -4
  26. data/lib/opentelemetry/sdk/trace/export/simple_span_processor.rb +10 -1
  27. data/lib/opentelemetry/sdk/trace/multi_span_processor.rb +12 -1
  28. data/lib/opentelemetry/sdk/trace/noop_span_processor.rb +10 -1
  29. data/lib/opentelemetry/sdk/trace/samplers.rb +48 -57
  30. data/lib/opentelemetry/sdk/trace/samplers/constant_sampler.rb +33 -0
  31. data/lib/opentelemetry/sdk/trace/samplers/decision.rb +3 -3
  32. data/lib/opentelemetry/sdk/trace/samplers/parent_based.rb +53 -0
  33. data/lib/opentelemetry/sdk/trace/samplers/result.rb +4 -3
  34. data/lib/opentelemetry/sdk/trace/samplers/trace_id_ratio_based.rb +45 -0
  35. data/lib/opentelemetry/sdk/trace/span.rb +39 -28
  36. data/lib/opentelemetry/sdk/trace/span_data.rb +18 -2
  37. data/lib/opentelemetry/sdk/trace/tracer.rb +26 -15
  38. data/lib/opentelemetry/sdk/trace/{tracer_factory.rb → tracer_provider.rb} +9 -9
  39. data/lib/opentelemetry/sdk/version.rb +1 -1
  40. metadata +20 -8
  41. data/lib/opentelemetry/sdk/trace/samplers/probability_sampler.rb +0 -74
@@ -23,7 +23,7 @@ module OpenTelemetry
23
23
  end
24
24
 
25
25
  def export(spans)
26
- return ResultCodes::FAILED_NOT_RETRYABLE if @stopped
26
+ return ResultCodes::FAILURE if @stopped
27
27
 
28
28
  Array(spans).each { |s| pp s }
29
29
 
@@ -14,13 +14,13 @@ module OpenTelemetry
14
14
  #
15
15
  # class MyClassTest
16
16
  # def setup
17
- # @tracer_factory = TracerFactory.new
17
+ # @tracer_provider = TracerProvider.new
18
18
  # @exporter = InMemorySpanExporter.new
19
- # @tracer_factory.add_span_processor(SimpleSampledSpansProcessor.new(@exporter))
19
+ # @tracer_provider.add_span_processor(SimpleSampledSpansProcessor.new(@exporter))
20
20
  # end
21
21
  #
22
22
  # def test_finished_spans
23
- # @tracer_factory.tracer.in_span("span") {}
23
+ # @tracer_provider.tracer.in_span("span") {}
24
24
  #
25
25
  # spans = @exporter.finished_spans
26
26
  # spans.wont_be_nil
@@ -61,18 +61,18 @@ module OpenTelemetry
61
61
  # @param [Enumerable<SpanData>] span_datas the list of sampled {SpanData}s to be
62
62
  # exported.
63
63
  # @return [Integer] the result of the export, SUCCESS or
64
- # FAILED_NOT_RETRYABLE
64
+ # FAILURE
65
65
  def export(span_datas)
66
66
  @mutex.synchronize do
67
- return FAILED_NOT_RETRYABLE if @stopped
67
+ return FAILURE if @stopped
68
68
 
69
69
  @finished_spans.concat(span_datas.to_a)
70
70
  end
71
71
  SUCCESS
72
72
  end
73
73
 
74
- # Called when {TracerFactory#shutdown} is called, if this exporter is
75
- # registered to a {TracerFactory} object.
74
+ # Called when {TracerProvider#shutdown} is called, if this exporter is
75
+ # registered to a {TracerProvider} object.
76
76
  def shutdown
77
77
  @mutex.synchronize do
78
78
  @finished_spans.clear
@@ -26,17 +26,15 @@ module OpenTelemetry
26
26
  # @return [Integer] the result of the export.
27
27
  def export(spans)
28
28
  @span_exporters.inject(SUCCESS) do |result_code, span_exporter|
29
- begin
30
- merge_result_code(result_code, span_exporter.export(spans))
31
- rescue => e # rubocop:disable Style/RescueStandardError
32
- OpenTelemetry.logger.warn("exception raised by export - #{e}")
33
- FAILED_NOT_RETRYABLE
34
- end
29
+ merge_result_code(result_code, span_exporter.export(spans))
30
+ rescue => e # rubocop:disable Style/RescueStandardError
31
+ OpenTelemetry.logger.warn("exception raised by export - #{e}")
32
+ FAILURE
35
33
  end
36
34
  end
37
35
 
38
- # Called when {TracerFactory#shutdown} is called, if this exporter is
39
- # registered to a {TracerFactory} object.
36
+ # Called when {TracerProvider#shutdown} is called, if this exporter is
37
+ # registered to a {TracerProvider} object.
40
38
  def shutdown
41
39
  @span_exporters.each(&:shutdown)
42
40
  end
@@ -48,13 +46,9 @@ module OpenTelemetry
48
46
  if result_code == SUCCESS && new_result_code == SUCCESS
49
47
  # If both errors are success then return success.
50
48
  SUCCESS
51
- elsif result_code == FAILED_NOT_RETRYABLE || new_result_code == FAILED_NOT_RETRYABLE
52
- # If any of the codes is not retryable then return not_retryable.
53
- FAILED_NOT_RETRYABLE
54
49
  else
55
- # At this point at least one of the code is FAILED_RETRYABLE and
56
- # none are FAILED_NOT_RETRYABLE, so return FAILED_RETRYABLE.
57
- FAILED_RETRYABLE
50
+ # At this point at least one of the code is FAILURE, so return FAILURE.
51
+ FAILURE
58
52
  end
59
53
  end
60
54
  end
@@ -12,7 +12,7 @@ module OpenTelemetry
12
12
  # duck type. SpanExporter allows different tracing services to export
13
13
  # recorded data for sampled spans in their own format.
14
14
  #
15
- # To export data an exporter MUST be registered to the {TracerFactory} using
15
+ # To export data an exporter MUST be registered to the {TracerProvider} using
16
16
  # a {SimpleSpanProcessor} or a {BatchSpanProcessor}.
17
17
  class NoopSpanExporter
18
18
  def initialize
@@ -27,11 +27,11 @@ module OpenTelemetry
27
27
  def export(spans)
28
28
  return SUCCESS unless @stopped
29
29
 
30
- FAILED_NOT_RETRYABLE
30
+ FAILURE
31
31
  end
32
32
 
33
- # Called when {TracerFactory#shutdown} is called, if this exporter is
34
- # registered to a {TracerFactory} object.
33
+ # Called when {TracerProvider#shutdown} is called, if this exporter is
34
+ # registered to a {TracerProvider} object.
35
35
  def shutdown
36
36
  @stopped = true
37
37
  end
@@ -52,7 +52,16 @@ module OpenTelemetry
52
52
  OpenTelemetry.logger.error("unexpected error in span.on_finish - #{e}")
53
53
  end
54
54
 
55
- # Called when {TracerFactory#shutdown} is called.
55
+ # Export all ended spans to the configured `Exporter` that have not yet
56
+ # been exported.
57
+ #
58
+ # This method should only be called in cases where it is absolutely
59
+ # necessary, such as when using some FaaS providers that may suspend
60
+ # the process after an invocation, but before the `Processor` exports
61
+ # the completed spans.
62
+ def force_flush; end
63
+
64
+ # Called when {TracerProvider#shutdown} is called.
56
65
  def shutdown
57
66
  @span_exporter&.shutdown
58
67
  end
@@ -41,7 +41,18 @@ module OpenTelemetry
41
41
  @span_processors.each { |processor| processor.on_finish(span) }
42
42
  end
43
43
 
44
- # Called when {TracerFactory#shutdown} is called.
44
+ # Export all ended spans to the configured `Exporter` that have not yet
45
+ # been exported.
46
+ #
47
+ # This method should only be called in cases where it is absolutely
48
+ # necessary, such as when using some FaaS providers that may suspend
49
+ # the process after an invocation, but before the `Processor` exports
50
+ # the completed spans.
51
+ def force_flush
52
+ @span_processors.each(&:force_flush)
53
+ end
54
+
55
+ # Called when {TracerProvider#shutdown} is called.
45
56
  def shutdown
46
57
  @span_processors.each(&:shutdown)
47
58
  end
@@ -33,7 +33,16 @@ module OpenTelemetry
33
33
  # @param [Span] span the {Span} that just ended.
34
34
  def on_finish(span); end
35
35
 
36
- # Called when {TracerFactory#shutdown} is called.
36
+ # Export all ended spans to the configured `Exporter` that have not yet
37
+ # been exported.
38
+ #
39
+ # This method should only be called in cases where it is absolutely
40
+ # necessary, such as when using some FaaS providers that may suspend
41
+ # the process after an invocation, but before the `Processor` exports
42
+ # the completed spans.
43
+ def force_flush; end
44
+
45
+ # Called when {TracerProvider#shutdown} is called.
37
46
  def shutdown; end
38
47
  end
39
48
  end
@@ -6,29 +6,28 @@
6
6
 
7
7
  require 'opentelemetry/sdk/trace/samplers/decision'
8
8
  require 'opentelemetry/sdk/trace/samplers/result'
9
- require 'opentelemetry/sdk/trace/samplers/probability_sampler'
9
+ require 'opentelemetry/sdk/trace/samplers/constant_sampler'
10
+ require 'opentelemetry/sdk/trace/samplers/parent_based'
11
+ require 'opentelemetry/sdk/trace/samplers/trace_id_ratio_based'
10
12
 
11
13
  module OpenTelemetry
12
14
  module SDK
13
15
  module Trace
14
16
  # The Samplers module contains the sampling logic for OpenTelemetry. The
15
- # reference implementation provides a {ProbabilitySampler}, {ALWAYS_ON},
16
- # {ALWAYS_OFF}, and {ALWAYS_PARENT}.
17
+ # reference implementation provides a {TraceIdRatioBased}, {ALWAYS_ON},
18
+ # {ALWAYS_OFF}, and {ParentBased}.
17
19
  #
18
- # Custom samplers can be provided by SDK users. The required interface is
19
- # a callable with the signature:
20
+ # Custom samplers can be provided by SDK users. The required interface is:
20
21
  #
21
- # (trace_id:, span_id:, parent_context:, hint:, links:, name:, kind:, attributes:) -> Result
22
+ # should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:) -> Result
23
+ # description -> String
22
24
  #
23
25
  # Where:
24
26
  #
25
27
  # @param [String] trace_id The trace_id of the {Span} to be created.
26
- # @param [String] span_id The span_id of the {Span} to be created.
27
28
  # @param [OpenTelemetry::Trace::SpanContext] parent_context The
28
29
  # {OpenTelemetry::Trace::SpanContext} of a parent span, typically
29
30
  # extracted from the wire. Can be nil for a root span.
30
- # @param [Symbol] hint A {OpenTelemetry::Trace::SamplingHint} about
31
- # whether the {Span} should be sampled and/or record events.
32
31
  # @param [Enumerable<Link>] links A collection of links to be associated
33
32
  # with the {Span} to be created. Can be nil.
34
33
  # @param [String] name Name of the {Span} to be created.
@@ -42,63 +41,55 @@ module OpenTelemetry
42
41
  NOT_RECORD = Result.new(decision: Decision::NOT_RECORD)
43
42
  RECORD = Result.new(decision: Decision::RECORD)
44
43
  SAMPLING_HINTS = [Decision::NOT_RECORD, Decision::RECORD, Decision::RECORD_AND_SAMPLED].freeze
45
- APPLY_PROBABILITY_TO_SYMBOLS = %i[root_spans root_spans_and_remote_parent all_spans].freeze
46
44
 
47
- private_constant(:RECORD_AND_SAMPLED, :NOT_RECORD, :RECORD, :SAMPLING_HINTS, :APPLY_PROBABILITY_TO_SYMBOLS)
45
+ private_constant(:RECORD_AND_SAMPLED, :NOT_RECORD, :RECORD, :SAMPLING_HINTS)
48
46
 
49
- # rubocop:disable Lint/UnusedBlockArgument
47
+ # Returns a {Result} with {Decision::RECORD_AND_SAMPLED}.
48
+ ALWAYS_ON = ConstantSampler.new(result: RECORD_AND_SAMPLED, description: 'AlwaysOnSampler')
50
49
 
51
- # Ignores all values in hint and returns a {Result} with
52
- # {Decision::RECORD_AND_SAMPLED}.
53
- ALWAYS_ON = ->(trace_id:, span_id:, parent_context:, hint:, links:, name:, kind:, attributes:) { RECORD_AND_SAMPLED }
50
+ # Returns a {Result} with {Decision::NOT_RECORD}.
51
+ ALWAYS_OFF = ConstantSampler.new(result: NOT_RECORD, description: 'AlwaysOffSampler')
54
52
 
55
- # Ignores all values in hint and returns a {Result} with
56
- # {Decision::NOT_RECORD}.
57
- ALWAYS_OFF = ->(trace_id:, span_id:, parent_context:, hint:, links:, name:, kind:, attributes:) { NOT_RECORD }
58
-
59
- # Ignores all values in hint and returns a {Result} with
60
- # {Decision::RECORD_AND_SAMPLED} if the parent context is sampled or
61
- # {Decision::NOT_RECORD} otherwise, or if there is no parent context.
62
- # rubocop:disable Style/Lambda
63
- ALWAYS_PARENT = ->(trace_id:, span_id:, parent_context:, hint:, links:, name:, kind:, attributes:) do
64
- if parent_context&.trace_flags&.sampled?
65
- RECORD_AND_SAMPLED
66
- else
67
- NOT_RECORD
68
- end
53
+ # Returns a new sampler. It delegates to samplers according to the following rules:
54
+ #
55
+ # | Parent | parent.remote? | parent.trace_flags.sampled? | Invoke sampler |
56
+ # |--|--|--|--|
57
+ # | absent | n/a | n/a | root |
58
+ # | present | true | true | remote_parent_sampled |
59
+ # | present | true | false | remote_parent_not_sampled |
60
+ # | present | false | true | local_parent_sampled |
61
+ # | present | false | false | local_parent_not_sampled |
62
+ #
63
+ # @param [Sampler] root The sampler to which the sampling
64
+ # decision is delegated for spans with no parent (root spans).
65
+ # @param [optional Sampler] remote_parent_sampled The sampler to which the sampling
66
+ # decision is delegated for remote parent sampled spans. Defaults to ALWAYS_ON.
67
+ # @param [optional Sampler] remote_parent_not_sampled The sampler to which the sampling
68
+ # decision is delegated for remote parent not sampled spans. Defaults to ALWAYS_OFF.
69
+ # @param [optional Sampler] local_parent_sampled The sampler to which the sampling
70
+ # decision is delegated for local parent sampled spans. Defaults to ALWAYS_ON.
71
+ # @param [optional Sampler] local_parent_not_sampled The sampler to which the sampling
72
+ # decision is delegated for local parent not sampld spans. Defaults to ALWAYS_OFF.
73
+ def self.parent_based(
74
+ root:,
75
+ remote_parent_sampled: ALWAYS_ON,
76
+ remote_parent_not_sampled: ALWAYS_OFF,
77
+ local_parent_sampled: ALWAYS_ON,
78
+ local_parent_not_sampled: ALWAYS_OFF
79
+ )
80
+ ParentBased.new(root, remote_parent_sampled, remote_parent_not_sampled, local_parent_sampled, local_parent_not_sampled)
69
81
  end
70
- # rubocop:enable Style/Lambda
71
- # rubocop:enable Lint/UnusedBlockArgument
72
82
 
73
- # Returns a new sampler. The probability of sampling a trace is equal
74
- # to that of the specified probability.
83
+ # Returns a new sampler. The ratio describes the proportion of the trace ID
84
+ # space that is sampled.
75
85
  #
76
- # @param [Numeric] probability The desired probability of sampling.
86
+ # @param [Numeric] ratio The desired sampling ratio.
77
87
  # Must be within [0.0, 1.0].
78
- # @param [optional Enumerable<Symbol>] ignore_hints Sampling hints to
79
- # ignore. Defaults to ignore {OpenTelemetry::Trace::SamplingHint::RECORD}.
80
- # @param [optional Boolean] ignore_parent Whether to ignore parent
81
- # sampling. Defaults to not ignore parent sampling.
82
- # @param [optional Symbol] apply_probability_to Whether to apply
83
- # probability sampling to root spans, root spans and remote parents,
84
- # or all spans. Allowed values include :root_spans, :root_spans_and_remote_parent,
85
- # and :all_spans. Defaults to :root_spans_and_remote_parent.
86
- # @raise [ArgumentError] if probability is out of range
87
- # @raise [ArgumentError] if ignore_hints contains invalid hints
88
- # @raise [ArgumentError] if apply_probability_to is not one of the allowed symbols
89
- def self.probability(probability,
90
- ignore_hints: [OpenTelemetry::Trace::SamplingHint::RECORD],
91
- ignore_parent: false,
92
- apply_probability_to: :root_spans_and_remote_parent)
93
- raise ArgumentError, 'probability must be in range [0.0, 1.0]' unless (0.0..1.0).include?(probability)
94
- raise ArgumentError, 'ignore_hints' unless (ignore_hints.to_a - SAMPLING_HINTS).empty?
95
- raise ArgumentError, 'apply_probability_to' unless APPLY_PROBABILITY_TO_SYMBOLS.include?(apply_probability_to)
88
+ # @raise [ArgumentError] if ratio is out of range
89
+ def self.trace_id_ratio_based(ratio)
90
+ raise ArgumentError, 'ratio must be in range [0.0, 1.0]' unless (0.0..1.0).include?(ratio)
96
91
 
97
- ProbabilitySampler.new(probability,
98
- ignore_hints: ignore_hints.to_a,
99
- ignore_parent: ignore_parent,
100
- apply_to_remote_parent: apply_probability_to != :root_spans,
101
- apply_to_all_spans: apply_probability_to == :all_spans)
92
+ TraceIdRatioBased.new(ratio)
102
93
  end
103
94
  end
104
95
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Trace
10
+ module Samplers
11
+ # @api private
12
+ #
13
+ # Implements a sampler returning a constant result.
14
+ class ConstantSampler
15
+ attr_reader :description
16
+
17
+ def initialize(result:, description:)
18
+ @result = result
19
+ @description = description
20
+ end
21
+
22
+ # @api private
23
+ #
24
+ # See {Samplers}.
25
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
26
+ # All arguments ignored for sampling decision.
27
+ @result
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -12,13 +12,13 @@ module OpenTelemetry
12
12
  # decision part of a sampling {Result}.
13
13
  module Decision
14
14
  # Decision to not record events and not sample.
15
- NOT_RECORD = OpenTelemetry::Trace::SamplingHint::NOT_RECORD
15
+ NOT_RECORD = :__not_record__
16
16
 
17
17
  # Decision to record events and not sample.
18
- RECORD = OpenTelemetry::Trace::SamplingHint::RECORD
18
+ RECORD = :__record__
19
19
 
20
20
  # Decision to record events and sample.
21
- RECORD_AND_SAMPLED = OpenTelemetry::Trace::SamplingHint::RECORD_AND_SAMPLED
21
+ RECORD_AND_SAMPLED = :__record_and_sampled__
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Trace
10
+ module Samplers
11
+ # @api private
12
+ #
13
+ # This is a composite sampler. ParentBased helps distinguished between the
14
+ # following cases:
15
+ # * No parent (root span).
16
+ # * Remote parent (SpanContext.remote? with trace_flags.sampled?)
17
+ # * Remote parent (SpanContext.remote? with !trace_flags.sampled?)
18
+ # * Local parent (!SpanContext.remote? with trace_flags.sampled?)
19
+ # * Local parent (!SpanContext.remote? with !trace_flags.sampled?)
20
+ class ParentBased
21
+ def initialize(root, remote_parent_sampled, remote_parent_not_sampled, local_parent_sampled, local_parent_not_sampled)
22
+ @root = root
23
+ @remote_parent_sampled = remote_parent_sampled
24
+ @remote_parent_not_sampled = remote_parent_not_sampled
25
+ @local_parent_sampled = local_parent_sampled
26
+ @local_parent_not_sampled = local_parent_not_sampled
27
+ end
28
+
29
+ # @api private
30
+ #
31
+ # See {Samplers}.
32
+ def description
33
+ "ParentBased{root=#{@root.description}, remote_parent_sampled=#{@remote_parent_sampled.description}, remote_parent_not_sampled=#{@remote_parent_not_sampled.description}, local_parent_sampled=#{@local_parent_sampled.description}, local_parent_not_sampled=#{@local_parent_not_sampled.description}}"
34
+ end
35
+
36
+ # @api private
37
+ #
38
+ # See {Samplers}.
39
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
40
+ delegate = if parent_context.nil?
41
+ @root
42
+ elsif parent_context.remote?
43
+ parent_context.trace_flags.sampled? ? @remote_parent_sampled : @remote_parent_not_sampled
44
+ else
45
+ parent_context.trace_flags.sampled? ? @local_parent_sampled : @local_parent_not_sampled
46
+ end
47
+ delegate.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -19,7 +19,7 @@ module OpenTelemetry
19
19
 
20
20
  # Returns a frozen hash of attributes to be attached span.
21
21
  #
22
- # @return [Hash<String, Object>]
22
+ # @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
23
23
  attr_reader :attributes
24
24
 
25
25
  # Returns a new sampling result with the specified decision and
@@ -27,8 +27,9 @@ module OpenTelemetry
27
27
  #
28
28
  # @param [Symbol] decision Whether or not a span should be sampled
29
29
  # and/or record events.
30
- # @param [optional Hash<String, Object>] attributes A frozen or freezable hash
31
- # containing attributes to be attached to the span.
30
+ # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
31
+ # attributes A frozen or freezable hash containing attributes to be
32
+ # attached to the span.
32
33
  def initialize(decision:, attributes: nil)
33
34
  @decision = decision
34
35
  @attributes = attributes.freeze || EMPTY_HASH
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Trace
10
+ module Samplers
11
+ # @api private
12
+ #
13
+ # Implements sampling based on a probability.
14
+ class TraceIdRatioBased
15
+ attr_reader :description
16
+
17
+ def initialize(probability)
18
+ @probability = probability
19
+ @id_upper_bound = (probability * (2**64 - 1)).ceil
20
+ @description = format('TraceIdRatioBased{%.6f}', probability)
21
+ end
22
+
23
+ # @api private
24
+ #
25
+ # See {Samplers}.
26
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
27
+ # Ignored for sampling decision: parent_context:, links, name, kind, attributes.
28
+
29
+ if sample?(trace_id)
30
+ RECORD_AND_SAMPLED
31
+ else
32
+ NOT_RECORD
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def sample?(trace_id)
39
+ @probability == 1.0 || trace_id[8, 8].unpack1('Q>') < @id_upper_bound
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end