datadog 2.16.0 → 2.17.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -1
- data/ext/datadog_profiling_native_extension/encoded_profile.c +22 -12
- data/ext/datadog_profiling_native_extension/encoded_profile.h +1 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +45 -72
- data/ext/datadog_profiling_native_extension/stack_recorder.c +4 -5
- data/ext/libdatadog_api/crashtracker.c +10 -3
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/lru_cache.rb +49 -0
- data/lib/datadog/appsec/api_security.rb +9 -0
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -5
- data/lib/datadog/core/configuration/components.rb +29 -20
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/option.rb +18 -18
- data/lib/datadog/core/configuration/option_definition.rb +4 -4
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +10 -10
- data/lib/datadog/core/configuration.rb +16 -16
- data/lib/datadog/core/crashtracking/component.rb +2 -1
- data/lib/datadog/core/encoding.rb +1 -1
- data/lib/datadog/core/environment/cgroup.rb +10 -12
- data/lib/datadog/core/environment/container.rb +38 -40
- data/lib/datadog/core/environment/ext.rb +6 -6
- data/lib/datadog/core/environment/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +12 -14
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client.rb +32 -31
- data/lib/datadog/core/remote/component.rb +3 -3
- data/lib/datadog/core/remote/configuration/digest.rb +7 -7
- data/lib/datadog/core/remote/configuration/path.rb +1 -1
- data/lib/datadog/core/remote/transport/http/client.rb +1 -1
- data/lib/datadog/core/remote/transport/http/config.rb +21 -5
- data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -1
- data/lib/datadog/core/runtime/metrics.rb +3 -3
- data/lib/datadog/core/telemetry/component.rb +39 -24
- data/lib/datadog/core/telemetry/emitter.rb +7 -1
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +179 -0
- data/lib/datadog/core/telemetry/event/base.rb +40 -0
- data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
- data/lib/datadog/core/telemetry/event/log.rb +76 -0
- data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
- data/lib/datadog/core/telemetry/event.rb +17 -475
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/metric.rb +3 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -2
- data/lib/datadog/core/telemetry/transport/telemetry.rb +0 -1
- data/lib/datadog/core/telemetry/worker.rb +48 -27
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/builder.rb +13 -13
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
- data/lib/datadog/core/utils/duration.rb +32 -32
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/network.rb +6 -6
- data/lib/datadog/core/utils/only_once_successful.rb +16 -5
- data/lib/datadog/core/utils/time.rb +10 -2
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
- data/lib/datadog/core/worker.rb +1 -1
- data/lib/datadog/core/workers/async.rb +9 -10
- data/lib/datadog/error_tracking/component.rb +2 -2
- data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
- data/lib/datadog/profiling/ext.rb +0 -1
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +1 -6
- data/lib/datadog/profiling/scheduler.rb +8 -1
- data/lib/datadog/profiling/tag_builder.rb +1 -5
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/version.rb +1 -1
- metadata +23 -6
@@ -17,8 +17,6 @@ module Datadog
|
|
17
17
|
DEFAULT_BUFFER_MAX_SIZE = 1000
|
18
18
|
APP_STARTED_EVENT_RETRIES = 10
|
19
19
|
|
20
|
-
TELEMETRY_STARTED_ONCE = Utils::OnlyOnceSuccessful.new(APP_STARTED_EVENT_RETRIES)
|
21
|
-
|
22
20
|
def initialize(
|
23
21
|
heartbeat_interval_seconds:,
|
24
22
|
metrics_aggregation_interval_seconds:,
|
@@ -48,16 +46,22 @@ module Datadog
|
|
48
46
|
@buffer_size = buffer_size
|
49
47
|
|
50
48
|
self.buffer = buffer_klass.new(@buffer_size)
|
49
|
+
|
50
|
+
@initial_event_once = Utils::OnlyOnceSuccessful.new(APP_STARTED_EVENT_RETRIES)
|
51
51
|
end
|
52
52
|
|
53
53
|
attr_reader :logger
|
54
|
+
attr_reader :initial_event_once
|
55
|
+
attr_reader :initial_event
|
54
56
|
|
55
57
|
# Returns true if worker thread is successfully started,
|
56
58
|
# false if worker thread was not started but telemetry is enabled,
|
57
59
|
# nil if telemetry is disabled.
|
58
|
-
def start
|
60
|
+
def start(initial_event)
|
59
61
|
return if !enabled? || forked?
|
60
62
|
|
63
|
+
@initial_event = initial_event
|
64
|
+
|
61
65
|
# starts async worker
|
62
66
|
# perform should return true if thread was actually started,
|
63
67
|
# false otherwise
|
@@ -81,12 +85,16 @@ module Datadog
|
|
81
85
|
true
|
82
86
|
end
|
83
87
|
|
84
|
-
def
|
85
|
-
|
88
|
+
def sent_initial_event?
|
89
|
+
initial_event_once.success?
|
90
|
+
end
|
91
|
+
|
92
|
+
def failed_initial_event?
|
93
|
+
initial_event_once.failed?
|
86
94
|
end
|
87
95
|
|
88
|
-
def
|
89
|
-
|
96
|
+
def need_initial_event?
|
97
|
+
!sent_initial_event? && !failed_initial_event?
|
90
98
|
end
|
91
99
|
|
92
100
|
# Wait for the worker to send out all events that have already
|
@@ -114,7 +122,7 @@ module Datadog
|
|
114
122
|
# Note that the first wait interval between telemetry event
|
115
123
|
# sending is 10 seconds, the timeout needs to be strictly
|
116
124
|
# greater than that.
|
117
|
-
return true if buffer.empty? && !in_iteration? &&
|
125
|
+
return true if buffer.empty? && !in_iteration? && sent_initial_event?
|
118
126
|
|
119
127
|
sleep 0.5
|
120
128
|
|
@@ -127,11 +135,26 @@ module Datadog
|
|
127
135
|
def perform(*events)
|
128
136
|
return if !enabled? || forked?
|
129
137
|
|
130
|
-
|
138
|
+
if need_initial_event?
|
139
|
+
started!
|
140
|
+
unless sent_initial_event?
|
141
|
+
# We still haven't succeeded in sending the started event,
|
142
|
+
# which will make flush_events do nothing - but the events
|
143
|
+
# given to us as the parameter have already been removed
|
144
|
+
# from the queue.
|
145
|
+
# Put the events back to the front of the queue to not
|
146
|
+
# lose them.
|
147
|
+
buffer.unshift(*events)
|
148
|
+
return
|
149
|
+
end
|
150
|
+
end
|
131
151
|
|
132
152
|
metric_events = @metrics_manager.flush!
|
133
153
|
events = [] if events.nil?
|
134
|
-
|
154
|
+
events += metric_events
|
155
|
+
if events.any?
|
156
|
+
flush_events(events)
|
157
|
+
end
|
135
158
|
|
136
159
|
@current_ticks += 1
|
137
160
|
return if @current_ticks < @ticks_per_heartbeat
|
@@ -141,11 +164,6 @@ module Datadog
|
|
141
164
|
end
|
142
165
|
|
143
166
|
def flush_events(events)
|
144
|
-
return if events.empty?
|
145
|
-
# TODO: can this method silently drop events which are
|
146
|
-
# generated prior to the started event being submitted?
|
147
|
-
return if !enabled? || !sent_started_event?
|
148
|
-
|
149
167
|
events = deduplicate_logs(events)
|
150
168
|
|
151
169
|
logger.debug { "Sending #{events&.count} telemetry events" }
|
@@ -153,7 +171,7 @@ module Datadog
|
|
153
171
|
end
|
154
172
|
|
155
173
|
def heartbeat!
|
156
|
-
return if !enabled? || !
|
174
|
+
return if !enabled? || !sent_initial_event?
|
157
175
|
|
158
176
|
send_event(Event::AppHeartbeat.new)
|
159
177
|
end
|
@@ -161,26 +179,29 @@ module Datadog
|
|
161
179
|
def started!
|
162
180
|
return unless enabled?
|
163
181
|
|
164
|
-
|
165
|
-
|
166
|
-
disable!
|
167
|
-
return
|
168
|
-
end
|
169
|
-
|
170
|
-
TELEMETRY_STARTED_ONCE.run do
|
171
|
-
res = send_event(Event::AppStarted.new)
|
182
|
+
initial_event_once.run do
|
183
|
+
res = send_event(initial_event)
|
172
184
|
|
173
185
|
if res.ok?
|
174
|
-
logger.debug
|
186
|
+
logger.debug { "Telemetry initial event (#{initial_event.type}) is successfully sent" }
|
175
187
|
|
176
|
-
|
188
|
+
# TODO Dependencies loaded event should probably check for new
|
189
|
+
# dependencies and send the new ones.
|
190
|
+
# System tests demand only one instance of this event per
|
191
|
+
# dependency.
|
192
|
+
send_event(Event::AppDependenciesLoaded.new) if @dependency_collection && initial_event.class.eql?(Telemetry::Event::AppStarted) # standard:disable Style/ClassEqualityComparison:
|
177
193
|
|
178
194
|
true
|
179
195
|
else
|
180
|
-
logger.debug(
|
196
|
+
logger.debug("Error sending telemetry initial event (#{initial_event.type}), retry after heartbeat interval...")
|
181
197
|
false
|
182
198
|
end
|
183
199
|
end
|
200
|
+
|
201
|
+
if failed_initial_event?
|
202
|
+
logger.debug { "Telemetry initial event (#{initial_event.type}) exhausted retries, disabling telemetry worker" }
|
203
|
+
disable!
|
204
|
+
end
|
184
205
|
end
|
185
206
|
|
186
207
|
def send_event(event)
|
@@ -41,19 +41,19 @@ module Datadog
|
|
41
41
|
|
42
42
|
def adapter(config, *args, **kwargs)
|
43
43
|
@default_adapter = case config
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
44
|
+
when Core::Configuration::AgentSettingsResolver::AgentSettings
|
45
|
+
registry_klass = REGISTRY.get(config.adapter)
|
46
|
+
raise UnknownAdapterError, config.adapter if registry_klass.nil?
|
47
|
+
|
48
|
+
registry_klass.build(config)
|
49
|
+
when Symbol
|
50
|
+
registry_klass = REGISTRY.get(config)
|
51
|
+
raise UnknownAdapterError, config if registry_klass.nil?
|
52
|
+
|
53
|
+
registry_klass.new(*args, **kwargs)
|
54
|
+
else
|
55
|
+
config
|
56
|
+
end
|
57
57
|
end
|
58
58
|
|
59
59
|
def headers(values = {})
|
@@ -51,13 +51,13 @@ module Datadog
|
|
51
51
|
def fork
|
52
52
|
# If a block is provided, it must be wrapped to trigger callbacks.
|
53
53
|
child_block = if block_given?
|
54
|
-
|
55
|
-
|
54
|
+
proc do
|
55
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:child)
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
# Invoke original block
|
58
|
+
yield
|
59
|
+
end
|
60
|
+
end
|
61
61
|
|
62
62
|
# Start fork
|
63
63
|
# If a block is provided, use the wrapped version.
|
@@ -7,42 +7,42 @@ module Datadog
|
|
7
7
|
module Duration
|
8
8
|
def self.call(value, base: :s)
|
9
9
|
cast = if value.include?('.')
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
method(:Float)
|
11
|
+
else
|
12
|
+
method(:Integer)
|
13
|
+
end
|
14
14
|
|
15
15
|
scale = case base
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
when :s
|
17
|
+
1_000_000_000
|
18
|
+
when :ms
|
19
|
+
1_000_000
|
20
|
+
when :us
|
21
|
+
1000
|
22
|
+
when :ns
|
23
|
+
1
|
24
|
+
else
|
25
|
+
raise ArgumentError, "invalid base: #{base.inspect}"
|
26
|
+
end
|
27
27
|
|
28
28
|
result = case value
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
29
|
+
when /^(\d+(?:\.\d+)?)h$/
|
30
|
+
cast.call(Regexp.last_match(1)) * 1_000_000_000 * 60 * 60 / scale
|
31
|
+
when /^(\d+(?:\.\d+)?)m$/
|
32
|
+
cast.call(Regexp.last_match(1)) * 1_000_000_000 * 60 / scale
|
33
|
+
when /^(\d+(?:\.\d+)?)s$/
|
34
|
+
cast.call(Regexp.last_match(1)) * 1_000_000_000 / scale
|
35
|
+
when /^(\d+(?:\.\d+)?)ms$/
|
36
|
+
cast.call(Regexp.last_match(1)) * 1_000_000 / scale
|
37
|
+
when /^(\d+(?:\.\d+)?)us$/
|
38
|
+
cast.call(Regexp.last_match(1)) * 1_000 / scale
|
39
|
+
when /^(\d+(?:\.\d+)?)ns$/
|
40
|
+
cast.call(Regexp.last_match(1)) / scale
|
41
|
+
when /^(\d+(?:\.\d+)?)$/
|
42
|
+
cast.call(Regexp.last_match(1))
|
43
|
+
else
|
44
|
+
raise ArgumentError, "invalid duration: #{value.inspect}"
|
45
|
+
end
|
46
46
|
# @type var result: Numeric
|
47
47
|
result.round
|
48
48
|
end
|
@@ -47,12 +47,12 @@ module Datadog
|
|
47
47
|
# This wrapper prevents this by initializing the fork PID when the object is created.
|
48
48
|
if RUBY_VERSION >= '3'
|
49
49
|
def initialize(*args, **kwargs, &block)
|
50
|
-
super
|
50
|
+
super
|
51
51
|
update_fork_pid!
|
52
52
|
end
|
53
53
|
else
|
54
54
|
def initialize(*args, &block)
|
55
|
-
super
|
55
|
+
super
|
56
56
|
update_fork_pid!
|
57
57
|
end
|
58
58
|
end
|
@@ -32,7 +32,7 @@ module Datadog
|
|
32
32
|
def stripped_ip_from_request_headers(headers, ip_headers_to_check: DEFAULT_IP_HEADERS_NAMES)
|
33
33
|
ip = ip_header(headers, ip_headers_to_check)
|
34
34
|
|
35
|
-
ip
|
35
|
+
ip&.to_s
|
36
36
|
end
|
37
37
|
|
38
38
|
# @param [String] IP value.
|
@@ -40,7 +40,7 @@ module Datadog
|
|
40
40
|
# @return [nil] when no valid IP value found.
|
41
41
|
def stripped_ip(ip)
|
42
42
|
ip = ip_to_ipaddr(ip)
|
43
|
-
ip
|
43
|
+
ip&.to_s
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
@@ -52,10 +52,10 @@ module Datadog
|
|
52
52
|
return unless ip
|
53
53
|
|
54
54
|
clean_ip = if likely_ipv4?(ip)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
strip_ipv4_port(ip)
|
56
|
+
else
|
57
|
+
strip_zone_specifier(strip_ipv6_port(ip))
|
58
|
+
end
|
59
59
|
|
60
60
|
begin
|
61
61
|
IPAddr.new(clean_ip)
|
@@ -5,14 +5,25 @@ require_relative 'only_once'
|
|
5
5
|
module Datadog
|
6
6
|
module Core
|
7
7
|
module Utils
|
8
|
-
# Helper class to execute something with only one
|
8
|
+
# Helper class to execute something with only one successful execution.
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# If limit is not provided to the constructor, +run+ will execute the
|
11
|
+
# block an unlimited number of times until the block indicates that it
|
12
|
+
# executed successfully by returning a truthy value. After a block
|
13
|
+
# executes successfully, subsequent +run+ calls will not invoke the
|
14
|
+
# block.
|
12
15
|
#
|
13
|
-
#
|
16
|
+
# If a non-zero limit is provided to the constructor, +run+ will
|
17
|
+
# execute the block up to that many times, and will mark the instance
|
18
|
+
# of OnlyOneSuccessful as failed if none of the executions succeeded.
|
14
19
|
#
|
15
|
-
#
|
20
|
+
# One consumer of this class is sending the app-started telemetry event.
|
21
|
+
#
|
22
|
+
# Successful execution is determined by the return value of the block:
|
23
|
+
# any truthy value is considered success.
|
24
|
+
#
|
25
|
+
# This class is thread-safe (however, instances of it must also be
|
26
|
+
# created in a thread-safe manner).
|
16
27
|
#
|
17
28
|
# Note: In its current state, this class is not Ractor-safe.
|
18
29
|
# In https://github.com/DataDog/dd-trace-rb/pull/1398#issuecomment-797378810 we have a discussion of alternatives,
|
@@ -35,7 +35,11 @@ module Datadog
|
|
35
35
|
# Avoid method redefinition warning.
|
36
36
|
# `rescue nil` is added in case customers remove the method
|
37
37
|
# themselves to squelch the warning.
|
38
|
-
|
38
|
+
begin
|
39
|
+
remove_method(:now)
|
40
|
+
rescue
|
41
|
+
nil
|
42
|
+
end
|
39
43
|
end
|
40
44
|
define_singleton_method(:now, &block)
|
41
45
|
end
|
@@ -53,7 +57,11 @@ module Datadog
|
|
53
57
|
# Avoid method redefinition warning
|
54
58
|
# `rescue nil` is added in case customers remove the method
|
55
59
|
# themselves to squelch the warning.
|
56
|
-
|
60
|
+
begin
|
61
|
+
remove_method(:get_time)
|
62
|
+
rescue
|
63
|
+
nil
|
64
|
+
end
|
57
65
|
end
|
58
66
|
define_singleton_method(:get_time, &block)
|
59
67
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Core
|
5
|
+
module Utils
|
6
|
+
# Helper methods for truncating data
|
7
|
+
module Truncation
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def truncate_in_middle(string, max_prefix_length, max_suffix_length)
|
11
|
+
max_length = max_prefix_length + 3 + max_suffix_length
|
12
|
+
if string.length > max_length
|
13
|
+
"#{string[0...max_prefix_length]}...#{string[-max_suffix_length..-1]}"
|
14
|
+
else
|
15
|
+
string
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -28,29 +28,29 @@ module Datadog
|
|
28
28
|
"--#{SecureRandom.uuid}"
|
29
29
|
end
|
30
30
|
|
31
|
-
def initialize(path, params, headers={}, boundary = Multipartable.secure_boundary)
|
31
|
+
def initialize(path, params, headers = {}, boundary = Multipartable.secure_boundary)
|
32
32
|
headers = headers.clone # don't want to modify the original variable
|
33
33
|
parts_headers = headers.delete(:parts) || {}
|
34
34
|
super(path, headers)
|
35
|
-
parts = params.map do |k,v|
|
35
|
+
parts = params.map do |k, v|
|
36
36
|
case v
|
37
37
|
when Array
|
38
|
-
v.map {|item| Parts::Part.new(boundary, "#{k}[]", item, parts_headers[k]) }
|
38
|
+
v.map { |item| Parts::Part.new(boundary, "#{k}[]", item, parts_headers[k]) }
|
39
39
|
else
|
40
40
|
Parts::Part.new(boundary, k, v, parts_headers[k])
|
41
41
|
end
|
42
42
|
end.flatten
|
43
43
|
parts << Parts::EpiloguePart.new(boundary)
|
44
|
-
ios = parts.map {|p| p.to_io }
|
45
|
-
|
46
|
-
|
47
|
-
self.content_length = parts.inject(0) {|sum,i| sum + i.length }
|
44
|
+
ios = parts.map { |p| p.to_io }
|
45
|
+
set_content_type(headers["Content-Type"] || "multipart/form-data",
|
46
|
+
{"boundary" => boundary})
|
47
|
+
self.content_length = parts.inject(0) { |sum, i| sum + i.length }
|
48
48
|
self.body_stream = CompositeReadIO.new(*ios)
|
49
49
|
|
50
50
|
@boundary = boundary
|
51
51
|
end
|
52
52
|
|
53
|
-
|
53
|
+
attr_reader :boundary
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -58,7 +58,7 @@ module Datadog
|
|
58
58
|
part = ''
|
59
59
|
part << "--#{boundary}\r\n"
|
60
60
|
part << "Content-ID: #{headers["Content-ID"]}\r\n" if headers["Content-ID"]
|
61
|
-
part << "Content-Disposition: form-data; name=\"#{name
|
61
|
+
part << "Content-Disposition: form-data; name=\"#{name}\"\r\n"
|
62
62
|
part << "Content-Type: #{headers["Content-Type"]}\r\n" if headers["Content-Type"]
|
63
63
|
part << "\r\n"
|
64
64
|
part << "#{value}\r\n"
|
@@ -76,9 +76,9 @@ module Datadog
|
|
76
76
|
# @param io [IO]
|
77
77
|
# @param headers [Hash]
|
78
78
|
def initialize(boundary, name, io, headers = {})
|
79
|
-
file_length = io.respond_to?(:length) ?
|
79
|
+
file_length = io.respond_to?(:length) ? io.length : File.size(io.local_path)
|
80
80
|
@head = build_head(boundary, name, io.original_filename, io.content_type, file_length,
|
81
|
-
|
81
|
+
io.respond_to?(:opts) ? io.opts.merge(headers) : headers)
|
82
82
|
@foot = "\r\n"
|
83
83
|
@length = @head.bytesize + file_length + @foot.length
|
84
84
|
@io = CompositeReadIO.new(StringIO.new(@head), io, StringIO.new(@foot))
|
@@ -98,16 +98,16 @@ module Datadog
|
|
98
98
|
|
99
99
|
part = ''
|
100
100
|
part << "--#{boundary}\r\n"
|
101
|
-
part << "Content-Disposition: #{content_disposition}; name=\"#{name
|
101
|
+
part << "Content-Disposition: #{content_disposition}; name=\"#{name}\"; filename=\"#{filename}\"\r\n"
|
102
102
|
part << "Content-Length: #{content_len}\r\n"
|
103
103
|
if content_id = opts.delete("Content-ID")
|
104
104
|
part << "Content-ID: #{content_id}\r\n"
|
105
105
|
end
|
106
106
|
|
107
|
-
if opts["Content-Type"]
|
108
|
-
|
107
|
+
part << if !opts["Content-Type"].nil?
|
108
|
+
"Content-Type: " + opts["Content-Type"] + "\r\n"
|
109
109
|
else
|
110
|
-
|
110
|
+
"Content-Type: #{type}\r\n"
|
111
111
|
end
|
112
112
|
|
113
113
|
part << "Content-Transfer-Encoding: #{trans_encoding}\r\n"
|
data/lib/datadog/core/worker.rb
CHANGED
@@ -154,16 +154,15 @@ module Datadog
|
|
154
154
|
Datadog.logger.debug { "Starting thread for: #{self}" }
|
155
155
|
|
156
156
|
@worker = ::Thread.new do
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
157
|
+
yield
|
158
|
+
# rubocop:disable Lint/RescueException
|
159
|
+
rescue Exception => e
|
160
|
+
@error = e
|
161
|
+
Datadog.logger.debug(
|
162
|
+
"Worker thread error. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
163
|
+
)
|
164
|
+
raise
|
165
|
+
|
167
166
|
# rubocop:enable Lint/RescueException
|
168
167
|
end
|
169
168
|
@worker.name = self.class.name
|
@@ -33,9 +33,9 @@ module Datadog
|
|
33
33
|
if RUBY_ENGINE != 'ruby'
|
34
34
|
logger.warn("error tracking: cannot enable error tracking: MRI is required, but running on #{RUBY_ENGINE}")
|
35
35
|
false
|
36
|
-
elsif RUBY_VERSION < '2.
|
36
|
+
elsif RUBY_VERSION < '2.7'
|
37
37
|
logger.warn(
|
38
|
-
"error tracking: cannot enable error tracking: Ruby 2.
|
38
|
+
"error tracking: cannot enable error tracking: Ruby 2.7+ is required, but running
|
39
39
|
on #{RUBY_VERSION}"
|
40
40
|
)
|
41
41
|
false
|
@@ -19,7 +19,6 @@ module Datadog
|
|
19
19
|
FORM_FIELD_TAG_RUNTIME = "runtime"
|
20
20
|
FORM_FIELD_TAG_RUNTIME_ENGINE = "runtime_engine"
|
21
21
|
FORM_FIELD_TAG_RUNTIME_ID = "runtime-id"
|
22
|
-
FORM_FIELD_TAG_RUNTIME_PLATFORM = "runtime_platform"
|
23
22
|
FORM_FIELD_TAG_RUNTIME_VERSION = "runtime_version"
|
24
23
|
FORM_FIELD_TAG_SERVICE = "service"
|
25
24
|
FORM_FIELD_TAG_VERSION = "version"
|
@@ -32,7 +32,7 @@ module Datadog
|
|
32
32
|
@code_provenance_file_name = code_provenance_file_name
|
33
33
|
@code_provenance_data = code_provenance_data
|
34
34
|
@tags_as_array = tags_as_array
|
35
|
-
@internal_metadata_json = JSON.
|
35
|
+
@internal_metadata_json = JSON.generate(internal_metadata)
|
36
36
|
@info_json = info_json
|
37
37
|
end
|
38
38
|
end
|
@@ -29,12 +29,7 @@ module Datadog
|
|
29
29
|
status, result = self.class._native_do_export(
|
30
30
|
exporter_configuration,
|
31
31
|
@upload_timeout_milliseconds,
|
32
|
-
flush
|
33
|
-
# TODO: This is going to be removed once we move to libdatadog 17
|
34
|
-
flush.start.tv_sec,
|
35
|
-
flush.start.tv_nsec,
|
36
|
-
flush.finish.tv_sec,
|
37
|
-
flush.finish.tv_nsec,
|
32
|
+
flush
|
38
33
|
)
|
39
34
|
|
40
35
|
if status == :ok
|
@@ -37,6 +37,7 @@ module Datadog
|
|
37
37
|
@exporter = exporter
|
38
38
|
@transport = transport
|
39
39
|
@profiler_failed = false
|
40
|
+
@stop_requested = false
|
40
41
|
|
41
42
|
# Workers::Async::Thread settings
|
42
43
|
self.fork_policy = fork_policy
|
@@ -88,7 +89,7 @@ module Datadog
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def work_pending?
|
91
|
-
!profiler_failed && exporter.can_flush?
|
92
|
+
!profiler_failed && exporter.can_flush? && (run_loop? || !stop_requested?)
|
92
93
|
end
|
93
94
|
|
94
95
|
def reset_after_fork
|
@@ -138,8 +139,14 @@ module Datadog
|
|
138
139
|
Datadog::Core::Telemetry::Logger.report(e, description: "Unable to report profile")
|
139
140
|
end
|
140
141
|
|
142
|
+
@stop_requested = !run_loop?
|
143
|
+
|
141
144
|
true
|
142
145
|
end
|
146
|
+
|
147
|
+
def stop_requested?
|
148
|
+
@stop_requested
|
149
|
+
end
|
143
150
|
end
|
144
151
|
end
|
145
152
|
end
|