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.
- checksums.yaml +7 -0
- data/.yardopts +9 -0
- data/CHANGELOG.md +1 -0
- data/LICENSE +201 -0
- data/README.md +73 -0
- data/lib/opentelemetry-sdk.rb +7 -0
- data/lib/opentelemetry/sdk.rb +69 -0
- data/lib/opentelemetry/sdk/configurator.rb +171 -0
- data/lib/opentelemetry/sdk/correlation_context.rb +16 -0
- data/lib/opentelemetry/sdk/correlation_context/builder.rb +40 -0
- data/lib/opentelemetry/sdk/correlation_context/manager.rb +87 -0
- data/lib/opentelemetry/sdk/instrumentation_library.rb +13 -0
- data/lib/opentelemetry/sdk/internal.rb +52 -0
- data/lib/opentelemetry/sdk/resources.rb +16 -0
- data/lib/opentelemetry/sdk/resources/constants.rb +124 -0
- data/lib/opentelemetry/sdk/resources/resource.rb +84 -0
- data/lib/opentelemetry/sdk/trace.rb +24 -0
- data/lib/opentelemetry/sdk/trace/config.rb +18 -0
- data/lib/opentelemetry/sdk/trace/config/trace_config.rb +77 -0
- data/lib/opentelemetry/sdk/trace/export.rb +30 -0
- data/lib/opentelemetry/sdk/trace/export/batch_span_processor.rb +144 -0
- data/lib/opentelemetry/sdk/trace/export/console_span_exporter.rb +40 -0
- data/lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb +86 -0
- data/lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb +58 -0
- data/lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb +42 -0
- data/lib/opentelemetry/sdk/trace/export/simple_span_processor.rb +72 -0
- data/lib/opentelemetry/sdk/trace/multi_span_processor.rb +62 -0
- data/lib/opentelemetry/sdk/trace/noop_span_processor.rb +50 -0
- data/lib/opentelemetry/sdk/trace/samplers.rb +90 -0
- data/lib/opentelemetry/sdk/trace/samplers/constant_sampler.rb +33 -0
- data/lib/opentelemetry/sdk/trace/samplers/decision.rb +26 -0
- data/lib/opentelemetry/sdk/trace/samplers/parent_or_else.rb +43 -0
- data/lib/opentelemetry/sdk/trace/samplers/probability_sampler.rb +64 -0
- data/lib/opentelemetry/sdk/trace/samplers/result.rb +55 -0
- data/lib/opentelemetry/sdk/trace/span.rb +336 -0
- data/lib/opentelemetry/sdk/trace/span_data.rb +34 -0
- data/lib/opentelemetry/sdk/trace/tracer.rb +78 -0
- data/lib/opentelemetry/sdk/trace/tracer_provider.rb +84 -0
- data/lib/opentelemetry/sdk/version.rb +12 -0
- 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
|