datadog 2.1.0 → 2.3.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 +101 -1
- data/ext/datadog_profiling_loader/extconf.rb +15 -15
- data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +132 -44
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +90 -37
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +69 -62
- data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
- data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/helpers.h +6 -17
- data/ext/datadog_profiling_native_extension/http_transport.c +3 -3
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -126
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
- data/ext/datadog_profiling_native_extension/profiling.c +0 -2
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +27 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
- data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
- data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +20 -7
- data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
- data/ext/libdatadog_api/extconf.rb +108 -0
- data/ext/libdatadog_api/macos_development.md +26 -0
- data/ext/libdatadog_extconf_helpers.rb +130 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +1 -0
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +17 -12
- data/lib/datadog/core/configuration/settings.rb +93 -7
- data/lib/datadog/core/configuration.rb +3 -17
- data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
- data/lib/datadog/core/crashtracking/component.rb +111 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
- data/lib/datadog/core/deprecations.rb +58 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +6 -0
- data/lib/datadog/core/telemetry/component.rb +154 -0
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +132 -26
- data/lib/datadog/core/telemetry/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +11 -13
- data/lib/datadog/core/telemetry/http/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/transport.rb +38 -9
- data/lib/datadog/core/telemetry/logging.rb +35 -0
- data/lib/datadog/core/telemetry/metric.rb +167 -0
- data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
- data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
- data/lib/datadog/core/telemetry/request.rb +1 -1
- data/lib/datadog/core/telemetry/worker.rb +173 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/only_once_successful.rb +76 -0
- data/lib/datadog/core.rb +2 -19
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +24 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +3 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
- data/lib/datadog/profiling/component.rb +85 -90
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +8 -6
- data/lib/datadog/profiling/load_native_extension.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +5 -8
- data/lib/datadog/profiling/scheduler.rb +31 -25
- data/lib/datadog/profiling/tag_builder.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +5 -5
- data/lib/datadog/profiling/tasks/setup.rb +16 -35
- data/lib/datadog/profiling.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -1
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
- data/lib/datadog/tracing/contrib/analytics.rb +5 -0
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
- data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
- data/lib/datadog/tracing/distributed/datadog.rb +2 -2
- data/lib/datadog/tracing/distributed/propagation.rb +9 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +3 -2
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/span.rb +9 -2
- data/lib/datadog/tracing/span_event.rb +41 -0
- data/lib/datadog/tracing/span_operation.rb +9 -4
- data/lib/datadog/tracing/trace_operation.rb +7 -3
- data/lib/datadog/tracing/trace_segment.rb +4 -1
- data/lib/datadog/tracing/tracer.rb +9 -2
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing.rb +5 -1
- data/lib/datadog/version.rb +2 -2
- metadata +43 -12
- data/lib/datadog/core/telemetry/client.rb +0 -95
- data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -16,22 +16,20 @@ module Datadog
|
|
16
16
|
|
17
17
|
# @param http_transport [Datadog::Core::Telemetry::Http::Transport] Transport object that can be used to send
|
18
18
|
# telemetry requests via the agent
|
19
|
-
def initialize(http_transport:
|
19
|
+
def initialize(http_transport:)
|
20
20
|
@http_transport = http_transport
|
21
21
|
end
|
22
22
|
|
23
23
|
# Retrieves and emits a TelemetryRequest object based on the request type specified
|
24
24
|
def request(event)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
rescue
|
32
|
-
|
33
|
-
Telemetry::Http::InternalErrorResponse.new(e)
|
34
|
-
end
|
25
|
+
seq_id = self.class.sequence.next
|
26
|
+
payload = Request.build_payload(event, seq_id)
|
27
|
+
res = @http_transport.request(request_type: event.type, payload: payload.to_json)
|
28
|
+
Datadog.logger.debug { "Telemetry sent for event `#{event.type}` (code: #{res.code.inspect})" }
|
29
|
+
res
|
30
|
+
rescue => e
|
31
|
+
Datadog.logger.debug("Unable to send telemetry request for event `#{event.type rescue 'unknown'}`: #{e}")
|
32
|
+
Telemetry::Http::InternalErrorResponse.new(e)
|
35
33
|
end
|
36
34
|
|
37
35
|
# Initializes a Sequence object to track seq_id if not already initialized; else returns stored
|
@@ -3,17 +3,27 @@
|
|
3
3
|
module Datadog
|
4
4
|
module Core
|
5
5
|
module Telemetry
|
6
|
+
# Collection of telemetry events
|
6
7
|
class Event
|
8
|
+
extend Core::Utils::Forking
|
9
|
+
|
10
|
+
# returns sequence that increments every time the configuration changes
|
11
|
+
def self.configuration_sequence
|
12
|
+
after_fork! { @sequence = Datadog::Core::Utils::Sequence.new(1) }
|
13
|
+
@sequence ||= Datadog::Core::Utils::Sequence.new(1)
|
14
|
+
end
|
15
|
+
|
7
16
|
# Base class for all Telemetry V2 events.
|
8
17
|
class Base
|
9
18
|
# The type of the event.
|
10
19
|
# It must be one of the stings defined in the Telemetry V2
|
11
20
|
# specification for event names.
|
12
|
-
def type
|
21
|
+
def type
|
22
|
+
raise NotImplementedError, 'Must be implemented by subclass'
|
23
|
+
end
|
13
24
|
|
14
25
|
# The JSON payload for the event.
|
15
|
-
|
16
|
-
def payload(seq_id)
|
26
|
+
def payload
|
17
27
|
{}
|
18
28
|
end
|
19
29
|
end
|
@@ -24,8 +34,7 @@ module Datadog
|
|
24
34
|
'app-started'
|
25
35
|
end
|
26
36
|
|
27
|
-
def payload
|
28
|
-
@seq_id = seq_id
|
37
|
+
def payload
|
29
38
|
{
|
30
39
|
products: products,
|
31
40
|
configuration: configuration,
|
@@ -38,6 +47,7 @@ module Datadog
|
|
38
47
|
private
|
39
48
|
|
40
49
|
def products
|
50
|
+
# @type var products: Hash[Symbol, Hash[Symbol, Object]]
|
41
51
|
products = {
|
42
52
|
appsec: {
|
43
53
|
enabled: Datadog::AppSec.enabled?,
|
@@ -79,16 +89,19 @@ module Datadog
|
|
79
89
|
].freeze
|
80
90
|
|
81
91
|
# rubocop:disable Metrics/AbcSize
|
92
|
+
# rubocop:disable Metrics/MethodLength
|
82
93
|
def configuration
|
83
94
|
config = Datadog.configuration
|
95
|
+
seq_id = Event.configuration_sequence.next
|
84
96
|
|
85
97
|
list = [
|
86
|
-
conf_value('DD_AGENT_HOST', config.agent.host),
|
87
|
-
conf_value('DD_AGENT_TRANSPORT', agent_transport(config)),
|
88
|
-
conf_value('DD_TRACE_SAMPLE_RATE', to_value(config.tracing.sampling.default_rate)),
|
98
|
+
conf_value('DD_AGENT_HOST', config.agent.host, seq_id),
|
99
|
+
conf_value('DD_AGENT_TRANSPORT', agent_transport(config), seq_id),
|
100
|
+
conf_value('DD_TRACE_SAMPLE_RATE', to_value(config.tracing.sampling.default_rate), seq_id),
|
89
101
|
conf_value(
|
90
102
|
'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
|
91
|
-
config.tracing.contrib.global_default_service_name.enabled
|
103
|
+
config.tracing.contrib.global_default_service_name.enabled,
|
104
|
+
seq_id
|
92
105
|
),
|
93
106
|
]
|
94
107
|
|
@@ -97,32 +110,45 @@ module Datadog
|
|
97
110
|
peer_service_mapping = config.tracing.contrib.peer_service_mapping
|
98
111
|
peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
|
99
112
|
end
|
100
|
-
list << conf_value('DD_TRACE_PEER_SERVICE_MAPPING', peer_service_mapping_str)
|
113
|
+
list << conf_value('DD_TRACE_PEER_SERVICE_MAPPING', peer_service_mapping_str, seq_id)
|
101
114
|
|
102
115
|
# Whitelist of configuration options to send in additional payload object
|
103
116
|
TARGET_OPTIONS.each do |option|
|
104
117
|
split_option = option.split('.')
|
105
|
-
list << conf_value(option, to_value(config.dig(*split_option)))
|
118
|
+
list << conf_value(option, to_value(config.dig(*split_option)), seq_id)
|
106
119
|
end
|
107
120
|
|
108
121
|
# Add some more custom additional payload values here
|
109
122
|
list.push(
|
110
|
-
conf_value('tracing.auto_instrument.enabled', !defined?(Datadog::AutoInstrument::LOADED).nil
|
111
|
-
conf_value(
|
112
|
-
|
113
|
-
|
123
|
+
conf_value('tracing.auto_instrument.enabled', !defined?(Datadog::AutoInstrument::LOADED).nil?, seq_id),
|
124
|
+
conf_value(
|
125
|
+
'tracing.writer_options.buffer_size',
|
126
|
+
to_value(config.tracing.writer_options[:buffer_size]),
|
127
|
+
seq_id
|
128
|
+
),
|
129
|
+
conf_value(
|
130
|
+
'tracing.writer_options.flush_interval',
|
131
|
+
to_value(config.tracing.writer_options[:flush_interval]),
|
132
|
+
seq_id
|
133
|
+
),
|
134
|
+
conf_value(
|
135
|
+
'tracing.opentelemetry.enabled',
|
136
|
+
!defined?(Datadog::OpenTelemetry::LOADED).nil?,
|
137
|
+
seq_id
|
138
|
+
),
|
114
139
|
)
|
115
|
-
list << conf_value('logger.instance', config.logger.instance.class.to_s) if config.logger.instance
|
140
|
+
list << conf_value('logger.instance', config.logger.instance.class.to_s, seq_id) if config.logger.instance
|
116
141
|
if config.respond_to?('appsec')
|
117
|
-
list << conf_value('appsec.enabled', config.dig('appsec', 'enabled'))
|
118
|
-
list << conf_value('appsec.sca_enabled', config.dig('appsec', 'sca_enabled'))
|
142
|
+
list << conf_value('appsec.enabled', config.dig('appsec', 'enabled'), seq_id)
|
143
|
+
list << conf_value('appsec.sca_enabled', config.dig('appsec', 'sca_enabled'), seq_id)
|
119
144
|
end
|
120
|
-
list << conf_value('ci.enabled', config.dig('ci', 'enabled')) if config.respond_to?('ci')
|
145
|
+
list << conf_value('ci.enabled', config.dig('ci', 'enabled'), seq_id) if config.respond_to?('ci')
|
121
146
|
|
122
147
|
list.reject! { |entry| entry[:value].nil? }
|
123
148
|
list
|
124
149
|
end
|
125
150
|
# rubocop:enable Metrics/AbcSize
|
151
|
+
# rubocop:enable Metrics/MethodLength
|
126
152
|
|
127
153
|
def agent_transport(config)
|
128
154
|
adapter = Core::Configuration::AgentSettingsResolver.call(config).adapter
|
@@ -133,12 +159,12 @@ module Datadog
|
|
133
159
|
end
|
134
160
|
end
|
135
161
|
|
136
|
-
def conf_value(name, value, origin = 'code')
|
162
|
+
def conf_value(name, value, seq_id, origin = 'code')
|
137
163
|
{
|
138
164
|
name: name,
|
139
165
|
value: value,
|
140
166
|
origin: origin,
|
141
|
-
seq_id:
|
167
|
+
seq_id: seq_id,
|
142
168
|
}
|
143
169
|
end
|
144
170
|
|
@@ -168,7 +194,7 @@ module Datadog
|
|
168
194
|
'app-dependencies-loaded'
|
169
195
|
end
|
170
196
|
|
171
|
-
def payload
|
197
|
+
def payload
|
172
198
|
{ dependencies: dependencies }
|
173
199
|
end
|
174
200
|
|
@@ -191,7 +217,7 @@ module Datadog
|
|
191
217
|
'app-integrations-change'
|
192
218
|
end
|
193
219
|
|
194
|
-
def payload
|
220
|
+
def payload
|
195
221
|
{ integrations: integrations }
|
196
222
|
end
|
197
223
|
|
@@ -244,18 +270,20 @@ module Datadog
|
|
244
270
|
@origin = origin
|
245
271
|
end
|
246
272
|
|
247
|
-
def payload
|
248
|
-
{ configuration: configuration
|
273
|
+
def payload
|
274
|
+
{ configuration: configuration }
|
249
275
|
end
|
250
276
|
|
251
|
-
def configuration
|
277
|
+
def configuration
|
252
278
|
config = Datadog.configuration
|
279
|
+
seq_id = Event.configuration_sequence.next
|
253
280
|
|
254
281
|
res = @changes.map do |name, value|
|
255
282
|
{
|
256
283
|
name: name,
|
257
284
|
value: value,
|
258
285
|
origin: @origin,
|
286
|
+
seq_id: seq_id,
|
259
287
|
}
|
260
288
|
end
|
261
289
|
|
@@ -285,6 +313,84 @@ module Datadog
|
|
285
313
|
'app-closing'
|
286
314
|
end
|
287
315
|
end
|
316
|
+
|
317
|
+
# Telemetry class for the 'generate-metrics' event
|
318
|
+
class GenerateMetrics < Base
|
319
|
+
def type
|
320
|
+
'generate-metrics'
|
321
|
+
end
|
322
|
+
|
323
|
+
def initialize(namespace, metric_series)
|
324
|
+
super()
|
325
|
+
@namespace = namespace
|
326
|
+
@metric_series = metric_series
|
327
|
+
end
|
328
|
+
|
329
|
+
def payload
|
330
|
+
{
|
331
|
+
namespace: @namespace,
|
332
|
+
series: @metric_series.map(&:to_h)
|
333
|
+
}
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Telemetry class for the 'logs' event
|
338
|
+
class Log < Base
|
339
|
+
LEVELS = {
|
340
|
+
error: 'ERROR',
|
341
|
+
debug: 'DEBUG',
|
342
|
+
warn: 'WARN',
|
343
|
+
}.freeze
|
344
|
+
|
345
|
+
def type
|
346
|
+
'logs'
|
347
|
+
end
|
348
|
+
|
349
|
+
def initialize(message:, level:)
|
350
|
+
super()
|
351
|
+
@message = message
|
352
|
+
@level = LEVELS.fetch(level) { |k| raise ArgumentError, "Invalid log level :#{k}" }
|
353
|
+
end
|
354
|
+
|
355
|
+
def payload
|
356
|
+
{
|
357
|
+
logs: [{
|
358
|
+
message: @message,
|
359
|
+
level: @level,
|
360
|
+
# More optional fields to be added here...
|
361
|
+
}]
|
362
|
+
}
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# Telemetry class for the 'distributions' event
|
367
|
+
class Distributions < GenerateMetrics
|
368
|
+
def type
|
369
|
+
'distributions'
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
# Telemetry class for the 'message-batch' event
|
374
|
+
class MessageBatch
|
375
|
+
attr_reader :events
|
376
|
+
|
377
|
+
def type
|
378
|
+
'message-batch'
|
379
|
+
end
|
380
|
+
|
381
|
+
def initialize(events)
|
382
|
+
@events = events
|
383
|
+
end
|
384
|
+
|
385
|
+
def payload
|
386
|
+
@events.map do |event|
|
387
|
+
{
|
388
|
+
request_type: event.type,
|
389
|
+
payload: event.payload,
|
390
|
+
}
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
288
394
|
end
|
289
395
|
end
|
290
396
|
end
|
@@ -5,11 +5,14 @@ module Datadog
|
|
5
5
|
module Telemetry
|
6
6
|
module Ext
|
7
7
|
ENV_ENABLED = 'DD_INSTRUMENTATION_TELEMETRY_ENABLED'
|
8
|
+
ENV_METRICS_ENABLED = 'DD_TELEMETRY_METRICS_ENABLED'
|
8
9
|
ENV_HEARTBEAT_INTERVAL = 'DD_TELEMETRY_HEARTBEAT_INTERVAL'
|
10
|
+
ENV_METRICS_AGGREGATION_INTERVAL = 'DD_TELEMETRY_METRICS_AGGREGATION_INTERVAL'
|
9
11
|
ENV_DEPENDENCY_COLLECTION = 'DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED'
|
10
12
|
ENV_INSTALL_ID = 'DD_INSTRUMENTATION_INSTALL_ID'
|
11
13
|
ENV_INSTALL_TYPE = 'DD_INSTRUMENTATION_INSTALL_TYPE'
|
12
14
|
ENV_INSTALL_TIME = 'DD_INSTRUMENTATION_INSTALL_TIME'
|
15
|
+
ENV_AGENTLESS_URL_OVERRIDE = 'DD_TELEMETRY_AGENTLESS_URL'
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -15,7 +15,7 @@ module Datadog
|
|
15
15
|
:timeout,
|
16
16
|
:ssl
|
17
17
|
|
18
|
-
DEFAULT_TIMEOUT =
|
18
|
+
DEFAULT_TIMEOUT = 2
|
19
19
|
|
20
20
|
def initialize(hostname:, port: nil, timeout: DEFAULT_TIMEOUT, ssl: true)
|
21
21
|
@hostname = hostname
|
@@ -34,19 +34,17 @@ module Datadog
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def post(env)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
http.request(post)
|
43
|
-
end
|
44
|
-
|
45
|
-
Response.new(http_response)
|
46
|
-
rescue StandardError => e
|
47
|
-
Datadog.logger.debug("Unable to send telemetry event to agent: #{e}")
|
48
|
-
Telemetry::Http::InternalErrorResponse.new(e)
|
37
|
+
post = ::Net::HTTP::Post.new(env.path, env.headers)
|
38
|
+
post.body = env.body
|
39
|
+
|
40
|
+
http_response = open do |http|
|
41
|
+
http.request(post)
|
49
42
|
end
|
43
|
+
|
44
|
+
Response.new(http_response)
|
45
|
+
rescue StandardError => e
|
46
|
+
Datadog.logger.debug("Unable to send telemetry event to agent: #{e}")
|
47
|
+
Telemetry::Http::InternalErrorResponse.new(e)
|
50
48
|
end
|
51
49
|
|
52
50
|
# Data structure for an HTTP Response
|
@@ -17,7 +17,10 @@ module Datadog
|
|
17
17
|
CONTENT_TYPE_APPLICATION_JSON = 'application/json'
|
18
18
|
API_VERSION = 'v2'
|
19
19
|
|
20
|
+
AGENTLESS_HOST_PREFIX = 'instrumentation-telemetry-intake'
|
21
|
+
|
20
22
|
AGENT_ENDPOINT = '/telemetry/proxy/api/v2/apmtelemetry'
|
23
|
+
AGENTLESS_ENDPOINT = '/api/v2/apmtelemetry'
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../configuration/settings'
|
4
|
+
require_relative '../../environment/ext'
|
4
5
|
require_relative '../../transport/ext'
|
5
6
|
require_relative 'env'
|
6
7
|
require_relative 'ext'
|
@@ -13,18 +14,42 @@ module Datadog
|
|
13
14
|
# Class to send telemetry data to Telemetry API
|
14
15
|
# Currently only supports the HTTP protocol.
|
15
16
|
class Transport
|
17
|
+
def self.build_agent_transport(agent_settings)
|
18
|
+
Transport.new(
|
19
|
+
host: agent_settings.hostname,
|
20
|
+
port: agent_settings.port,
|
21
|
+
path: Http::Ext::AGENT_ENDPOINT
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.build_agentless_transport(api_key:, dd_site:, url_override: nil)
|
26
|
+
url = url_override || "https://#{Http::Ext::AGENTLESS_HOST_PREFIX}.#{dd_site}:443"
|
27
|
+
|
28
|
+
uri = URI.parse(url)
|
29
|
+
raise "Invalid agentless mode URL: #{url}" if uri.host.nil?
|
30
|
+
|
31
|
+
Transport.new(
|
32
|
+
host: uri.host,
|
33
|
+
port: uri.port || 80,
|
34
|
+
path: Http::Ext::AGENTLESS_ENDPOINT,
|
35
|
+
ssl: uri.scheme == 'https' || uri.port == 443,
|
36
|
+
api_key: api_key
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
16
40
|
attr_reader \
|
17
41
|
:host,
|
18
42
|
:port,
|
19
43
|
:ssl,
|
20
|
-
:path
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@host =
|
25
|
-
@port =
|
26
|
-
@ssl =
|
27
|
-
@path =
|
44
|
+
:path,
|
45
|
+
:api_key
|
46
|
+
|
47
|
+
def initialize(host:, port:, path:, ssl: false, api_key: nil)
|
48
|
+
@host = host
|
49
|
+
@port = port
|
50
|
+
@ssl = ssl
|
51
|
+
@path = path
|
52
|
+
@api_key = api_key
|
28
53
|
end
|
29
54
|
|
30
55
|
def request(request_type:, payload:)
|
@@ -38,7 +63,7 @@ module Datadog
|
|
38
63
|
private
|
39
64
|
|
40
65
|
def headers(request_type:, api_version: Http::Ext::API_VERSION)
|
41
|
-
{
|
66
|
+
result = {
|
42
67
|
Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST => '1',
|
43
68
|
Ext::HEADER_CONTENT_TYPE => Http::Ext::CONTENT_TYPE_APPLICATION_JSON,
|
44
69
|
Ext::HEADER_DD_TELEMETRY_API_VERSION => api_version,
|
@@ -49,6 +74,10 @@ module Datadog
|
|
49
74
|
# Enable debug mode for telemetry
|
50
75
|
# HEADER_TELEMETRY_DEBUG_ENABLED => 'true',
|
51
76
|
}
|
77
|
+
|
78
|
+
result[Ext::HEADER_DD_API_KEY] = api_key unless api_key.nil?
|
79
|
+
|
80
|
+
result
|
52
81
|
end
|
53
82
|
|
54
83
|
def adapter
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'event'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Core
|
7
|
+
module Telemetry
|
8
|
+
# Logging interface for sending telemetry logs.
|
9
|
+
#
|
10
|
+
# Reporting internal error so that we can fix them.
|
11
|
+
# IMPORTANT: Make sure to not log any sensitive information.
|
12
|
+
module Logging
|
13
|
+
module_function
|
14
|
+
|
15
|
+
def report(exception, level:)
|
16
|
+
# Annoymous exceptions to be logged as <Class:0x00007f8b1c0b3b40>
|
17
|
+
message = exception.class.name || exception.class.inspect
|
18
|
+
|
19
|
+
event = Event::Log.new(
|
20
|
+
message: message,
|
21
|
+
level: level
|
22
|
+
)
|
23
|
+
|
24
|
+
if (telemetry = Datadog.send(:components).telemetry)
|
25
|
+
telemetry.log!(event)
|
26
|
+
else
|
27
|
+
Datadog.logger.debug do
|
28
|
+
"Attempting to send telemetry log when telemetry component is not ready: #{message}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Core
|
5
|
+
module Telemetry
|
6
|
+
# Telemetry metrics data model (internal Datadog metrics for client libraries)
|
7
|
+
module Metric
|
8
|
+
# Base class for all metric types
|
9
|
+
class Base
|
10
|
+
attr_reader :name, :tags, :values, :common
|
11
|
+
|
12
|
+
# @param name [String] metric name
|
13
|
+
# @param tags [Array<String>|Hash{String=>String}] metric tags as hash or array of "tag:val" strings
|
14
|
+
# @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric
|
15
|
+
def initialize(name, tags: {}, common: true)
|
16
|
+
@name = name
|
17
|
+
@values = []
|
18
|
+
@tags = tags_to_array(tags)
|
19
|
+
@common = common
|
20
|
+
end
|
21
|
+
|
22
|
+
def id
|
23
|
+
@id ||= "#{type}::#{name}::#{tags.join(',')}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def track(value)
|
27
|
+
raise NotImplementedError, 'method must be implemented in subclasses'
|
28
|
+
end
|
29
|
+
|
30
|
+
def type
|
31
|
+
raise NotImplementedError, 'method must be implemented in subclasses'
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_h
|
35
|
+
{
|
36
|
+
metric: name,
|
37
|
+
points: values,
|
38
|
+
type: type,
|
39
|
+
tags: tags,
|
40
|
+
common: common
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def tags_to_array(tags)
|
47
|
+
return tags if tags.is_a?(Array)
|
48
|
+
|
49
|
+
tags.map { |k, v| "#{k}:#{v}" }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Base class for metrics that require aggregation interval
|
54
|
+
class IntervalMetric < Base
|
55
|
+
attr_reader :interval
|
56
|
+
|
57
|
+
# @param name [String] metric name
|
58
|
+
# @param tags [Array<String>|Hash{String=>String}] metric tags as hash of array of "tag:val" strings
|
59
|
+
# @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric
|
60
|
+
# @param interval [Integer] metrics aggregation interval in seconds
|
61
|
+
def initialize(name, interval:, tags: {}, common: true)
|
62
|
+
raise ArgumentError, 'interval must be a positive number' if interval.nil? || interval <= 0
|
63
|
+
|
64
|
+
super(name, tags: tags, common: common)
|
65
|
+
|
66
|
+
@interval = interval
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_h
|
70
|
+
res = super
|
71
|
+
res[:interval] = interval
|
72
|
+
res
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Count metric adds up all the submitted values in a time interval. This would be suitable for a
|
77
|
+
# metric tracking the number of website hits, for instance.
|
78
|
+
class Count < Base
|
79
|
+
TYPE = 'count'
|
80
|
+
|
81
|
+
def type
|
82
|
+
TYPE
|
83
|
+
end
|
84
|
+
|
85
|
+
def track(value)
|
86
|
+
value = value.to_i
|
87
|
+
|
88
|
+
if values.empty?
|
89
|
+
values << [Time.now.to_i, value]
|
90
|
+
else
|
91
|
+
values[0][0] = Time.now.to_i
|
92
|
+
values[0][1] += value
|
93
|
+
end
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# A gauge type takes the last value reported during the interval. This type would make sense for tracking RAM or
|
99
|
+
# CPU usage, where taking the last value provides a representative picture of the host’s behavior during the time
|
100
|
+
# interval.
|
101
|
+
class Gauge < IntervalMetric
|
102
|
+
TYPE = 'gauge'
|
103
|
+
|
104
|
+
def type
|
105
|
+
TYPE
|
106
|
+
end
|
107
|
+
|
108
|
+
def track(value)
|
109
|
+
if values.empty?
|
110
|
+
values << [Time.now.to_i, value]
|
111
|
+
else
|
112
|
+
values[0][0] = Time.now.to_i
|
113
|
+
values[0][1] = value
|
114
|
+
end
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# The rate type takes the count and divides it by the length of the time interval. This is useful if you’re
|
120
|
+
# interested in the number of hits per second.
|
121
|
+
class Rate < IntervalMetric
|
122
|
+
TYPE = 'rate'
|
123
|
+
|
124
|
+
def initialize(name, interval:, tags: {}, common: true)
|
125
|
+
super
|
126
|
+
|
127
|
+
@value = 0.0
|
128
|
+
end
|
129
|
+
|
130
|
+
def type
|
131
|
+
TYPE
|
132
|
+
end
|
133
|
+
|
134
|
+
def track(value = 1.0)
|
135
|
+
@value += value
|
136
|
+
@values = [[Time.now.to_i, @value / interval]]
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Distribution metric represents the global statistical distribution of a set of values.
|
142
|
+
class Distribution < Base
|
143
|
+
TYPE = 'distributions'
|
144
|
+
|
145
|
+
def type
|
146
|
+
TYPE
|
147
|
+
end
|
148
|
+
|
149
|
+
def track(value)
|
150
|
+
values << value
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
|
154
|
+
# distribution metric data does not have type field
|
155
|
+
def to_h
|
156
|
+
{
|
157
|
+
metric: name,
|
158
|
+
points: values,
|
159
|
+
tags: tags,
|
160
|
+
common: common
|
161
|
+
}
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|