opentelemetry-sdk 0.5.1

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 (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,18 @@
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
+ # The Config module contains the configuration logic for the
11
+ # OpenTelemetry SDK.
12
+ module Config
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ require 'opentelemetry/sdk/trace/config/trace_config'
@@ -0,0 +1,77 @@
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 Config
11
+ # Class that holds global trace parameters.
12
+ class TraceConfig
13
+ DEFAULT_SAMPLER = Samplers::ALWAYS_ON
14
+ DEFAULT_MAX_ATTRIBUTES_COUNT = 32
15
+ DEFAULT_MAX_EVENTS_COUNT = 128
16
+ DEFAULT_MAX_LINKS_COUNT = 32
17
+ DEFAULT_MAX_ATTRIBUTES_PER_EVENT = 32
18
+ DEFAULT_MAX_ATTRIBUTES_PER_LINK = 32
19
+
20
+ private_constant(:DEFAULT_SAMPLER,
21
+ :DEFAULT_MAX_ATTRIBUTES_COUNT,
22
+ :DEFAULT_MAX_EVENTS_COUNT,
23
+ :DEFAULT_MAX_LINKS_COUNT,
24
+ :DEFAULT_MAX_ATTRIBUTES_PER_EVENT,
25
+ :DEFAULT_MAX_ATTRIBUTES_PER_LINK)
26
+
27
+ # The global default sampler (see {Samplers}).
28
+ attr_reader :sampler
29
+
30
+ # The global default max number of attributes per {Span}.
31
+ attr_reader :max_attributes_count
32
+
33
+ # The global default max number of {OpenTelemetry::Trace::Event}s per {Span}.
34
+ attr_reader :max_events_count
35
+
36
+ # The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}.
37
+ attr_reader :max_links_count
38
+
39
+ # The global default max number of attributes per {OpenTelemetry::Trace::Event}.
40
+ attr_reader :max_attributes_per_event
41
+
42
+ # The global default max number of attributes per {OpenTelemetry::Trace::Link}.
43
+ attr_reader :max_attributes_per_link
44
+
45
+ # Returns a {TraceConfig} with the desired values.
46
+ #
47
+ # @return [TraceConfig] with the desired values.
48
+ # @raise [ArgumentError] if any of the max numbers are not positive.
49
+ def initialize(sampler: DEFAULT_SAMPLER,
50
+ max_attributes_count: DEFAULT_MAX_ATTRIBUTES_COUNT,
51
+ max_events_count: DEFAULT_MAX_EVENTS_COUNT,
52
+ max_links_count: DEFAULT_MAX_LINKS_COUNT,
53
+ max_attributes_per_event: DEFAULT_MAX_ATTRIBUTES_PER_EVENT,
54
+ max_attributes_per_link: DEFAULT_MAX_ATTRIBUTES_PER_LINK)
55
+ raise ArgumentError, 'max_attributes_count must be positive' unless max_attributes_count.positive?
56
+ raise ArgumentError, 'max_events_count must be positive' unless max_events_count.positive?
57
+ raise ArgumentError, 'max_links_count must be positive' unless max_links_count.positive?
58
+ raise ArgumentError, 'max_attributes_per_event must be positive' unless max_attributes_per_event.positive?
59
+ raise ArgumentError, 'max_attributes_per_link must be positive' unless max_attributes_per_link.positive?
60
+
61
+ @sampler = sampler
62
+ @max_attributes_count = max_attributes_count
63
+ @max_events_count = max_events_count
64
+ @max_links_count = max_links_count
65
+ @max_attributes_per_event = max_attributes_per_event
66
+ @max_attributes_per_link = max_attributes_per_link
67
+ end
68
+
69
+ # TODO: from_proto
70
+
71
+ # The default {TraceConfig}.
72
+ DEFAULT = new
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,30 @@
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
+ # The Export module contains the built-in exporters for the OpenTelemetry
11
+ # reference implementation.
12
+ module Export
13
+ # Result codes for the SpanExporter#export method.
14
+
15
+ # The export operation finished successfully.
16
+ SUCCESS = 0
17
+
18
+ # The export operation finished with an error.
19
+ FAILURE = 1
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ require 'opentelemetry/sdk/trace/export/batch_span_processor'
26
+ require 'opentelemetry/sdk/trace/export/console_span_exporter'
27
+ require 'opentelemetry/sdk/trace/export/in_memory_span_exporter'
28
+ require 'opentelemetry/sdk/trace/export/multi_span_exporter'
29
+ require 'opentelemetry/sdk/trace/export/noop_span_exporter'
30
+ require 'opentelemetry/sdk/trace/export/simple_span_processor'
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'timeout'
8
+
9
+ module OpenTelemetry
10
+ module SDK
11
+ module Trace
12
+ module Export
13
+ # Implementation of the duck type SpanProcessor that batches spans
14
+ # exported by the SDK then pushes them to the exporter pipeline.
15
+ #
16
+ # All spans reported by the SDK implementation are first added to a
17
+ # synchronized queue (with a {max_queue_size} maximum size, after the
18
+ # size is reached spans are dropped) and exported every
19
+ # schedule_delay_millis to the exporter pipeline in batches of
20
+ # max_export_batch_size.
21
+ #
22
+ # If the queue gets half full a preemptive notification is sent to the
23
+ # worker thread that exports the spans to wake up and start a new
24
+ # export cycle.
25
+ class BatchSpanProcessor
26
+ EXPORTER_TIMEOUT_MILLIS = 30_000
27
+ SCHEDULE_DELAY_MILLIS = 5_000
28
+ MAX_QUEUE_SIZE = 2048
29
+ MAX_EXPORT_BATCH_SIZE = 512
30
+ private_constant(:SCHEDULE_DELAY_MILLIS, :MAX_QUEUE_SIZE, :MAX_EXPORT_BATCH_SIZE)
31
+
32
+ def initialize(exporter:,
33
+ exporter_timeout_millis: EXPORTER_TIMEOUT_MILLIS,
34
+ schedule_delay_millis: SCHEDULE_DELAY_MILLIS,
35
+ max_queue_size: MAX_QUEUE_SIZE,
36
+ max_export_batch_size: MAX_EXPORT_BATCH_SIZE)
37
+ raise ArgumentError if max_export_batch_size > max_queue_size
38
+
39
+ @exporter = exporter
40
+ @exporter_timeout_seconds = exporter_timeout_millis / 1000.0
41
+ @mutex = Mutex.new
42
+ @condition = ConditionVariable.new
43
+ @keep_running = true
44
+ @delay_seconds = schedule_delay_millis / 1000.0
45
+ @max_queue_size = max_queue_size
46
+ @batch_size = max_export_batch_size
47
+ @spans = []
48
+ @thread = Thread.new { work }
49
+ end
50
+
51
+ # does nothing for this processor
52
+ def on_start(span)
53
+ # noop
54
+ end
55
+
56
+ # adds a span to the batcher, threadsafe may block on lock
57
+ def on_finish(span) # rubocop:disable Metrics/AbcSize
58
+ return unless span.context.trace_flags.sampled?
59
+
60
+ lock do
61
+ n = spans.size + 1 - max_queue_size
62
+ spans.shift(n) if n.positive?
63
+ spans << span
64
+ @condition.signal if spans.size > max_queue_size / 2
65
+ end
66
+ end
67
+
68
+ # TODO: test this explicitly.
69
+ # Export all ended spans to the configured `Exporter` that have not yet
70
+ # been exported.
71
+ #
72
+ # This method should only be called in cases where it is absolutely
73
+ # necessary, such as when using some FaaS providers that may suspend
74
+ # the process after an invocation, but before the `Processor` exports
75
+ # the completed spans.
76
+ def force_flush
77
+ snapshot = lock { spans.shift(spans.size) }
78
+ until snapshot.empty?
79
+ batch = snapshot.shift(@batch_size).map!(&:to_span_data)
80
+ result_code = @exporter.export(batch)
81
+ report_result(result_code, batch)
82
+ end
83
+ end
84
+
85
+ # shuts the consumer thread down and flushes the current accumulated buffer
86
+ # will block until the thread is finished
87
+ def shutdown
88
+ lock do
89
+ @keep_running = false
90
+ @condition.signal
91
+ end
92
+
93
+ @thread.join
94
+ force_flush
95
+ @exporter.shutdown
96
+ end
97
+
98
+ private
99
+
100
+ attr_reader :spans, :max_queue_size, :batch_size
101
+
102
+ def work
103
+ loop do
104
+ batch = lock do
105
+ @condition.wait(@mutex, @delay_seconds) if spans.size < batch_size && @keep_running
106
+ @condition.wait(@mutex, @delay_seconds) while spans.empty? && @keep_running
107
+ return unless @keep_running
108
+
109
+ fetch_batch
110
+ end
111
+
112
+ export_batch(batch)
113
+ end
114
+ end
115
+
116
+ def export_batch(batch)
117
+ result_code = export_with_timeout(batch)
118
+ report_result(result_code, batch)
119
+ end
120
+
121
+ def export_with_timeout(batch)
122
+ Timeout.timeout(@exporter_timeout_seconds) { @exporter.export(batch) }
123
+ rescue Timeout::Error
124
+ FAILURE
125
+ end
126
+
127
+ def report_result(result_code, batch)
128
+ OpenTelemetry.logger.error("Unable to export #{batch.size} spans") unless result_code == SUCCESS
129
+ end
130
+
131
+ def fetch_batch
132
+ spans.shift(@batch_size).map!(&:to_span_data)
133
+ end
134
+
135
+ def lock
136
+ @mutex.synchronize do
137
+ yield
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'pp'
8
+
9
+ module OpenTelemetry
10
+ module SDK
11
+ module Trace
12
+ module Export
13
+ # Outputs {SpanData} to the console.
14
+ #
15
+ # Potentially useful for exploratory purposes.
16
+ class ConsoleSpanExporter
17
+ ResultCodes = OpenTelemetry::SDK::Trace::Export
18
+
19
+ private_constant(:ResultCodes)
20
+
21
+ def initialize
22
+ @stopped = false
23
+ end
24
+
25
+ def export(spans)
26
+ return ResultCodes::FAILURE if @stopped
27
+
28
+ Array(spans).each { |s| pp s }
29
+
30
+ ResultCodes::SUCCESS
31
+ end
32
+
33
+ def shutdown
34
+ @stopped = true
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,86 @@
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 SpanExporter implementation that can be used to test OpenTelemetry integration.
12
+ #
13
+ # Example usage:
14
+ #
15
+ # class MyClassTest
16
+ # def setup
17
+ # @tracer_provider = TracerProvider.new
18
+ # @exporter = InMemorySpanExporter.new
19
+ # @tracer_provider.add_span_processor(SimpleSampledSpansProcessor.new(@exporter))
20
+ # end
21
+ #
22
+ # def test_finished_spans
23
+ # @tracer_provider.tracer.in_span("span") {}
24
+ #
25
+ # spans = @exporter.finished_spans
26
+ # spans.wont_be_nil
27
+ # spans.size.must_equal(1)
28
+ # spans[0].name.must_equal("span")
29
+ # end
30
+ class InMemorySpanExporter
31
+ # Returns a new instance of the {InMemorySpanExporter}.
32
+ #
33
+ # @return a new instance of the {InMemorySpanExporter}.
34
+ def initialize
35
+ @finished_spans = []
36
+ @stopped = false
37
+ @mutex = Mutex.new
38
+ end
39
+
40
+ # Returns a frozen array of the finished {SpanData}s, represented by
41
+ # {io.opentelemetry.proto.trace.v1.Span}.
42
+ #
43
+ # @return [Array<SpanData>] a frozen array of the finished {SpanData}s.
44
+ def finished_spans
45
+ @mutex.synchronize do
46
+ @finished_spans.clone.freeze
47
+ end
48
+ end
49
+
50
+ # Clears the internal collection of finished {Span}s.
51
+ #
52
+ # Does not reset the state of this exporter if already shutdown.
53
+ def reset
54
+ @mutex.synchronize do
55
+ @finished_spans.clear
56
+ end
57
+ end
58
+
59
+ # Called to export sampled {SpanData}s.
60
+ #
61
+ # @param [Enumerable<SpanData>] span_datas the list of sampled {SpanData}s to be
62
+ # exported.
63
+ # @return [Integer] the result of the export, SUCCESS or
64
+ # FAILURE
65
+ def export(span_datas)
66
+ @mutex.synchronize do
67
+ return FAILURE if @stopped
68
+
69
+ @finished_spans.concat(span_datas.to_a)
70
+ end
71
+ SUCCESS
72
+ end
73
+
74
+ # Called when {TracerProvider#shutdown} is called, if this exporter is
75
+ # registered to a {TracerProvider} object.
76
+ def shutdown
77
+ @mutex.synchronize do
78
+ @finished_spans.clear
79
+ @stopped = true
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,58 @@
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
+ # Implementation of the SpanExporter duck type that simply forwards all
12
+ # received spans to a collection of SpanExporters.
13
+ #
14
+ # Can be used to export to multiple backends using the same
15
+ # SpanProcessor like a {SimpleSpanProcessor} or a
16
+ # {BatchSpanProcessor}.
17
+ class MultiSpanExporter
18
+ def initialize(span_exporters)
19
+ @span_exporters = span_exporters.clone.freeze
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
+ @span_exporters.inject(SUCCESS) do |result_code, span_exporter|
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
33
+ end
34
+ end
35
+
36
+ # Called when {TracerProvider#shutdown} is called, if this exporter is
37
+ # registered to a {TracerProvider} object.
38
+ def shutdown
39
+ @span_exporters.each(&:shutdown)
40
+ end
41
+
42
+ private
43
+
44
+ # Returns a merged error code, see the rules in the code.
45
+ def merge_result_code(result_code, new_result_code)
46
+ if result_code == SUCCESS && new_result_code == SUCCESS
47
+ # If both errors are success then return success.
48
+ SUCCESS
49
+ else
50
+ # At this point at least one of the code is FAILURE, so return FAILURE.
51
+ FAILURE
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end