opentelemetry-sdk 0.5.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -2
  3. data/CHANGELOG.md +60 -0
  4. data/README.md +1 -1
  5. data/lib/opentelemetry/sdk.rb +2 -1
  6. data/lib/opentelemetry/sdk/baggage.rb +16 -0
  7. data/lib/opentelemetry/sdk/{correlation_context → baggage}/builder.rb +5 -5
  8. data/lib/opentelemetry/sdk/{correlation_context → baggage}/manager.rb +37 -27
  9. data/lib/opentelemetry/sdk/configurator.rb +41 -20
  10. data/lib/opentelemetry/sdk/resources/constants.rb +0 -4
  11. data/lib/opentelemetry/sdk/resources/resource.rb +33 -22
  12. data/lib/opentelemetry/sdk/trace.rb +1 -0
  13. data/lib/opentelemetry/sdk/trace/config/trace_config.rb +3 -3
  14. data/lib/opentelemetry/sdk/trace/event.rb +48 -0
  15. data/lib/opentelemetry/sdk/trace/export.rb +9 -4
  16. data/lib/opentelemetry/sdk/trace/export/batch_span_processor.rb +84 -36
  17. data/lib/opentelemetry/sdk/trace/export/console_span_exporter.rb +5 -8
  18. data/lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb +8 -2
  19. data/lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb +17 -16
  20. data/lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb +6 -2
  21. data/lib/opentelemetry/sdk/trace/export/simple_span_processor.rb +22 -4
  22. data/lib/opentelemetry/sdk/trace/multi_span_processor.rb +30 -6
  23. data/lib/opentelemetry/sdk/trace/noop_span_processor.rb +17 -3
  24. data/lib/opentelemetry/sdk/trace/samplers.rb +46 -45
  25. data/lib/opentelemetry/sdk/trace/samplers/constant_sampler.rb +4 -5
  26. data/lib/opentelemetry/sdk/trace/samplers/decision.rb +3 -3
  27. data/lib/opentelemetry/sdk/trace/samplers/parent_based.rb +54 -0
  28. data/lib/opentelemetry/sdk/trace/samplers/result.rb +16 -5
  29. data/lib/opentelemetry/sdk/trace/samplers/trace_id_ratio_based.rb +44 -0
  30. data/lib/opentelemetry/sdk/trace/span.rb +30 -36
  31. data/lib/opentelemetry/sdk/trace/span_data.rb +16 -3
  32. data/lib/opentelemetry/sdk/trace/tracer.rb +13 -12
  33. data/lib/opentelemetry/sdk/trace/tracer_provider.rb +4 -2
  34. data/lib/opentelemetry/sdk/version.rb +1 -1
  35. metadata +30 -11
  36. data/lib/opentelemetry/sdk/correlation_context.rb +0 -16
  37. data/lib/opentelemetry/sdk/trace/samplers/parent_or_else.rb +0 -43
  38. data/lib/opentelemetry/sdk/trace/samplers/probability_sampler.rb +0 -64
@@ -26,8 +26,10 @@ module OpenTelemetry
26
26
  # not throw or block the execution thread.
27
27
  #
28
28
  # @param [Span] span the {Span} that just started.
29
- def on_start(span)
30
- @span_processors.each { |processor| processor.on_start(span) }
29
+ # @param [Context] parent_context the parent {Context} of the newly
30
+ # started span.
31
+ def on_start(span, parent_context)
32
+ @span_processors.each { |processor| processor.on_start(span, parent_context) }
31
33
  end
32
34
 
33
35
  # Called when a {Span} is ended, if the {Span#recording?}
@@ -48,13 +50,35 @@ module OpenTelemetry
48
50
  # necessary, such as when using some FaaS providers that may suspend
49
51
  # the process after an invocation, but before the `Processor` exports
50
52
  # the completed spans.
51
- def force_flush
52
- @span_processors.each(&:force_flush)
53
+ #
54
+ # @param [optional Numeric] timeout An optional timeout in seconds.
55
+ # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
56
+ # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
57
+ def force_flush(timeout: nil)
58
+ start_time = Time.now
59
+ results = @span_processors.map do |processor|
60
+ remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
61
+ return Export::TIMEOUT if remaining_timeout&.zero?
62
+
63
+ processor.force_flush(timeout: remaining_timeout)
64
+ end
65
+ results.uniq.max
53
66
  end
54
67
 
55
68
  # Called when {TracerProvider#shutdown} is called.
56
- def shutdown
57
- @span_processors.each(&:shutdown)
69
+ #
70
+ # @param [optional Numeric] timeout An optional timeout in seconds.
71
+ # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
72
+ # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
73
+ def shutdown(timeout: nil)
74
+ start_time = Time.now
75
+ results = @span_processors.map do |processor|
76
+ remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
77
+ return Export::TIMEOUT if remaining_timeout&.zero?
78
+
79
+ processor.shutdown(timeout: remaining_timeout)
80
+ end
81
+ results.uniq.max
58
82
  end
59
83
  end
60
84
  end
@@ -22,7 +22,9 @@ module OpenTelemetry
22
22
  # not throw or block the execution thread.
23
23
  #
24
24
  # @param [Span] span the {Span} that just started.
25
- def on_start(span); end
25
+ # @param [Context] parent_context the parent {Context} of the newly
26
+ # started span.
27
+ def on_start(span, parent_context); end
26
28
 
27
29
  # Called when a {Span} is ended, if the {Span#recording?}
28
30
  # returns true.
@@ -40,10 +42,22 @@ module OpenTelemetry
40
42
  # necessary, such as when using some FaaS providers that may suspend
41
43
  # the process after an invocation, but before the `Processor` exports
42
44
  # the completed spans.
43
- def force_flush; end
45
+ #
46
+ # @param [optional Numeric] timeout An optional timeout in seconds.
47
+ # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
48
+ # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
49
+ def force_flush(timeout: nil)
50
+ Export::SUCCESS
51
+ end
44
52
 
45
53
  # Called when {TracerProvider#shutdown} is called.
46
- def shutdown; end
54
+ #
55
+ # @param [optional Numeric] timeout An optional timeout in seconds.
56
+ # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
57
+ # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
58
+ def shutdown(timeout: nil)
59
+ Export::SUCCESS
60
+ end
47
61
  end
48
62
  end
49
63
  end
@@ -7,15 +7,15 @@
7
7
  require 'opentelemetry/sdk/trace/samplers/decision'
8
8
  require 'opentelemetry/sdk/trace/samplers/result'
9
9
  require 'opentelemetry/sdk/trace/samplers/constant_sampler'
10
- require 'opentelemetry/sdk/trace/samplers/parent_or_else'
11
- require 'opentelemetry/sdk/trace/samplers/probability_sampler'
10
+ require 'opentelemetry/sdk/trace/samplers/parent_based'
11
+ require 'opentelemetry/sdk/trace/samplers/trace_id_ratio_based'
12
12
 
13
13
  module OpenTelemetry
14
14
  module SDK
15
15
  module Trace
16
16
  # The Samplers module contains the sampling logic for OpenTelemetry. The
17
- # reference implementation provides a {ProbabilitySampler}, {ALWAYS_ON},
18
- # {ALWAYS_OFF}, and {ParentOrElse}.
17
+ # reference implementation provides a {TraceIdRatioBased}, {ALWAYS_ON},
18
+ # {ALWAYS_OFF}, and {ParentBased}.
19
19
  #
20
20
  # Custom samplers can be provided by SDK users. The required interface is:
21
21
  #
@@ -25,9 +25,10 @@ module OpenTelemetry
25
25
  # Where:
26
26
  #
27
27
  # @param [String] trace_id The trace_id of the {Span} to be created.
28
- # @param [OpenTelemetry::Trace::SpanContext] parent_context The
29
- # {OpenTelemetry::Trace::SpanContext} of a parent span, typically
30
- # extracted from the wire. Can be nil for a root span.
28
+ # @param [OpenTelemetry::Context] parent_context The
29
+ # {OpenTelemetry::Context} with a parent {Span}. The {Span}'s
30
+ # {OpenTelemetry::Trace::SpanContext} may be invalid to indicate a
31
+ # root span.
31
32
  # @param [Enumerable<Link>] links A collection of links to be associated
32
33
  # with the {Span} to be created. Can be nil.
33
34
  # @param [String] name Name of the {Span} to be created.
@@ -37,52 +38,52 @@ module OpenTelemetry
37
38
  # to the {Span} to be created. Can be nil.
38
39
  # @return [Result] The sampling result.
39
40
  module Samplers
40
- RECORD_AND_SAMPLED = Result.new(decision: Decision::RECORD_AND_SAMPLED)
41
- NOT_RECORD = Result.new(decision: Decision::NOT_RECORD)
42
- RECORD = Result.new(decision: Decision::RECORD)
43
- SAMPLING_HINTS = [Decision::NOT_RECORD, Decision::RECORD, Decision::RECORD_AND_SAMPLED].freeze
44
- APPLY_PROBABILITY_TO_SYMBOLS = %i[root_spans root_spans_and_remote_parent all_spans].freeze
41
+ # Returns a {Result} with {Decision::RECORD_AND_SAMPLE}.
42
+ ALWAYS_ON = ConstantSampler.new(decision: Decision::RECORD_AND_SAMPLE, description: 'AlwaysOnSampler')
45
43
 
46
- private_constant(:RECORD_AND_SAMPLED, :NOT_RECORD, :RECORD, :SAMPLING_HINTS, :APPLY_PROBABILITY_TO_SYMBOLS)
44
+ # Returns a {Result} with {Decision::DROP}.
45
+ ALWAYS_OFF = ConstantSampler.new(decision: Decision::DROP, description: 'AlwaysOffSampler')
47
46
 
48
- # Returns a {Result} with {Decision::RECORD_AND_SAMPLED}.
49
- ALWAYS_ON = ConstantSampler.new(result: RECORD_AND_SAMPLED, description: 'AlwaysOnSampler')
50
-
51
- # Returns a {Result} with {Decision::NOT_RECORD}.
52
- ALWAYS_OFF = ConstantSampler.new(result: NOT_RECORD, description: 'AlwaysOffSampler')
53
-
54
- # Returns a new sampler. It either respects the parent span's sampling
55
- # decision or delegates to delegate_sampler for root spans.
47
+ # Returns a new sampler. It delegates to samplers according to the following rules:
48
+ #
49
+ # | Parent | parent.remote? | parent.trace_flags.sampled? | Invoke sampler |
50
+ # |--|--|--|--|
51
+ # | absent | n/a | n/a | root |
52
+ # | present | true | true | remote_parent_sampled |
53
+ # | present | true | false | remote_parent_not_sampled |
54
+ # | present | false | true | local_parent_sampled |
55
+ # | present | false | false | local_parent_not_sampled |
56
56
  #
57
- # @param [Sampler] delegate_sampler The sampler to which the sampling
58
- # decision is delegated for root spans.
59
- def self.parent_or_else(delegate_sampler)
60
- ParentOrElse.new(delegate_sampler)
57
+ # @param [Sampler] root The sampler to which the sampling
58
+ # decision is delegated for spans with no parent (root spans).
59
+ # @param [optional Sampler] remote_parent_sampled The sampler to which the sampling
60
+ # decision is delegated for remote parent sampled spans. Defaults to ALWAYS_ON.
61
+ # @param [optional Sampler] remote_parent_not_sampled The sampler to which the sampling
62
+ # decision is delegated for remote parent not sampled spans. Defaults to ALWAYS_OFF.
63
+ # @param [optional Sampler] local_parent_sampled The sampler to which the sampling
64
+ # decision is delegated for local parent sampled spans. Defaults to ALWAYS_ON.
65
+ # @param [optional Sampler] local_parent_not_sampled The sampler to which the sampling
66
+ # decision is delegated for local parent not sampld spans. Defaults to ALWAYS_OFF.
67
+ def self.parent_based(
68
+ root:,
69
+ remote_parent_sampled: ALWAYS_ON,
70
+ remote_parent_not_sampled: ALWAYS_OFF,
71
+ local_parent_sampled: ALWAYS_ON,
72
+ local_parent_not_sampled: ALWAYS_OFF
73
+ )
74
+ ParentBased.new(root, remote_parent_sampled, remote_parent_not_sampled, local_parent_sampled, local_parent_not_sampled)
61
75
  end
62
76
 
63
- # Returns a new sampler. The probability of sampling a trace is equal
64
- # to that of the specified probability.
77
+ # Returns a new sampler. The ratio describes the proportion of the trace ID
78
+ # space that is sampled.
65
79
  #
66
- # @param [Numeric] probability The desired probability of sampling.
80
+ # @param [Numeric] ratio The desired sampling ratio.
67
81
  # Must be within [0.0, 1.0].
68
- # @param [optional Boolean] ignore_parent Whether to ignore parent
69
- # sampling. Defaults to not ignore parent sampling.
70
- # @param [optional Symbol] apply_probability_to Whether to apply
71
- # probability sampling to root spans, root spans and remote parents,
72
- # or all spans. Allowed values include :root_spans, :root_spans_and_remote_parent,
73
- # and :all_spans. Defaults to :root_spans_and_remote_parent.
74
- # @raise [ArgumentError] if probability is out of range
75
- # @raise [ArgumentError] if apply_probability_to is not one of the allowed symbols
76
- def self.probability(probability,
77
- ignore_parent: false,
78
- apply_probability_to: :root_spans_and_remote_parent)
79
- raise ArgumentError, 'probability must be in range [0.0, 1.0]' unless (0.0..1.0).include?(probability)
80
- raise ArgumentError, 'apply_probability_to' unless APPLY_PROBABILITY_TO_SYMBOLS.include?(apply_probability_to)
82
+ # @raise [ArgumentError] if ratio is out of range
83
+ def self.trace_id_ratio_based(ratio)
84
+ raise ArgumentError, 'ratio must be in range [0.0, 1.0]' unless (0.0..1.0).include?(ratio)
81
85
 
82
- ProbabilitySampler.new(probability,
83
- ignore_parent: ignore_parent,
84
- apply_to_remote_parent: apply_probability_to != :root_spans,
85
- apply_to_all_spans: apply_probability_to == :all_spans)
86
+ TraceIdRatioBased.new(ratio)
86
87
  end
87
88
  end
88
89
  end
@@ -10,12 +10,12 @@ module OpenTelemetry
10
10
  module Samplers
11
11
  # @api private
12
12
  #
13
- # Implements a sampler returning a constant result.
13
+ # Implements a sampler returning a result with a constant decision.
14
14
  class ConstantSampler
15
15
  attr_reader :description
16
16
 
17
- def initialize(result:, description:)
18
- @result = result
17
+ def initialize(decision:, description:)
18
+ @decision = decision
19
19
  @description = description
20
20
  end
21
21
 
@@ -23,8 +23,7 @@ module OpenTelemetry
23
23
  #
24
24
  # See {Samplers}.
25
25
  def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
26
- # All arguments ignored for sampling decision.
27
- @result
26
+ Result.new(decision: @decision, tracestate: OpenTelemetry::Trace.current_span(parent_context).context.tracestate)
28
27
  end
29
28
  end
30
29
  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 = :__not_record__
15
+ DROP = :__drop__
16
16
 
17
17
  # Decision to record events and not sample.
18
- RECORD = :__record__
18
+ RECORD_ONLY = :__record_only__
19
19
 
20
20
  # Decision to record events and sample.
21
- RECORD_AND_SAMPLED = :__record_and_sampled__
21
+ RECORD_AND_SAMPLE = :__record_and_sample__
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,54 @@
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
+ parent_span_context = OpenTelemetry::Trace.current_span(parent_context).context
41
+ delegate = if !parent_span_context.valid?
42
+ @root
43
+ elsif parent_span_context.remote?
44
+ parent_span_context.trace_flags.sampled? ? @remote_parent_sampled : @remote_parent_not_sampled
45
+ else
46
+ parent_span_context.trace_flags.sampled? ? @local_parent_sampled : @local_parent_not_sampled
47
+ end
48
+ delegate.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -14,14 +14,19 @@ module OpenTelemetry
14
14
  # root span.
15
15
  class Result
16
16
  EMPTY_HASH = {}.freeze
17
- DECISIONS = [Decision::RECORD, Decision::NOT_RECORD, Decision::RECORD_AND_SAMPLED].freeze
17
+ DECISIONS = [Decision::RECORD_ONLY, Decision::DROP, Decision::RECORD_AND_SAMPLE].freeze
18
18
  private_constant(:EMPTY_HASH, :DECISIONS)
19
19
 
20
- # Returns a frozen hash of attributes to be attached span.
20
+ # Returns a frozen hash of attributes to be attached to the span.
21
21
  #
22
22
  # @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
23
23
  attr_reader :attributes
24
24
 
25
+ # Returns a Tracestate to be associated with the span.
26
+ #
27
+ # @return [Tracestate]
28
+ attr_reader :tracestate
29
+
25
30
  # Returns a new sampling result with the specified decision and
26
31
  # attributes.
27
32
  #
@@ -30,23 +35,29 @@ module OpenTelemetry
30
35
  # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
31
36
  # attributes A frozen or freezable hash containing attributes to be
32
37
  # attached to the span.
33
- def initialize(decision:, attributes: nil)
38
+ # @param [Tracestate] tracestate A Tracestate that will be associated
39
+ # with the Span through the new SpanContext. If the sampler returns
40
+ # an empty Tracestate here, the Tracestate will be cleared, so
41
+ # samplers SHOULD normally return the passed-in Tracestate if they
42
+ # do not intend to change it.
43
+ def initialize(decision:, attributes: nil, tracestate:)
34
44
  @decision = decision
35
45
  @attributes = attributes.freeze || EMPTY_HASH
46
+ @tracestate = tracestate
36
47
  end
37
48
 
38
49
  # Returns true if this span should be sampled.
39
50
  #
40
51
  # @return [Boolean] sampling decision
41
52
  def sampled?
42
- @decision == Decision::RECORD_AND_SAMPLED
53
+ @decision == Decision::RECORD_AND_SAMPLE
43
54
  end
44
55
 
45
56
  # Returns true if this span should record events, attributes, status, etc.
46
57
  #
47
58
  # @return [Boolean] recording decision
48
59
  def recording?
49
- @decision != Decision::NOT_RECORD
60
+ @decision != Decision::DROP
50
61
  end
51
62
  end
52
63
  end
@@ -0,0 +1,44 @@
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
+ tracestate = OpenTelemetry::Trace.current_span(parent_context).context.tracestate
28
+ if sample?(trace_id)
29
+ Result.new(decision: Decision::RECORD_AND_SAMPLE, tracestate: tracestate)
30
+ else
31
+ Result.new(decision: Decision::DROP, tracestate: tracestate)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def sample?(trace_id)
38
+ @probability == 1.0 || trace_id[8, 8].unpack1('Q>') < @id_upper_bound
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -16,12 +16,16 @@ module OpenTelemetry
16
16
  #
17
17
  # rubocop:disable Metrics/ClassLength
18
18
  class Span < OpenTelemetry::Trace::Span
19
+ DEFAULT_STATUS = OpenTelemetry::Trace::Status.new(OpenTelemetry::Trace::Status::UNSET)
20
+
21
+ private_constant(:DEFAULT_STATUS)
22
+
19
23
  # The following readers are intended for the use of SpanProcessors and
20
24
  # should not be considered part of the public interface for instrumentation.
21
- attr_reader :name, :status, :kind, :parent_span_id, :start_timestamp, :end_timestamp, :links, :library_resource, :instrumentation_library
25
+ attr_reader :name, :status, :kind, :parent_span_id, :start_timestamp, :end_timestamp, :links, :resource, :instrumentation_library
22
26
 
23
27
  # Return a frozen copy of the current attributes. This is intended for
24
- # use of SpanProcesses and should not be considered part of the public
28
+ # use of SpanProcessors and should not be considered part of the public
25
29
  # interface for instrumentation.
26
30
  #
27
31
  # @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] may be nil.
@@ -48,7 +52,7 @@ module OpenTelemetry
48
52
  # like events with the #add_event operation and attributes using
49
53
  # #set_attribute.
50
54
  def recording?
51
- true
55
+ !@ended
52
56
  end
53
57
 
54
58
  # Set attribute
@@ -59,7 +63,7 @@ module OpenTelemetry
59
63
  # meanings.
60
64
  #
61
65
  # @param [String] key
62
- # @param [String, Boolean, Numeric] value
66
+ # @param [String, Boolean, Numeric, Array<String, Numeric, Boolean>] value
63
67
  #
64
68
  # @return [self] returns itself
65
69
  def set_attribute(key, value)
@@ -76,37 +80,29 @@ module OpenTelemetry
76
80
  end
77
81
  self
78
82
  end
83
+ alias []= set_attribute
79
84
 
80
- # Add an Event to a {Span}. This can be accomplished eagerly or lazily.
81
- # Lazy evaluation is useful when the event attributes are expensive to
82
- # build and where the cost can be avoided for an unsampled {Span}.
83
- #
84
- # Eager example:
85
- #
86
- # span.add_event(name: 'event', attributes: {'eager' => true})
85
+ # Add an Event to a {Span}.
87
86
  #
88
- # Lazy example:
87
+ # Example:
89
88
  #
90
- # span.add_event { OpenTelemetry::Trace::Event.new(name: 'event', attributes: {'eager' => false}) }
89
+ # span.add_event('event', attributes: {'eager' => true})
91
90
  #
92
91
  # Note that the OpenTelemetry project
93
92
  # {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
94
93
  # documents} certain "standard event names and keys" which have
95
94
  # prescribed semantic meanings.
96
95
  #
97
- # @param [optional String] name Optional name of the event. This is
98
- # required if a block is not given.
96
+ # @param [String] name Name of the event.
99
97
  # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
100
98
  # One or more key:value pairs, where the keys must be strings and the
101
- # values may be string, boolean or numeric type. This argument should
102
- # only be used when passing in a name.
99
+ # values may be string, boolean or numeric type.
103
100
  # @param [optional Time] timestamp Optional timestamp for the event.
104
- # This argument should only be used when passing in a name.
105
101
  #
106
102
  # @return [self] returns itself
107
- def add_event(name: nil, attributes: nil, timestamp: nil)
103
+ def add_event(name, attributes: nil, timestamp: nil)
108
104
  super
109
- event = block_given? ? yield : OpenTelemetry::Trace::Event.new(name: name, attributes: attributes, timestamp: timestamp || Time.now)
105
+ event = Event.new(name: name, attributes: attributes, timestamp: timestamp || Time.now)
110
106
 
111
107
  @mutex.synchronize do
112
108
  if @ended
@@ -120,18 +116,18 @@ module OpenTelemetry
120
116
  self
121
117
  end
122
118
 
123
- # Record an error during the execution of this span. Multiple errors
119
+ # Record an exception during the execution of this span. Multiple exceptions
124
120
  # can be recorded on a span.
125
121
  #
126
- # @param [Exception] error The error to be recorded
122
+ # @param [Exception] exception The exception to be recorded
127
123
  #
128
124
  # @return [void]
129
- def record_error(error)
130
- add_event(name: 'error',
125
+ def record_exception(exception)
126
+ add_event('exception',
131
127
  attributes: {
132
- 'error.type' => error.class.to_s,
133
- 'error.message' => error.message,
134
- 'error.stack' => error.backtrace.join("\n")
128
+ 'exception.type' => exception.class.to_s,
129
+ 'exception.message' => exception.message,
130
+ 'exception.stacktrace' => exception.full_message(highlight: false, order: :top)
135
131
  })
136
132
  end
137
133
 
@@ -227,7 +223,6 @@ module OpenTelemetry
227
223
  @kind,
228
224
  @status,
229
225
  @parent_span_id,
230
- @child_count,
231
226
  @total_recorded_attributes,
232
227
  @total_recorded_events,
233
228
  @total_recorded_links,
@@ -236,7 +231,7 @@ module OpenTelemetry
236
231
  @attributes,
237
232
  @links,
238
233
  @events,
239
- @library_resource,
234
+ @resource,
240
235
  @instrumentation_library,
241
236
  context.span_id,
242
237
  context.trace_id,
@@ -246,7 +241,7 @@ module OpenTelemetry
246
241
  end
247
242
 
248
243
  # @api private
249
- def initialize(context, name, kind, parent_span_id, trace_config, span_processor, attributes, links, start_timestamp, library_resource, instrumentation_library) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
244
+ def initialize(context, parent_context, name, kind, parent_span_id, trace_config, span_processor, attributes, links, start_timestamp, resource, instrumentation_library) # rubocop:disable Metrics/AbcSize
250
245
  super(span_context: context)
251
246
  @mutex = Mutex.new
252
247
  @name = name
@@ -254,11 +249,10 @@ module OpenTelemetry
254
249
  @parent_span_id = parent_span_id.freeze || OpenTelemetry::Trace::INVALID_SPAN_ID
255
250
  @trace_config = trace_config
256
251
  @span_processor = span_processor
257
- @library_resource = library_resource
252
+ @resource = resource
258
253
  @instrumentation_library = instrumentation_library
259
254
  @ended = false
260
- @status = nil
261
- @child_count = 0
255
+ @status = DEFAULT_STATUS
262
256
  @total_recorded_events = 0
263
257
  @total_recorded_links = links&.size || 0
264
258
  @total_recorded_attributes = attributes&.size || 0
@@ -268,7 +262,7 @@ module OpenTelemetry
268
262
  trim_span_attributes(@attributes)
269
263
  @events = nil
270
264
  @links = trim_links(links, trace_config.max_links_count, trace_config.max_attributes_per_link)
271
- @span_processor.on_start(self)
265
+ @span_processor.on_start(self, parent_context)
272
266
  end
273
267
 
274
268
  # TODO: Java implementation overrides finalize to log if a span isn't finished.
@@ -300,7 +294,7 @@ module OpenTelemetry
300
294
  attrs.keep_if { |key, value| Internal.valid_key?(key) && Internal.valid_value?(value) }
301
295
  excess = attrs.size - max_attributes_per_link
302
296
  excess.times { attrs.shift } if excess.positive?
303
- OpenTelemetry::Trace::Link.new(link.context, attrs)
297
+ OpenTelemetry::Trace::Link.new(link.span_context, attrs)
304
298
  end.freeze
305
299
  end
306
300
 
@@ -325,7 +319,7 @@ module OpenTelemetry
325
319
  attrs.keep_if { |key, value| Internal.valid_key?(key) && Internal.valid_value?(value) }
326
320
  excess = attrs.size - max_attributes_per_event
327
321
  excess.times { attrs.shift } if excess.positive?
328
- event = OpenTelemetry::Trace::Event.new(name: event.name, attributes: attrs, timestamp: event.timestamp)
322
+ event = Event.new(name: event.name, attributes: attrs, timestamp: event.timestamp)
329
323
  end
330
324
  events << event
331
325
  end