opentelemetry-sdk 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +1 -0
  4. data/LICENSE +201 -0
  5. data/README.md +73 -0
  6. data/lib/opentelemetry-sdk.rb +7 -0
  7. data/lib/opentelemetry/sdk.rb +69 -0
  8. data/lib/opentelemetry/sdk/configurator.rb +171 -0
  9. data/lib/opentelemetry/sdk/correlation_context.rb +16 -0
  10. data/lib/opentelemetry/sdk/correlation_context/builder.rb +40 -0
  11. data/lib/opentelemetry/sdk/correlation_context/manager.rb +87 -0
  12. data/lib/opentelemetry/sdk/instrumentation_library.rb +13 -0
  13. data/lib/opentelemetry/sdk/internal.rb +52 -0
  14. data/lib/opentelemetry/sdk/resources.rb +16 -0
  15. data/lib/opentelemetry/sdk/resources/constants.rb +124 -0
  16. data/lib/opentelemetry/sdk/resources/resource.rb +84 -0
  17. data/lib/opentelemetry/sdk/trace.rb +24 -0
  18. data/lib/opentelemetry/sdk/trace/config.rb +18 -0
  19. data/lib/opentelemetry/sdk/trace/config/trace_config.rb +77 -0
  20. data/lib/opentelemetry/sdk/trace/export.rb +30 -0
  21. data/lib/opentelemetry/sdk/trace/export/batch_span_processor.rb +144 -0
  22. data/lib/opentelemetry/sdk/trace/export/console_span_exporter.rb +40 -0
  23. data/lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb +86 -0
  24. data/lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb +58 -0
  25. data/lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb +42 -0
  26. data/lib/opentelemetry/sdk/trace/export/simple_span_processor.rb +72 -0
  27. data/lib/opentelemetry/sdk/trace/multi_span_processor.rb +62 -0
  28. data/lib/opentelemetry/sdk/trace/noop_span_processor.rb +50 -0
  29. data/lib/opentelemetry/sdk/trace/samplers.rb +90 -0
  30. data/lib/opentelemetry/sdk/trace/samplers/constant_sampler.rb +33 -0
  31. data/lib/opentelemetry/sdk/trace/samplers/decision.rb +26 -0
  32. data/lib/opentelemetry/sdk/trace/samplers/parent_or_else.rb +43 -0
  33. data/lib/opentelemetry/sdk/trace/samplers/probability_sampler.rb +64 -0
  34. data/lib/opentelemetry/sdk/trace/samplers/result.rb +55 -0
  35. data/lib/opentelemetry/sdk/trace/span.rb +336 -0
  36. data/lib/opentelemetry/sdk/trace/span_data.rb +34 -0
  37. data/lib/opentelemetry/sdk/trace/tracer.rb +78 -0
  38. data/lib/opentelemetry/sdk/trace/tracer_provider.rb +84 -0
  39. data/lib/opentelemetry/sdk/version.rb +12 -0
  40. metadata +207 -0
@@ -0,0 +1,42 @@
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 Export
11
+ # A noop exporter that demonstrates and documents the SpanExporter
12
+ # duck type. SpanExporter allows different tracing services to export
13
+ # recorded data for sampled spans in their own format.
14
+ #
15
+ # To export data an exporter MUST be registered to the {TracerProvider} using
16
+ # a {SimpleSpanProcessor} or a {BatchSpanProcessor}.
17
+ class NoopSpanExporter
18
+ def initialize
19
+ @stopped = false
20
+ end
21
+
22
+ # Called to export sampled {Span}s.
23
+ #
24
+ # @param [Enumerable<Span>] spans the list of sampled {Span}s to be
25
+ # exported.
26
+ # @return [Integer] the result of the export.
27
+ def export(spans)
28
+ return SUCCESS unless @stopped
29
+
30
+ FAILURE
31
+ end
32
+
33
+ # Called when {TracerProvider#shutdown} is called, if this exporter is
34
+ # registered to a {TracerProvider} object.
35
+ def shutdown
36
+ @stopped = true
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,72 @@
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 Export
11
+ # An implementation of the duck type SpanProcessor that converts the
12
+ # {Span} to {io.opentelemetry.proto.trace.v1.Span} and passes it to the
13
+ # configured exporter.
14
+ #
15
+ # Only spans that are recorded are converted, {OpenTelemetry::Trace::Span#is_recording?} must
16
+ # return true.
17
+ class SimpleSpanProcessor
18
+ # Returns a new {SimpleSpanProcessor} that converts spans to
19
+ # proto and forwards them to the given span_exporter.
20
+ #
21
+ # @param span_exporter the (duck type) SpanExporter to where the
22
+ # recorded Spans are pushed.
23
+ # @return [SimpleSpanProcessor]
24
+ # @raise ArgumentError if the span_exporter is nil.
25
+ def initialize(span_exporter)
26
+ @span_exporter = span_exporter
27
+ end
28
+
29
+ # Called when a {Span} is started, if the {Span#recording?}
30
+ # returns true.
31
+ #
32
+ # This method is called synchronously on the execution thread, should
33
+ # not throw or block the execution thread.
34
+ #
35
+ # @param [Span] span the {Span} that just started.
36
+ def on_start(span)
37
+ # Do nothing.
38
+ end
39
+
40
+ # Called when a {Span} is ended, if the {Span#recording?}
41
+ # returns true.
42
+ #
43
+ # This method is called synchronously on the execution thread, should
44
+ # not throw or block the execution thread.
45
+ #
46
+ # @param [Span] span the {Span} that just ended.
47
+ def on_finish(span)
48
+ return unless span.context.trace_flags.sampled?
49
+
50
+ @span_exporter&.export([span.to_span_data])
51
+ rescue => e # rubocop:disable Style/RescueStandardError
52
+ OpenTelemetry.logger.error("unexpected error in span.on_finish - #{e}")
53
+ end
54
+
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.
65
+ def shutdown
66
+ @span_exporter&.shutdown
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,62 @@
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
+ # Implementation of the SpanProcessor duck type that simply forwards all
11
+ # received events to a list of SpanProcessors.
12
+ class MultiSpanProcessor
13
+ # Creates a new {MultiSpanProcessor}.
14
+ #
15
+ # @param [Enumerable<SpanProcessor>] span_processors a collection of
16
+ # SpanProcessors.
17
+ # @return [MultiSpanProcessor]
18
+ def initialize(span_processors)
19
+ @span_processors = span_processors.to_a.freeze
20
+ end
21
+
22
+ # Called when a {Span} is started, if the {Span#recording?}
23
+ # returns true.
24
+ #
25
+ # This method is called synchronously on the execution thread, should
26
+ # not throw or block the execution thread.
27
+ #
28
+ # @param [Span] span the {Span} that just started.
29
+ def on_start(span)
30
+ @span_processors.each { |processor| processor.on_start(span) }
31
+ end
32
+
33
+ # Called when a {Span} is ended, if the {Span#recording?}
34
+ # returns true.
35
+ #
36
+ # This method is called synchronously on the execution thread, should
37
+ # not throw or block the execution thread.
38
+ #
39
+ # @param [Span] span the {Span} that just ended.
40
+ def on_finish(span)
41
+ @span_processors.each { |processor| processor.on_finish(span) }
42
+ end
43
+
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.
56
+ def shutdown
57
+ @span_processors.each(&:shutdown)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'singleton'
8
+
9
+ module OpenTelemetry
10
+ module SDK
11
+ module Trace
12
+ # NoopSpanProcessor is a singleton implementation of the duck type
13
+ # SpanProcessor that provides synchronous no-op hooks for when a
14
+ # {Span} is started or when a {Span} is ended.
15
+ class NoopSpanProcessor
16
+ include Singleton
17
+
18
+ # Called when a {Span} is started, if the {Span#recording?}
19
+ # returns true.
20
+ #
21
+ # This method is called synchronously on the execution thread, should
22
+ # not throw or block the execution thread.
23
+ #
24
+ # @param [Span] span the {Span} that just started.
25
+ def on_start(span); end
26
+
27
+ # Called when a {Span} is ended, if the {Span#recording?}
28
+ # returns true.
29
+ #
30
+ # This method is called synchronously on the execution thread, should
31
+ # not throw or block the execution thread.
32
+ #
33
+ # @param [Span] span the {Span} that just ended.
34
+ def on_finish(span); end
35
+
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.
46
+ def shutdown; end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'opentelemetry/sdk/trace/samplers/decision'
8
+ require 'opentelemetry/sdk/trace/samplers/result'
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'
12
+
13
+ module OpenTelemetry
14
+ module SDK
15
+ module Trace
16
+ # The Samplers module contains the sampling logic for OpenTelemetry. The
17
+ # reference implementation provides a {ProbabilitySampler}, {ALWAYS_ON},
18
+ # {ALWAYS_OFF}, and {ParentOrElse}.
19
+ #
20
+ # Custom samplers can be provided by SDK users. The required interface is:
21
+ #
22
+ # should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:) -> Result
23
+ # description -> String
24
+ #
25
+ # Where:
26
+ #
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.
31
+ # @param [Enumerable<Link>] links A collection of links to be associated
32
+ # with the {Span} to be created. Can be nil.
33
+ # @param [String] name Name of the {Span} to be created.
34
+ # @param [Symbol] kind The {OpenTelemetry::Trace::SpanKind} of the {Span}
35
+ # to be created. Can be nil.
36
+ # @param [Hash<String, Object>] attributes Attributes to be attached
37
+ # to the {Span} to be created. Can be nil.
38
+ # @return [Result] The sampling result.
39
+ 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
45
+
46
+ private_constant(:RECORD_AND_SAMPLED, :NOT_RECORD, :RECORD, :SAMPLING_HINTS, :APPLY_PROBABILITY_TO_SYMBOLS)
47
+
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.
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)
61
+ end
62
+
63
+ # Returns a new sampler. The probability of sampling a trace is equal
64
+ # to that of the specified probability.
65
+ #
66
+ # @param [Numeric] probability The desired probability of sampling.
67
+ # 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)
81
+
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
+ end
87
+ end
88
+ end
89
+ end
90
+ 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
@@ -0,0 +1,26 @@
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
+ # The Decision module contains a set of constants to be used in the
12
+ # decision part of a sampling {Result}.
13
+ module Decision
14
+ # Decision to not record events and not sample.
15
+ NOT_RECORD = :__not_record__
16
+
17
+ # Decision to record events and not sample.
18
+ RECORD = :__record__
19
+
20
+ # Decision to record events and sample.
21
+ RECORD_AND_SAMPLED = :__record_and_sampled__
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,43 @@
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. It either respects the parent span's sampling
14
+ # decision or delegates to delegate_sampler for root spans.
15
+ class ParentOrElse
16
+ def initialize(delegate_sampler)
17
+ @delegate_sampler = delegate_sampler
18
+ end
19
+
20
+ # @api private
21
+ #
22
+ # See {Samplers}.
23
+ def description
24
+ "ParentOrElse{#{@delegate_sampler.description}}"
25
+ end
26
+
27
+ # @api private
28
+ #
29
+ # See {Samplers}.
30
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
31
+ if parent_context.nil?
32
+ @delegate_sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
33
+ elsif parent_context.trace_flags.sampled?
34
+ RECORD_AND_SAMPLED
35
+ else
36
+ NOT_RECORD
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,64 @@
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 ProbabilitySampler
15
+ attr_reader :description
16
+
17
+ def initialize(probability, ignore_parent:, apply_to_remote_parent:, apply_to_all_spans:)
18
+ @probability = probability
19
+ @id_upper_bound = (probability * (2**64 - 1)).ceil
20
+ @use_parent_sampled_flag = !ignore_parent
21
+ @apply_to_remote_parent = apply_to_remote_parent
22
+ @apply_to_all_spans = apply_to_all_spans
23
+ @description = format('ProbabilitySampler{%.6f}', probability)
24
+ end
25
+
26
+ # @api private
27
+ #
28
+ # See {Samplers}.
29
+ def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
30
+ # Ignored for sampling decision: links, name, kind, attributes.
31
+
32
+ if sample?(trace_id, parent_context)
33
+ RECORD_AND_SAMPLED
34
+ else
35
+ NOT_RECORD
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def sample?(trace_id, parent_context)
42
+ if parent_context.nil?
43
+ sample_trace_id?(trace_id)
44
+ else
45
+ parent_sampled?(parent_context) || sample_trace_id_for_child?(parent_context, trace_id)
46
+ end
47
+ end
48
+
49
+ def parent_sampled?(parent_context)
50
+ @use_parent_sampled_flag && parent_context.trace_flags.sampled?
51
+ end
52
+
53
+ def sample_trace_id_for_child?(parent_context, trace_id)
54
+ (@apply_to_all_spans || (@apply_to_remote_parent && parent_context.remote?)) && sample_trace_id?(trace_id)
55
+ end
56
+
57
+ def sample_trace_id?(trace_id)
58
+ @probability == 1.0 || trace_id[8, 8].unpack1('Q>') < @id_upper_bound
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end