opentelemetry-sdk 0.4.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +2 -2
- data/CHANGELOG.md +42 -0
- data/README.md +1 -1
- data/lib/opentelemetry/sdk.rb +4 -3
- data/lib/opentelemetry/sdk/baggage.rb +16 -0
- data/lib/opentelemetry/sdk/{correlation_context → baggage}/builder.rb +5 -5
- data/lib/opentelemetry/sdk/{correlation_context → baggage}/manager.rb +37 -27
- data/lib/opentelemetry/sdk/configurator.rb +73 -39
- data/lib/opentelemetry/sdk/instrumentation_library.rb +13 -0
- data/lib/opentelemetry/sdk/resources.rb +1 -0
- data/lib/opentelemetry/sdk/resources/constants.rb +120 -0
- data/lib/opentelemetry/sdk/resources/resource.rb +38 -19
- data/lib/opentelemetry/sdk/trace.rb +1 -0
- data/lib/opentelemetry/sdk/trace/config/trace_config.rb +3 -3
- data/lib/opentelemetry/sdk/trace/event.rb +48 -0
- data/lib/opentelemetry/sdk/trace/export.rb +9 -9
- data/lib/opentelemetry/sdk/trace/export/batch_span_processor.rb +49 -28
- data/lib/opentelemetry/sdk/trace/export/console_span_exporter.rb +3 -6
- data/lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb +6 -2
- data/lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb +7 -8
- data/lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb +2 -1
- data/lib/opentelemetry/sdk/trace/export/simple_span_processor.rb +13 -3
- data/lib/opentelemetry/sdk/trace/multi_span_processor.rb +12 -4
- data/lib/opentelemetry/sdk/trace/noop_span_processor.rb +15 -3
- data/lib/opentelemetry/sdk/trace/samplers.rb +52 -51
- data/lib/opentelemetry/sdk/trace/samplers/constant_sampler.rb +33 -0
- data/lib/opentelemetry/sdk/trace/samplers/decision.rb +3 -3
- data/lib/opentelemetry/sdk/trace/samplers/parent_based.rb +53 -0
- data/lib/opentelemetry/sdk/trace/samplers/result.rb +3 -3
- data/lib/opentelemetry/sdk/trace/samplers/trace_id_ratio_based.rb +45 -0
- data/lib/opentelemetry/sdk/trace/span.rb +33 -36
- data/lib/opentelemetry/sdk/trace/span_data.rb +18 -3
- data/lib/opentelemetry/sdk/trace/tracer.rb +36 -20
- data/lib/opentelemetry/sdk/trace/tracer_provider.rb +4 -4
- data/lib/opentelemetry/sdk/version.rb +1 -1
- metadata +19 -10
- data/lib/opentelemetry/sdk/correlation_context.rb +0 -16
- data/lib/opentelemetry/sdk/trace/samplers/probability_sampler.rb +0 -61
@@ -0,0 +1,13 @@
|
|
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
|
+
# InstrumentationLibrary is a struct containing library information for export.
|
10
|
+
InstrumentationLibrary = Struct.new(:name,
|
11
|
+
:version)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2020 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
module SDK
|
9
|
+
module Resources
|
10
|
+
module Constants
|
11
|
+
# Attributes describing a service instance.
|
12
|
+
SERVICE_RESOURCE = {
|
13
|
+
# Logical name of the service.
|
14
|
+
name: 'service.name',
|
15
|
+
|
16
|
+
# A namespace for `service.name`.
|
17
|
+
namespace: 'service.namespace',
|
18
|
+
|
19
|
+
# The string ID of the service instance.
|
20
|
+
instance_id: 'service.instance.id',
|
21
|
+
|
22
|
+
# The version string of the service API or implementation.
|
23
|
+
version: 'service.version'
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
# Attributes describing the telemetry library.
|
27
|
+
TELEMETRY_SDK_RESOURCE = {
|
28
|
+
# The name of the telemetry library.
|
29
|
+
name: 'telemetry.sdk.name',
|
30
|
+
|
31
|
+
# The language of the telemetry library and of the code instrumented with it.
|
32
|
+
language: 'telemetry.sdk.language',
|
33
|
+
|
34
|
+
# The version string of the telemetry library
|
35
|
+
version: 'telemetry.sdk.version'
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
# Attributes defining a compute unit (e.g. Container, Process, Lambda
|
39
|
+
# Function).
|
40
|
+
CONTAINER_RESOURCE = {
|
41
|
+
# The container name.
|
42
|
+
name: 'container.name',
|
43
|
+
|
44
|
+
# The name of the image the container was built on.
|
45
|
+
image_name: 'container.image.name',
|
46
|
+
|
47
|
+
# The container image tag.
|
48
|
+
image_tag: 'container.image.tag'
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
FAAS_RESOURCE = {
|
52
|
+
# The name of the function being executed.
|
53
|
+
name: 'faas.name',
|
54
|
+
|
55
|
+
# The unique name of the function being executed.
|
56
|
+
id: 'faas.id',
|
57
|
+
|
58
|
+
# The version string of the function being executed.
|
59
|
+
version: 'faas.version',
|
60
|
+
|
61
|
+
# The execution environment ID as a string.
|
62
|
+
instance: 'faas.instance'
|
63
|
+
}.freeze
|
64
|
+
|
65
|
+
# Attributes defining a deployment service (e.g. Kubernetes).
|
66
|
+
K8S_RESOURCE = {
|
67
|
+
# The name of the cluster that the pod is running in.
|
68
|
+
cluster_name: 'k8s.cluster.name',
|
69
|
+
|
70
|
+
# The name of the namespace that the pod is running in.
|
71
|
+
namespace_name: 'k8s.namespace.name',
|
72
|
+
|
73
|
+
# The name of the pod.
|
74
|
+
pod_name: 'k8s.pod.name',
|
75
|
+
|
76
|
+
# The name of the deployment.
|
77
|
+
deployment_name: 'k8s.deployment.name'
|
78
|
+
}.freeze
|
79
|
+
|
80
|
+
# Attributes defining a computing instance (e.g. host).
|
81
|
+
HOST_RESOURCE = {
|
82
|
+
# Unique host id. For Cloud this must be the instance_id assigned by the
|
83
|
+
# cloud provider
|
84
|
+
id: 'host.id',
|
85
|
+
|
86
|
+
# Name of the host. It may contain what hostname returns on Unix systems,
|
87
|
+
# the fully qualified, or a name specified by the user.
|
88
|
+
name: 'host.name',
|
89
|
+
|
90
|
+
# Type of host. For Cloud this must be the machine type.
|
91
|
+
type: 'host.type',
|
92
|
+
|
93
|
+
# Name of the VM image or OS install the host was instantiated from.
|
94
|
+
image_name: 'host.image.name',
|
95
|
+
|
96
|
+
# VM image id. For Cloud, this value is from the provider.
|
97
|
+
image_id: 'host.image.id',
|
98
|
+
|
99
|
+
# The version string of the VM image.
|
100
|
+
image_version: 'host.image.version'
|
101
|
+
}.freeze
|
102
|
+
|
103
|
+
# Attributes defining a running environment (e.g. Cloud, Data Center).
|
104
|
+
CLOUD_RESOURCE = {
|
105
|
+
# Name of the cloud provider. Example values are aws, azure, gcp.
|
106
|
+
provider: 'cloud.provider',
|
107
|
+
|
108
|
+
# The cloud account id used to identify different entities.
|
109
|
+
account_id: 'cloud.account.id',
|
110
|
+
|
111
|
+
# A specific geographical location where different entities can run.
|
112
|
+
region: 'cloud.region',
|
113
|
+
|
114
|
+
# Zones are a sub set of the region connected through low-latency links.
|
115
|
+
zone: 'cloud.zone'
|
116
|
+
}.freeze
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -13,21 +13,40 @@ module OpenTelemetry
|
|
13
13
|
class << self
|
14
14
|
private :new # rubocop:disable Style/AccessModifierDeclarations
|
15
15
|
|
16
|
-
# Returns a newly created {Resource} with the specified
|
16
|
+
# Returns a newly created {Resource} with the specified attributes
|
17
17
|
#
|
18
|
-
# @param [Hash{String => String, Numeric, Boolean}
|
19
|
-
# as
|
20
|
-
# @raise [ArgumentError] If
|
18
|
+
# @param [Hash{String => String, Numeric, Boolean} attributes Hash of key-value pairs to be used
|
19
|
+
# as attributes for this resource
|
20
|
+
# @raise [ArgumentError] If attribute keys and values are not strings
|
21
21
|
# @return [Resource]
|
22
|
-
def create(
|
23
|
-
|
24
|
-
raise ArgumentError, '
|
25
|
-
raise ArgumentError, '
|
22
|
+
def create(attributes = {})
|
23
|
+
frozen_attributes = attributes.each_with_object({}) do |(k, v), memo|
|
24
|
+
raise ArgumentError, 'attribute keys must be strings' unless k.is_a?(String)
|
25
|
+
raise ArgumentError, 'attribute values must be strings, integers, floats, or booleans' unless Internal.valid_value?(v)
|
26
26
|
|
27
27
|
memo[-k] = v.freeze
|
28
28
|
end.freeze
|
29
29
|
|
30
|
-
new(
|
30
|
+
new(frozen_attributes)
|
31
|
+
end
|
32
|
+
|
33
|
+
def telemetry_sdk
|
34
|
+
resource_attributes = {
|
35
|
+
Constants::TELEMETRY_SDK_RESOURCE[:name] => 'opentelemetry',
|
36
|
+
Constants::TELEMETRY_SDK_RESOURCE[:language] => 'ruby',
|
37
|
+
Constants::TELEMETRY_SDK_RESOURCE[:version] => OpenTelemetry::SDK::VERSION
|
38
|
+
}
|
39
|
+
|
40
|
+
resource_pairs = ENV['OTEL_RESOURCE_ATTRIBUTES']
|
41
|
+
return create(resource_attributes) unless resource_pairs.is_a?(String)
|
42
|
+
|
43
|
+
resource_pairs.split(',').each do |pair|
|
44
|
+
key, value = pair.split('=')
|
45
|
+
resource_attributes[key] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
resource_attributes.delete_if { |_key, value| value.nil? || value.empty? }
|
49
|
+
create(resource_attributes)
|
31
50
|
end
|
32
51
|
end
|
33
52
|
|
@@ -36,18 +55,18 @@ module OpenTelemetry
|
|
36
55
|
# Users should use the {create} factory method to obtain a {Resource}
|
37
56
|
# instance.
|
38
57
|
#
|
39
|
-
# @param [Hash<String, String>]
|
40
|
-
# key-value pairs to be used as
|
58
|
+
# @param [Hash<String, String>] frozen_attributes Frozen-hash of frozen-string
|
59
|
+
# key-value pairs to be used as attributes for this resource
|
41
60
|
# @return [Resource]
|
42
|
-
def initialize(
|
43
|
-
@
|
61
|
+
def initialize(frozen_attributes)
|
62
|
+
@attributes = frozen_attributes
|
44
63
|
end
|
45
64
|
|
46
|
-
# Returns an enumerator for
|
65
|
+
# Returns an enumerator for attributes of this {Resource}
|
47
66
|
#
|
48
67
|
# @return [Enumerator]
|
49
|
-
def
|
50
|
-
@
|
68
|
+
def attribute_enumerator
|
69
|
+
@attribute_enumerator ||= attributes.to_enum
|
51
70
|
end
|
52
71
|
|
53
72
|
# Returns a new, merged {Resource} by merging the current {Resource} with
|
@@ -60,16 +79,16 @@ module OpenTelemetry
|
|
60
79
|
def merge(other)
|
61
80
|
return self unless other.is_a?(Resource)
|
62
81
|
|
63
|
-
|
82
|
+
merged_attributes = attributes.merge(other.attributes) do |_, old_v, new_v|
|
64
83
|
old_v.empty? ? new_v : old_v
|
65
84
|
end
|
66
85
|
|
67
|
-
self.class.send(:new,
|
86
|
+
self.class.send(:new, merged_attributes.freeze)
|
68
87
|
end
|
69
88
|
|
70
89
|
protected
|
71
90
|
|
72
|
-
attr_reader :
|
91
|
+
attr_reader :attributes
|
73
92
|
end
|
74
93
|
end
|
75
94
|
end
|
@@ -15,6 +15,7 @@ end
|
|
15
15
|
|
16
16
|
require 'opentelemetry/sdk/trace/samplers'
|
17
17
|
require 'opentelemetry/sdk/trace/config'
|
18
|
+
require 'opentelemetry/sdk/trace/event'
|
18
19
|
require 'opentelemetry/sdk/trace/export'
|
19
20
|
require 'opentelemetry/sdk/trace/multi_span_processor'
|
20
21
|
require 'opentelemetry/sdk/trace/noop_span_processor'
|
@@ -10,7 +10,7 @@ module OpenTelemetry
|
|
10
10
|
module Config
|
11
11
|
# Class that holds global trace parameters.
|
12
12
|
class TraceConfig
|
13
|
-
DEFAULT_SAMPLER = Samplers::ALWAYS_ON
|
13
|
+
DEFAULT_SAMPLER = Samplers.parent_based(root: Samplers::ALWAYS_ON)
|
14
14
|
DEFAULT_MAX_ATTRIBUTES_COUNT = 32
|
15
15
|
DEFAULT_MAX_EVENTS_COUNT = 128
|
16
16
|
DEFAULT_MAX_LINKS_COUNT = 32
|
@@ -30,13 +30,13 @@ module OpenTelemetry
|
|
30
30
|
# The global default max number of attributes per {Span}.
|
31
31
|
attr_reader :max_attributes_count
|
32
32
|
|
33
|
-
# The global default max number of {OpenTelemetry::Trace::Event}s per {Span}.
|
33
|
+
# The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}.
|
34
34
|
attr_reader :max_events_count
|
35
35
|
|
36
36
|
# The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}.
|
37
37
|
attr_reader :max_links_count
|
38
38
|
|
39
|
-
# The global default max number of attributes per {OpenTelemetry::Trace::Event}.
|
39
|
+
# The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}.
|
40
40
|
attr_reader :max_attributes_per_event
|
41
41
|
|
42
42
|
# The global default max number of attributes per {OpenTelemetry::Trace::Link}.
|
@@ -0,0 +1,48 @@
|
|
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
|
+
# A text annotation with a set of attributes and a timestamp.
|
11
|
+
class Event
|
12
|
+
EMPTY_ATTRIBUTES = {}.freeze
|
13
|
+
|
14
|
+
private_constant :EMPTY_ATTRIBUTES
|
15
|
+
|
16
|
+
# Returns the name of this event
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
attr_reader :name
|
20
|
+
|
21
|
+
# Returns the frozen attributes for this event
|
22
|
+
#
|
23
|
+
# @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
|
24
|
+
attr_reader :attributes
|
25
|
+
|
26
|
+
# Returns the timestamp for this event
|
27
|
+
#
|
28
|
+
# @return [Time]
|
29
|
+
attr_reader :timestamp
|
30
|
+
|
31
|
+
# Returns a new immutable {Event}.
|
32
|
+
#
|
33
|
+
# @param [String] name The name of this event
|
34
|
+
# @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
|
35
|
+
# attributes A hash of attributes for this event. Attributes will be
|
36
|
+
# frozen during Event initialization.
|
37
|
+
# @param [optional Time] timestamp The timestamp for this event.
|
38
|
+
# Defaults to Time.now.
|
39
|
+
# @return [Event]
|
40
|
+
def initialize(name:, attributes: nil, timestamp: nil)
|
41
|
+
@name = name
|
42
|
+
@attributes = attributes.freeze || EMPTY_ATTRIBUTES
|
43
|
+
@timestamp = timestamp || Time.now
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -7,21 +7,21 @@
|
|
7
7
|
module OpenTelemetry
|
8
8
|
module SDK
|
9
9
|
module Trace
|
10
|
-
# The Export module contains the built-in exporters for the OpenTelemetry
|
10
|
+
# The Export module contains the built-in exporters and span processors for the OpenTelemetry
|
11
11
|
# reference implementation.
|
12
12
|
module Export
|
13
|
-
# Result codes for the SpanExporter#export method.
|
13
|
+
# Result codes for the SpanExporter#export method and the SpanProcessor#force_flush and SpanProcessor#shutdown methods.
|
14
14
|
|
15
|
-
# The
|
15
|
+
# The operation finished successfully.
|
16
16
|
SUCCESS = 0
|
17
17
|
|
18
|
-
# The
|
19
|
-
|
20
|
-
FAILED_RETRYABLE = 1
|
18
|
+
# The operation finished with an error.
|
19
|
+
FAILURE = 1
|
21
20
|
|
22
|
-
#
|
23
|
-
|
24
|
-
|
21
|
+
# Additional result code for the SpanProcessor#force_flush and SpanProcessor#shutdown methods.
|
22
|
+
|
23
|
+
# The operation timed out.
|
24
|
+
TIMEOUT = 2
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -22,24 +22,29 @@ module OpenTelemetry
|
|
22
22
|
# If the queue gets half full a preemptive notification is sent to the
|
23
23
|
# worker thread that exports the spans to wake up and start a new
|
24
24
|
# export cycle.
|
25
|
-
#
|
26
|
-
# max_export_attempts attempts are made to export each batch, while
|
27
|
-
# export fails with {FAILED_RETRYABLE}, backing off linearly in 100ms
|
28
|
-
# increments.
|
29
25
|
class BatchSpanProcessor
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
# Returns a new instance of the {BatchSpanProcessor}.
|
27
|
+
#
|
28
|
+
# @param [SpanExporter] exporter
|
29
|
+
# @param [Numeric] exporter_timeout_millis the delay interval between two
|
30
|
+
# consecutive exports. Defaults to the value of the OTEL_BSP_EXPORT_TIMEOUT_MILLIS
|
31
|
+
# environment variable, if set, or 30,000 (30 seconds).
|
32
|
+
# @param [Numeric] schedule_delay_millis the maximum allowed time to export data.
|
33
|
+
# Defaults to the value of the OTEL_BSP_SCHEDULE_DELAY_MILLIS environment
|
34
|
+
# variable, if set, or 5,000 (5 seconds).
|
35
|
+
# @param [Integer] max_queue_size the maximum queue size in spans.
|
36
|
+
# Defaults to the value of the OTEL_BSP_MAX_QUEUE_SIZE environment
|
37
|
+
# variable, if set, or 2048.
|
38
|
+
# @param [Integer] max_export_batch_size the maximum batch size in spans.
|
39
|
+
# Defaults to the value of the OTEL_BSP_MAX_EXPORT_BATCH_SIZE environment
|
40
|
+
# variable, if set, or 512.
|
41
|
+
#
|
42
|
+
# @return a new instance of the {BatchSpanProcessor}.
|
37
43
|
def initialize(exporter:,
|
38
|
-
exporter_timeout_millis:
|
39
|
-
schedule_delay_millis:
|
40
|
-
max_queue_size:
|
41
|
-
max_export_batch_size:
|
42
|
-
max_export_attempts: MAX_EXPORT_ATTEMPTS)
|
44
|
+
exporter_timeout_millis: Float(ENV.fetch('OTEL_BSP_EXPORT_TIMEOUT_MILLIS', 30_000)),
|
45
|
+
schedule_delay_millis: Float(ENV.fetch('OTEL_BSP_SCHEDULE_DELAY_MILLIS', 5_000)),
|
46
|
+
max_queue_size: Integer(ENV.fetch('OTEL_BSP_MAX_QUEUE_SIZE', 2048)),
|
47
|
+
max_export_batch_size: Integer(ENV.fetch('OTEL_BSP_MAX_EXPORT_BATCH_SIZE', 512)))
|
43
48
|
raise ArgumentError if max_export_batch_size > max_queue_size
|
44
49
|
|
45
50
|
@exporter = exporter
|
@@ -50,13 +55,14 @@ module OpenTelemetry
|
|
50
55
|
@delay_seconds = schedule_delay_millis / 1000.0
|
51
56
|
@max_queue_size = max_queue_size
|
52
57
|
@batch_size = max_export_batch_size
|
53
|
-
@export_attempts = max_export_attempts
|
54
58
|
@spans = []
|
55
|
-
@
|
59
|
+
@pid = nil
|
60
|
+
@thread = nil
|
61
|
+
reset_on_fork
|
56
62
|
end
|
57
63
|
|
58
64
|
# does nothing for this processor
|
59
|
-
def on_start(span)
|
65
|
+
def on_start(span, parent_context)
|
60
66
|
# noop
|
61
67
|
end
|
62
68
|
|
@@ -65,6 +71,7 @@ module OpenTelemetry
|
|
65
71
|
return unless span.context.trace_flags.sampled?
|
66
72
|
|
67
73
|
lock do
|
74
|
+
reset_on_fork
|
68
75
|
n = spans.size + 1 - max_queue_size
|
69
76
|
spans.shift(n) if n.positive?
|
70
77
|
spans << span
|
@@ -80,17 +87,27 @@ module OpenTelemetry
|
|
80
87
|
# necessary, such as when using some FaaS providers that may suspend
|
81
88
|
# the process after an invocation, but before the `Processor` exports
|
82
89
|
# the completed spans.
|
90
|
+
#
|
91
|
+
# @return [Integer] SUCCESS if no error occurred, FAILURE if a
|
92
|
+
# non-specific failure occurred, TIMEOUT if a timeout occurred.
|
83
93
|
def force_flush
|
84
|
-
snapshot = lock
|
94
|
+
snapshot = lock do
|
95
|
+
reset_on_fork(restart_thread: false) if @keep_running
|
96
|
+
spans.shift(spans.size)
|
97
|
+
end
|
85
98
|
until snapshot.empty?
|
86
99
|
batch = snapshot.shift(@batch_size).map!(&:to_span_data)
|
87
100
|
result_code = @exporter.export(batch)
|
88
101
|
report_result(result_code, batch)
|
89
102
|
end
|
103
|
+
SUCCESS
|
90
104
|
end
|
91
105
|
|
92
106
|
# shuts the consumer thread down and flushes the current accumulated buffer
|
93
107
|
# will block until the thread is finished
|
108
|
+
#
|
109
|
+
# @return [Integer] SUCCESS if no error occurred, FAILURE if a
|
110
|
+
# non-specific failure occurred, TIMEOUT if a timeout occurred.
|
94
111
|
def shutdown
|
95
112
|
lock do
|
96
113
|
@keep_running = false
|
@@ -109,6 +126,7 @@ module OpenTelemetry
|
|
109
126
|
def work
|
110
127
|
loop do
|
111
128
|
batch = lock do
|
129
|
+
reset_on_fork(restart_thread: false)
|
112
130
|
@condition.wait(@mutex, @delay_seconds) if spans.size < batch_size && @keep_running
|
113
131
|
@condition.wait(@mutex, @delay_seconds) while spans.empty? && @keep_running
|
114
132
|
return unless @keep_running
|
@@ -120,21 +138,24 @@ module OpenTelemetry
|
|
120
138
|
end
|
121
139
|
end
|
122
140
|
|
123
|
-
def
|
124
|
-
|
125
|
-
@
|
126
|
-
result_code = export_with_timeout(batch)
|
127
|
-
break unless result_code == FAILED_RETRYABLE
|
141
|
+
def reset_on_fork(restart_thread: true)
|
142
|
+
pid = Process.pid
|
143
|
+
return if @pid == pid
|
128
144
|
|
129
|
-
|
130
|
-
|
145
|
+
@pid = pid
|
146
|
+
spans.clear
|
147
|
+
@thread = Thread.new { work } if restart_thread
|
148
|
+
end
|
149
|
+
|
150
|
+
def export_batch(batch)
|
151
|
+
result_code = export_with_timeout(batch)
|
131
152
|
report_result(result_code, batch)
|
132
153
|
end
|
133
154
|
|
134
155
|
def export_with_timeout(batch)
|
135
156
|
Timeout.timeout(@exporter_timeout_seconds) { @exporter.export(batch) }
|
136
157
|
rescue Timeout::Error
|
137
|
-
|
158
|
+
FAILURE
|
138
159
|
end
|
139
160
|
|
140
161
|
def report_result(result_code, batch)
|