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.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -1
  3. data/ext/datadog_profiling_loader/extconf.rb +15 -15
  4. data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
  5. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
  6. data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
  7. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +132 -44
  8. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
  10. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
  11. data/ext/datadog_profiling_native_extension/collectors_stack.c +90 -37
  12. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  13. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
  15. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
  17. data/ext/datadog_profiling_native_extension/extconf.rb +69 -62
  18. data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
  19. data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
  20. data/ext/datadog_profiling_native_extension/helpers.h +6 -17
  21. data/ext/datadog_profiling_native_extension/http_transport.c +3 -3
  22. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
  23. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
  24. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -126
  25. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
  26. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
  27. data/ext/datadog_profiling_native_extension/profiling.c +0 -2
  28. data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
  29. data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
  30. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
  31. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
  32. data/ext/datadog_profiling_native_extension/stack_recorder.c +27 -8
  33. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
  34. data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
  35. data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
  36. data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +20 -7
  37. data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
  38. data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
  39. data/ext/libdatadog_api/extconf.rb +108 -0
  40. data/ext/libdatadog_api/macos_development.md +26 -0
  41. data/ext/libdatadog_extconf_helpers.rb +130 -0
  42. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
  43. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
  44. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
  45. data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
  46. data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
  47. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
  48. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
  49. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  50. data/lib/datadog/appsec/extensions.rb +1 -0
  51. data/lib/datadog/appsec/processor/actions.rb +1 -1
  52. data/lib/datadog/appsec/response.rb +15 -1
  53. data/lib/datadog/appsec.rb +1 -0
  54. data/lib/datadog/core/configuration/components.rb +17 -12
  55. data/lib/datadog/core/configuration/settings.rb +93 -7
  56. data/lib/datadog/core/configuration.rb +3 -17
  57. data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
  58. data/lib/datadog/core/crashtracking/component.rb +111 -0
  59. data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
  60. data/lib/datadog/core/deprecations.rb +58 -0
  61. data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
  62. data/lib/datadog/core/environment/yjit.rb +5 -0
  63. data/lib/datadog/core/runtime/ext.rb +1 -0
  64. data/lib/datadog/core/runtime/metrics.rb +6 -0
  65. data/lib/datadog/core/telemetry/component.rb +154 -0
  66. data/lib/datadog/core/telemetry/emitter.rb +9 -11
  67. data/lib/datadog/core/telemetry/event.rb +132 -26
  68. data/lib/datadog/core/telemetry/ext.rb +3 -0
  69. data/lib/datadog/core/telemetry/http/adapters/net.rb +11 -13
  70. data/lib/datadog/core/telemetry/http/ext.rb +3 -0
  71. data/lib/datadog/core/telemetry/http/transport.rb +38 -9
  72. data/lib/datadog/core/telemetry/logging.rb +35 -0
  73. data/lib/datadog/core/telemetry/metric.rb +167 -0
  74. data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
  75. data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
  76. data/lib/datadog/core/telemetry/request.rb +1 -1
  77. data/lib/datadog/core/telemetry/worker.rb +173 -0
  78. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
  79. data/lib/datadog/core/utils/only_once_successful.rb +76 -0
  80. data/lib/datadog/core.rb +2 -19
  81. data/lib/datadog/kit/appsec/events.rb +2 -4
  82. data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
  83. data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -2
  84. data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
  85. data/lib/datadog/profiling/collectors/code_provenance.rb +24 -11
  86. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
  87. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
  88. data/lib/datadog/profiling/collectors/info.rb +3 -3
  89. data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
  90. data/lib/datadog/profiling/component.rb +85 -90
  91. data/lib/datadog/profiling/exporter.rb +3 -3
  92. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
  93. data/lib/datadog/profiling/ext.rb +21 -21
  94. data/lib/datadog/profiling/flush.rb +1 -1
  95. data/lib/datadog/profiling/http_transport.rb +8 -6
  96. data/lib/datadog/profiling/load_native_extension.rb +5 -5
  97. data/lib/datadog/profiling/preload.rb +1 -1
  98. data/lib/datadog/profiling/profiler.rb +5 -8
  99. data/lib/datadog/profiling/scheduler.rb +31 -25
  100. data/lib/datadog/profiling/tag_builder.rb +2 -2
  101. data/lib/datadog/profiling/tasks/exec.rb +5 -5
  102. data/lib/datadog/profiling/tasks/setup.rb +16 -35
  103. data/lib/datadog/profiling.rb +5 -5
  104. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  105. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
  106. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
  107. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
  108. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
  109. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
  110. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
  111. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
  112. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  113. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  114. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  115. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  116. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  117. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  118. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  119. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  120. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  121. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  122. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -1
  123. data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
  124. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
  125. data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
  126. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
  127. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
  128. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
  129. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
  130. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
  131. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
  132. data/lib/datadog/tracing/contrib/analytics.rb +5 -0
  133. data/lib/datadog/tracing/contrib/ext.rb +14 -0
  134. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
  135. data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
  136. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
  137. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +28 -0
  138. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
  139. data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
  140. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
  141. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
  142. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
  143. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
  144. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
  145. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
  146. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
  147. data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
  148. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  149. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
  150. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
  151. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
  152. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
  153. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
  154. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
  155. data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
  156. data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
  157. data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
  158. data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
  159. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
  160. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
  161. data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
  162. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  163. data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
  164. data/lib/datadog/tracing/distributed/datadog.rb +2 -2
  165. data/lib/datadog/tracing/distributed/propagation.rb +9 -2
  166. data/lib/datadog/tracing/distributed/trace_context.rb +3 -2
  167. data/lib/datadog/tracing/metadata/errors.rb +9 -1
  168. data/lib/datadog/tracing/metadata/ext.rb +4 -0
  169. data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
  170. data/lib/datadog/tracing/span.rb +9 -2
  171. data/lib/datadog/tracing/span_event.rb +41 -0
  172. data/lib/datadog/tracing/span_operation.rb +9 -4
  173. data/lib/datadog/tracing/trace_operation.rb +7 -3
  174. data/lib/datadog/tracing/trace_segment.rb +4 -1
  175. data/lib/datadog/tracing/tracer.rb +9 -2
  176. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
  177. data/lib/datadog/tracing.rb +5 -1
  178. data/lib/datadog/version.rb +2 -2
  179. metadata +43 -12
  180. data/lib/datadog/core/telemetry/client.rb +0 -95
  181. data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
  182. data/lib/datadog/profiling/crashtracker.rb +0 -91
  183. data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -1,11 +1,16 @@
1
1
  # rubocop:disable Style/StderrPuts
2
2
  # rubocop:disable Style/GlobalVars
3
3
 
4
- require_relative 'native_extension_helpers'
4
+ require_relative "native_extension_helpers"
5
+ require_relative "../libdatadog_extconf_helpers"
5
6
 
6
7
  SKIPPED_REASON_FILE = "#{__dir__}/skipped_reason.txt".freeze
7
8
  # Not a problem if the file doesn't exist or we can't delete it
8
- File.delete(SKIPPED_REASON_FILE) rescue nil
9
+ begin
10
+ File.delete(SKIPPED_REASON_FILE)
11
+ rescue
12
+ nil
13
+ end
9
14
 
10
15
  def skip_building_extension!(reason)
11
16
  fail_install_if_missing_extension =
@@ -24,13 +29,13 @@ def skip_building_extension!(reason)
24
29
  )
25
30
 
26
31
  if fail_install_if_missing_extension
27
- require 'mkmf'
32
+ require "mkmf"
28
33
  Logging.message(
29
- '[datadog] Failure cause: ' \
34
+ "[datadog] Failure cause: " \
30
35
  "#{Datadog::Profiling::NativeExtensionHelpers::Supported.render_skipped_reason_file(**reason)}\n"
31
36
  )
32
37
  else
33
- File.write('Makefile', 'all install clean: # dummy makefile that does nothing')
38
+ File.write("Makefile", "all install clean: # dummy makefile that does nothing")
34
39
  end
35
40
 
36
41
  exit
@@ -63,17 +68,17 @@ $stderr.puts(
63
68
 
64
69
  # NOTE: we MUST NOT require 'mkmf' before we check the #skip_building_extension? because the require triggers checks
65
70
  # that may fail on an environment not properly setup for building Ruby extensions.
66
- require 'mkmf'
71
+ require "mkmf"
67
72
 
68
73
  Logging.message("[datadog] Using compiler:\n")
69
- xsystem("#{CONFIG['CC']} -v")
74
+ xsystem("#{CONFIG["CC"]} -v")
70
75
  Logging.message("[datadog] End of compiler information\n")
71
76
 
72
77
  # mkmf on modern Rubies actually has an append_cflags that does something similar
73
78
  # (see https://github.com/ruby/ruby/pull/5760), but as usual we need a bit more boilerplate to deal with legacy Rubies
74
79
  def add_compiler_flag(flag)
75
80
  if try_cflags(flag)
76
- $CFLAGS << ' ' << flag
81
+ $CFLAGS << " " << flag
77
82
  else
78
83
  $stderr.puts("WARNING: '#{flag}' not accepted by compiler, skipping it")
79
84
  end
@@ -81,23 +86,23 @@ end
81
86
 
82
87
  # Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
83
88
  # But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
84
- add_compiler_flag '-Werror' if ENV['DATADOG_GEM_CI'] == 'true'
89
+ add_compiler_flag "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
85
90
 
86
91
  # Older gcc releases may not default to C99 and we need to ask for this. This is also used:
87
92
  # * by upstream Ruby -- search for gnu99 in the codebase
88
93
  # * by msgpack, another datadog gem dependency
89
94
  # (https://github.com/msgpack/msgpack-ruby/blob/18ce08f6d612fe973843c366ac9a0b74c4e50599/ext/msgpack/extconf.rb#L8)
90
- add_compiler_flag '-std=gnu99'
95
+ add_compiler_flag "-std=gnu99"
91
96
 
92
97
  # Gets really noisy when we include the MJIT header, let's omit it (TODO: Use #pragma GCC diagnostic instead?)
93
- add_compiler_flag '-Wno-unused-function'
98
+ add_compiler_flag "-Wno-unused-function"
94
99
 
95
100
  # Allow defining variables at any point in a function
96
- add_compiler_flag '-Wno-declaration-after-statement'
101
+ add_compiler_flag "-Wno-declaration-after-statement"
97
102
 
98
103
  # If we forget to include a Ruby header, the function call may still appear to work, but then
99
104
  # cause a segfault later. Let's ensure that never happens.
100
- add_compiler_flag '-Werror-implicit-function-declaration'
105
+ add_compiler_flag "-Werror-implicit-function-declaration"
101
106
 
102
107
  # The native extension is not intended to expose any symbols/functions for other native libraries to use;
103
108
  # the sole exception being `Init_datadog_profiling_native_extension` which needs to be visible for Ruby to call it when
@@ -105,22 +110,22 @@ add_compiler_flag '-Werror-implicit-function-declaration'
105
110
  #
106
111
  # By setting this compiler flag, we tell it to assume that everything is private unless explicitly stated.
107
112
  # For more details see https://gcc.gnu.org/wiki/Visibility
108
- add_compiler_flag '-fvisibility=hidden'
113
+ add_compiler_flag "-fvisibility=hidden"
109
114
 
110
115
  # Avoid legacy C definitions
111
- add_compiler_flag '-Wold-style-definition'
116
+ add_compiler_flag "-Wold-style-definition"
112
117
 
113
118
  # Enable all other compiler warnings
114
- add_compiler_flag '-Wall'
115
- add_compiler_flag '-Wextra'
119
+ add_compiler_flag "-Wall"
120
+ add_compiler_flag "-Wextra"
116
121
 
117
- if ENV['DDTRACE_DEBUG']
118
- $defs << '-DDD_DEBUG'
119
- CONFIG['optflags'] = '-O0'
120
- CONFIG['debugflags'] = '-ggdb3'
122
+ if ENV["DDTRACE_DEBUG"] == "true"
123
+ $defs << "-DDD_DEBUG"
124
+ CONFIG["optflags"] = "-O0"
125
+ CONFIG["debugflags"] = "-ggdb3"
121
126
  end
122
127
 
123
- if RUBY_PLATFORM.include?('linux')
128
+ if RUBY_PLATFORM.include?("linux")
124
129
  # Supposedly, the correct way to do this is
125
130
  # ```
126
131
  # have_library 'pthread'
@@ -128,77 +133,77 @@ if RUBY_PLATFORM.include?('linux')
128
133
  # ```
129
134
  # but it's slower to build
130
135
  # so instead we just assume that we have the function we need on Linux, and nowhere else
131
- $defs << '-DHAVE_PTHREAD_GETCPUCLOCKID'
136
+ $defs << "-DHAVE_PTHREAD_GETCPUCLOCKID"
137
+
138
+ # Not available on macOS
139
+ $defs << "-DHAVE_CLOCK_MONOTONIC_COARSE"
132
140
  end
133
141
 
134
- have_func 'malloc_stats'
142
+ have_func "malloc_stats"
135
143
 
136
144
  # On older Rubies, rb_postponed_job_preregister/rb_postponed_job_trigger did not exist
137
- $defs << '-DNO_POSTPONED_TRIGGER' if RUBY_VERSION < '3.3'
145
+ $defs << "-DNO_POSTPONED_TRIGGER" if RUBY_VERSION < "3.3"
138
146
 
139
147
  # On older Rubies, M:N threads were not available
140
- $defs << '-DNO_MN_THREADS_AVAILABLE' if RUBY_VERSION < '3.3'
148
+ $defs << "-DNO_MN_THREADS_AVAILABLE" if RUBY_VERSION < "3.3"
141
149
 
142
150
  # On older Rubies, we did not need to include the ractor header (this was built into the MJIT header)
143
- $defs << '-DNO_RACTOR_HEADER_INCLUDE' if RUBY_VERSION < '3.3'
151
+ $defs << "-DNO_RACTOR_HEADER_INCLUDE" if RUBY_VERSION < "3.3"
144
152
 
145
153
  # On older Rubies, some of the Ractor internal APIs were directly accessible
146
- $defs << '-DUSE_RACTOR_INTERNAL_APIS_DIRECTLY' if RUBY_VERSION < '3.3'
154
+ $defs << "-DUSE_RACTOR_INTERNAL_APIS_DIRECTLY" if RUBY_VERSION < "3.3"
147
155
 
148
156
  # On older Rubies, there was no struct rb_native_thread. See private_vm_api_acccess.c for details.
149
- $defs << '-DNO_RB_NATIVE_THREAD' if RUBY_VERSION < '3.2'
157
+ $defs << "-DNO_RB_NATIVE_THREAD" if RUBY_VERSION < "3.2"
150
158
 
151
159
  # On older Rubies, there was no struct rb_thread_sched (it was struct rb_global_vm_lock_struct)
152
- $defs << '-DNO_RB_THREAD_SCHED' if RUBY_VERSION < '3.2'
160
+ $defs << "-DNO_RB_THREAD_SCHED" if RUBY_VERSION < "3.2"
153
161
 
154
162
  # On older Rubies, the first_lineno inside a location was a VALUE and not a int (https://github.com/ruby/ruby/pull/6430)
155
- $defs << '-DNO_INT_FIRST_LINENO' if RUBY_VERSION < '3.2'
163
+ $defs << "-DNO_INT_FIRST_LINENO" if RUBY_VERSION < "3.2"
156
164
 
157
165
  # On older Rubies, "pop" was not a primitive operation
158
- $defs << '-DNO_PRIMITIVE_POP' if RUBY_VERSION < '3.2'
166
+ $defs << "-DNO_PRIMITIVE_POP" if RUBY_VERSION < "3.2"
159
167
 
160
168
  # On older Rubies, there was no tid member in the internal thread structure
161
- $defs << '-DNO_THREAD_TID' if RUBY_VERSION < '3.1'
169
+ $defs << "-DNO_THREAD_TID" if RUBY_VERSION < "3.1"
162
170
 
163
171
  # On older Rubies, there was no jit_return member on the rb_control_frame_t struct
164
- $defs << '-DNO_JIT_RETURN' if RUBY_VERSION < '3.1'
172
+ $defs << "-DNO_JIT_RETURN" if RUBY_VERSION < "3.1"
165
173
 
166
174
  # On older Rubies, rb_gc_force_recycle allowed to free objects in a way that
167
175
  # would be invisible to free tracepoints, finalizers and without cleaning
168
176
  # obj_to_id_tbl mappings.
169
- $defs << '-DHAVE_WORKING_RB_GC_FORCE_RECYCLE' if RUBY_VERSION < '3.1'
170
-
171
- # On older Rubies, we need to use a backported version of this function. See private_vm_api_access.h for details.
172
- $defs << '-DUSE_BACKPORTED_RB_PROFILE_FRAME_METHOD_NAME' if RUBY_VERSION < '3'
177
+ $defs << "-DHAVE_WORKING_RB_GC_FORCE_RECYCLE" if RUBY_VERSION < "3.1"
173
178
 
174
179
  # On older Rubies, there are no Ractors
175
- $defs << '-DNO_RACTORS' if RUBY_VERSION < '3'
180
+ $defs << "-DNO_RACTORS" if RUBY_VERSION < "3"
176
181
 
177
182
  # On older Rubies, rb_imemo_name did not exist
178
- $defs << '-DNO_IMEMO_NAME' if RUBY_VERSION < '3'
183
+ $defs << "-DNO_IMEMO_NAME" if RUBY_VERSION < "3"
179
184
 
180
185
  # On older Rubies, objects would not move
181
- $defs << '-DNO_T_MOVED' if RUBY_VERSION < '2.7'
186
+ $defs << "-DNO_T_MOVED" if RUBY_VERSION < "2.7"
182
187
 
183
188
  # On older Rubies, there was no RUBY_SEEN_OBJ_ID flag
184
- $defs << '-DNO_SEEN_OBJ_ID_FLAG' if RUBY_VERSION < '2.7'
189
+ $defs << "-DNO_SEEN_OBJ_ID_FLAG" if RUBY_VERSION < "2.7"
185
190
 
186
191
  # On older Rubies, rb_global_vm_lock_struct did not include the owner field
187
- $defs << '-DNO_GVL_OWNER' if RUBY_VERSION < '2.6'
192
+ $defs << "-DNO_GVL_OWNER" if RUBY_VERSION < "2.6"
188
193
 
189
194
  # On older Rubies, there was no thread->invoke_arg
190
- $defs << '-DNO_THREAD_INVOKE_ARG' if RUBY_VERSION < '2.6'
195
+ $defs << "-DNO_THREAD_INVOKE_ARG" if RUBY_VERSION < "2.6"
191
196
 
192
197
  # If we got here, libdatadog is available and loaded
193
- ENV['PKG_CONFIG_PATH'] = "#{ENV['PKG_CONFIG_PATH']}:#{Libdatadog.pkgconfig_folder}"
194
- Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV['PKG_CONFIG_PATH'].inspect}\n")
198
+ ENV["PKG_CONFIG_PATH"] = "#{ENV["PKG_CONFIG_PATH"]}:#{Libdatadog.pkgconfig_folder}"
199
+ Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV["PKG_CONFIG_PATH"].inspect}\n")
195
200
  $stderr.puts("Using libdatadog #{Libdatadog::VERSION} from #{Libdatadog.pkgconfig_folder}")
196
201
 
197
- unless pkg_config('datadog_profiling_with_rpath')
202
+ unless pkg_config("datadog_profiling_with_rpath")
198
203
  Logging.message("[datadog] Ruby detected the pkg-config command is #{$PKGCONFIG.inspect}\n")
199
204
 
200
205
  skip_building_extension!(
201
- if Datadog::Profiling::NativeExtensionHelpers::Supported.pkg_config_missing?
206
+ if Datadog::LibdatadogExtconfHelpers.pkg_config_missing?
202
207
  Datadog::Profiling::NativeExtensionHelpers::Supported::PKG_CONFIG_IS_MISSING
203
208
  else
204
209
  # Less specific error message
@@ -207,16 +212,18 @@ unless pkg_config('datadog_profiling_with_rpath')
207
212
  )
208
213
  end
209
214
 
210
- unless have_type('atomic_int', ['stdatomic.h'])
215
+ unless have_type("atomic_int", ["stdatomic.h"])
211
216
  skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
212
217
  end
213
218
 
214
- # See comments on the helper method being used for why we need to additionally set this.
219
+ # See comments on the helper methods being used for why we need to additionally set this.
215
220
  # The extremely excessive escaping around ORIGIN below seems to be correct and was determined after a lot of
216
221
  # experimentation. We need to get these special characters across a lot of tools untouched...
217
- $LDFLAGS += \
218
- ' -Wl,-rpath,$$$\\\\{ORIGIN\\}/' \
219
- "#{Datadog::Profiling::NativeExtensionHelpers.libdatadog_folder_relative_to_native_lib_folder}"
222
+ extra_relative_rpaths = [
223
+ Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_native_lib_folder(current_folder: __dir__),
224
+ *Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_ruby_extensions_folders,
225
+ ]
226
+ extra_relative_rpaths.each { |folder| $LDFLAGS += " -Wl,-rpath,$$$\\\\{ORIGIN\\}/#{folder.to_str}" }
220
227
  Logging.message("[datadog] After pkg-config $LDFLAGS were set to: #{$LDFLAGS.inspect}\n")
221
228
 
222
229
  # Tag the native extension library with the Ruby version and Ruby platform.
@@ -235,8 +242,8 @@ if Datadog::Profiling::NativeExtensionHelpers::CAN_USE_MJIT_HEADER
235
242
  # use the MJIT header.
236
243
  # Finally, the `COMMON_HEADERS` conflict with the MJIT header so we need to temporarily disable them for this check.
237
244
  original_common_headers = MakeMakefile::COMMON_HEADERS
238
- MakeMakefile::COMMON_HEADERS = ''.freeze
239
- unless have_macro('RUBY_MJIT_H', mjit_header_file_name)
245
+ MakeMakefile::COMMON_HEADERS = "".freeze
246
+ unless have_macro("RUBY_MJIT_H", mjit_header_file_name)
240
247
  skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILATION_BROKEN)
241
248
  end
242
249
  MakeMakefile::COMMON_HEADERS = original_common_headers
@@ -248,7 +255,7 @@ if Datadog::Profiling::NativeExtensionHelpers::CAN_USE_MJIT_HEADER
248
255
 
249
256
  # Warn on unused parameters to functions. Use `DDTRACE_UNUSED` to mark things as known-to-not-be-used.
250
257
  # See the comment on the same flag below for why this is done last.
251
- add_compiler_flag '-Wunused-parameter'
258
+ add_compiler_flag "-Wunused-parameter"
252
259
 
253
260
  create_makefile EXTENSION_NAME
254
261
  else
@@ -259,23 +266,23 @@ else
259
266
 
260
267
  create_header
261
268
 
262
- require 'debase/ruby_core_source'
263
- dir_config('ruby') # allow user to pass in non-standard core include directory
269
+ require "debase/ruby_core_source"
270
+ dir_config("ruby") # allow user to pass in non-standard core include directory
264
271
 
265
272
  Debase::RubyCoreSource
266
273
  .create_makefile_with_core(
267
274
  proc do
268
275
  headers_available =
269
- have_header('vm_core.h') &&
270
- have_header('iseq.h') &&
271
- (RUBY_VERSION < '3.3' || have_header('ractor_core.h'))
276
+ have_header("vm_core.h") &&
277
+ have_header("iseq.h") &&
278
+ (RUBY_VERSION < "3.3" || have_header("ractor_core.h"))
272
279
 
273
280
  if headers_available
274
281
  # Warn on unused parameters to functions. Use `DDTRACE_UNUSED` to mark things as known-to-not-be-used.
275
282
  # This is added as late as possible because in some Rubies we support (e.g. 3.3), adding this flag before
276
283
  # checking if internal VM headers are available causes those checks to fail because of this warning (and not
277
284
  # because the headers are not available.)
278
- add_compiler_flag '-Wunused-parameter'
285
+ add_compiler_flag "-Wunused-parameter"
279
286
  end
280
287
 
281
288
  headers_available
@@ -166,6 +166,12 @@ struct heap_recorder {
166
166
  size_t objects_frozen;
167
167
  } stats_last_update;
168
168
  };
169
+
170
+ struct end_heap_allocation_args {
171
+ struct heap_recorder *heap_recorder;
172
+ ddog_prof_Slice_Location locations;
173
+ };
174
+
169
175
  static heap_record* get_or_create_heap_record(heap_recorder*, ddog_prof_Slice_Location);
170
176
  static void cleanup_heap_record_if_unused(heap_recorder*, heap_record*);
171
177
  static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record);
@@ -176,6 +182,7 @@ static int st_object_records_iterate(st_data_t, st_data_t, st_data_t);
176
182
  static int st_object_records_debug(st_data_t key, st_data_t value, st_data_t extra);
177
183
  static int update_object_record_entry(st_data_t*, st_data_t*, st_data_t, int);
178
184
  static void commit_recording(heap_recorder*, heap_record*, recording);
185
+ static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args);
179
186
 
180
187
  // ==========================
181
188
  // Heap Recorder External API
@@ -219,7 +226,7 @@ void heap_recorder_free(heap_recorder *heap_recorder) {
219
226
  st_foreach(heap_recorder->heap_records, st_heap_record_entry_free, 0);
220
227
  st_free_table(heap_recorder->heap_records);
221
228
 
222
- if (heap_recorder->active_recording.object_record != NULL) {
229
+ if (heap_recorder->active_recording.object_record != NULL && heap_recorder->active_recording.object_record != &SKIPPED_RECORD) {
223
230
  // If there's a partial object record, clean it up as well
224
231
  object_record_free(heap_recorder->active_recording.object_record);
225
232
  }
@@ -340,9 +347,28 @@ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj
340
347
  };
341
348
  }
342
349
 
343
- void end_heap_allocation_recording(struct heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
350
+ // end_heap_allocation_recording_with_rb_protect gets called while the stack_recorder is holding one of the profile
351
+ // locks. To enable us to correctly unlock the profile on exception, we wrap the call to end_heap_allocation_recording
352
+ // with an rb_protect.
353
+ __attribute__((warn_unused_result))
354
+ int end_heap_allocation_recording_with_rb_protect(struct heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
355
+ int exception_state;
356
+ struct end_heap_allocation_args end_heap_allocation_args = {
357
+ .heap_recorder = heap_recorder,
358
+ .locations = locations,
359
+ };
360
+ rb_protect(end_heap_allocation_recording, (VALUE) &end_heap_allocation_args, &exception_state);
361
+ return exception_state;
362
+ }
363
+
364
+ static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args) {
365
+ struct end_heap_allocation_args *args = (struct end_heap_allocation_args *) end_heap_allocation_args;
366
+
367
+ struct heap_recorder *heap_recorder = args->heap_recorder;
368
+ ddog_prof_Slice_Location locations = args->locations;
369
+
344
370
  if (heap_recorder == NULL) {
345
- return;
371
+ return Qnil;
346
372
  }
347
373
 
348
374
  recording active_recording = heap_recorder->active_recording;
@@ -356,15 +382,16 @@ void end_heap_allocation_recording(struct heap_recorder *heap_recorder, ddog_pro
356
382
  // data required for committing though.
357
383
  heap_recorder->active_recording = (recording) {0};
358
384
 
359
- if (active_recording.object_record == &SKIPPED_RECORD) {
360
- // special marker when we decided to skip due to sampling
361
- return;
385
+ if (active_recording.object_record == &SKIPPED_RECORD) { // special marker when we decided to skip due to sampling
386
+ return Qnil;
362
387
  }
363
388
 
364
389
  heap_record *heap_record = get_or_create_heap_record(heap_recorder, locations);
365
390
 
366
391
  // And then commit the new allocation.
367
392
  commit_recording(heap_recorder, heap_record, active_recording);
393
+
394
+ return Qnil;
368
395
  }
369
396
 
370
397
  void heap_recorder_prepare_iteration(heap_recorder *heap_recorder) {
@@ -815,6 +842,7 @@ VALUE object_record_inspect(object_record *record) {
815
842
  if (!ruby_ref_from_id(LONG2NUM(record->obj_id), &ref)) {
816
843
  rb_str_catf(inspect, "object=<invalid>");
817
844
  } else {
845
+ rb_str_catf(inspect, "value=%p ", (void *) ref);
818
846
  VALUE ruby_inspect = ruby_safe_inspect(ref);
819
847
  if (ruby_inspect != Qnil) {
820
848
  rb_str_catf(inspect, "object=%"PRIsVALUE, ruby_inspect);
@@ -114,7 +114,9 @@ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj
114
114
  // @param locations The stacktrace representing the location of the allocation.
115
115
  //
116
116
  // WARN: It is illegal to call this without previously having called ::start_heap_allocation_recording.
117
- void end_heap_allocation_recording(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations);
117
+ // WARN: This method rescues exceptions with `rb_protect`, returning the exception state integer for the caller to handle.
118
+ __attribute__((warn_unused_result))
119
+ int end_heap_allocation_recording_with_rb_protect(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations);
118
120
 
119
121
  // Update the heap recorder to reflect the latest state of the VM and prepare internal structures
120
122
  // for efficient iteration.
@@ -2,22 +2,11 @@
2
2
 
3
3
  #include <stdint.h>
4
4
 
5
- // Used to mark symbols to be exported to the outside of the extension.
6
- // Consider very carefully before tagging a function with this.
7
- #define DDTRACE_EXPORT __attribute__ ((visibility ("default")))
8
-
9
- // Used to mark function arguments that are deliberately left unused
10
- #ifdef __GNUC__
11
- #define DDTRACE_UNUSED __attribute__((unused))
12
- #else
13
- #define DDTRACE_UNUSED
14
- #endif
15
-
16
5
  // @ivoanjo: After trying to read through https://stackoverflow.com/questions/3437404/min-and-max-in-c I decided I
17
6
  // don't like C and I just implemented this as a function.
18
- inline static uint64_t uint64_max_of(uint64_t a, uint64_t b) { return a > b ? a : b; }
19
- inline static uint64_t uint64_min_of(uint64_t a, uint64_t b) { return a > b ? b : a; }
20
- inline static long long_max_of(long a, long b) { return a > b ? a : b; }
21
- inline static long long_min_of(long a, long b) { return a > b ? b : a; }
22
- inline static double double_max_of(double a, double b) { return a > b ? a : b; }
23
- inline static double double_min_of(double a, double b) { return a > b ? b : a; }
7
+ static inline uint64_t uint64_max_of(uint64_t a, uint64_t b) { return a > b ? a : b; }
8
+ static inline uint64_t uint64_min_of(uint64_t a, uint64_t b) { return a > b ? b : a; }
9
+ static inline long long_max_of(long a, long b) { return a > b ? a : b; }
10
+ static inline long long_min_of(long a, long b) { return a > b ? b : a; }
11
+ static inline double double_max_of(double a, double b) { return a > b ? a : b; }
12
+ static inline double double_min_of(double a, double b) { return a > b ? b : a; }
@@ -21,7 +21,7 @@ struct call_exporter_without_gvl_arguments {
21
21
  bool send_ran;
22
22
  };
23
23
 
24
- inline static ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
24
+ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
25
25
  static VALUE _native_validate_exporter(VALUE self, VALUE exporter_configuration);
26
26
  static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration, VALUE tags_as_array);
27
27
  static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_result);
@@ -53,11 +53,11 @@ void http_transport_init(VALUE profiling_module) {
53
53
  ok_symbol = ID2SYM(rb_intern_const("ok"));
54
54
  error_symbol = ID2SYM(rb_intern_const("error"));
55
55
 
56
- library_version_string = ddtrace_version();
56
+ library_version_string = datadog_gem_version();
57
57
  rb_global_variable(&library_version_string);
58
58
  }
59
59
 
60
- inline static ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
60
+ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
61
61
  ENFORCE_TYPE(string, T_STRING);
62
62
  ddog_ByteSlice byte_slice = {.ptr = (uint8_t *) StringValuePtr(string), .len = RSTRING_LEN(string)};
63
63
  return byte_slice;
@@ -2,8 +2,6 @@
2
2
 
3
3
  #include <ruby.h>
4
4
 
5
- static VALUE log_failure_to_process_tag(VALUE err_details);
6
-
7
5
  const char *ruby_value_type_to_string(enum ruby_value_type type) {
8
6
  return ruby_value_type_to_char_slice(type).ptr;
9
7
  }
@@ -62,87 +60,3 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
62
60
  ddog_Error_drop(error);
63
61
  return error_msg_size;
64
62
  }
65
-
66
- __attribute__((warn_unused_result))
67
- ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
68
- ENFORCE_TYPE(exporter_configuration, T_ARRAY);
69
-
70
- VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
71
- ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
72
- ID working_mode = SYM2ID(exporter_working_mode);
73
-
74
- ID agentless_id = rb_intern("agentless");
75
- ID agent_id = rb_intern("agent");
76
-
77
- if (working_mode != agentless_id && working_mode != agent_id) {
78
- rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
79
- }
80
-
81
- if (working_mode == agentless_id) {
82
- VALUE site = rb_ary_entry(exporter_configuration, 1);
83
- VALUE api_key = rb_ary_entry(exporter_configuration, 2);
84
- ENFORCE_TYPE(site, T_STRING);
85
- ENFORCE_TYPE(api_key, T_STRING);
86
-
87
- return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
88
- } else { // agent_id
89
- VALUE base_url = rb_ary_entry(exporter_configuration, 1);
90
- ENFORCE_TYPE(base_url, T_STRING);
91
-
92
- return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
93
- }
94
- }
95
-
96
- __attribute__((warn_unused_result))
97
- ddog_Vec_Tag convert_tags(VALUE tags_as_array) {
98
- ENFORCE_TYPE(tags_as_array, T_ARRAY);
99
-
100
- long tags_count = RARRAY_LEN(tags_as_array);
101
- ddog_Vec_Tag tags = ddog_Vec_Tag_new();
102
-
103
- for (long i = 0; i < tags_count; i++) {
104
- VALUE name_value_pair = rb_ary_entry(tags_as_array, i);
105
-
106
- if (!RB_TYPE_P(name_value_pair, T_ARRAY)) {
107
- ddog_Vec_Tag_drop(tags);
108
- ENFORCE_TYPE(name_value_pair, T_ARRAY);
109
- }
110
-
111
- // Note: We can index the array without checking its size first because rb_ary_entry returns Qnil if out of bounds
112
- VALUE tag_name = rb_ary_entry(name_value_pair, 0);
113
- VALUE tag_value = rb_ary_entry(name_value_pair, 1);
114
-
115
- if (!(RB_TYPE_P(tag_name, T_STRING) && RB_TYPE_P(tag_value, T_STRING))) {
116
- ddog_Vec_Tag_drop(tags);
117
- ENFORCE_TYPE(tag_name, T_STRING);
118
- ENFORCE_TYPE(tag_value, T_STRING);
119
- }
120
-
121
- ddog_Vec_Tag_PushResult push_result =
122
- ddog_Vec_Tag_push(&tags, char_slice_from_ruby_string(tag_name), char_slice_from_ruby_string(tag_value));
123
-
124
- if (push_result.tag == DDOG_VEC_TAG_PUSH_RESULT_ERR) {
125
- // libdatadog validates tags and may catch invalid tags that ddtrace didn't actually catch.
126
- // We warn users about such tags, and then just ignore them.
127
-
128
- int exception_state;
129
- rb_protect(log_failure_to_process_tag, get_error_details_and_drop(&push_result.err), &exception_state);
130
-
131
- // Since we are calling into Ruby code, it may raise an exception. Ensure that dynamically-allocated tags
132
- // get cleaned before propagating the exception.
133
- if (exception_state) {
134
- ddog_Vec_Tag_drop(tags);
135
- rb_jump_tag(exception_state); // "Re-raise" exception
136
- }
137
- }
138
- }
139
-
140
- return tags;
141
- }
142
-
143
- static VALUE log_failure_to_process_tag(VALUE err_details) {
144
- VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
145
- VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
146
-
147
- return rb_funcall(logger, rb_intern("warn"), 1, rb_sprintf("Failed to add tag to profiling request: %"PRIsVALUE, err_details));
148
- }
@@ -3,27 +3,10 @@
3
3
  #include <datadog/profiling.h>
4
4
  #include "ruby_helpers.h"
5
5
 
6
- inline static ddog_CharSlice char_slice_from_ruby_string(VALUE string) {
7
- ENFORCE_TYPE(string, T_STRING);
8
- ddog_CharSlice char_slice = {.ptr = StringValuePtr(string), .len = RSTRING_LEN(string)};
9
- return char_slice;
10
- }
11
-
12
- inline static VALUE ruby_string_from_vec_u8(ddog_Vec_U8 string) {
6
+ static inline VALUE ruby_string_from_vec_u8(ddog_Vec_U8 string) {
13
7
  return rb_str_new((char *) string.ptr, string.len);
14
8
  }
15
9
 
16
- inline static VALUE ruby_string_from_error(const ddog_Error *error) {
17
- ddog_CharSlice char_slice = ddog_Error_message(error);
18
- return rb_str_new(char_slice.ptr, char_slice.len);
19
- }
20
-
21
- inline static VALUE get_error_details_and_drop(ddog_Error *error) {
22
- VALUE result = ruby_string_from_error(error);
23
- ddog_Error_drop(error);
24
- return result;
25
- }
26
-
27
10
  // Utility function to be able to extract an error cstring from a ddog_Error.
28
11
  // Returns the amount of characters written to string (which are necessarily
29
12
  // bounded by capacity - 1 since the string will be null-terminated).
@@ -37,10 +20,6 @@ ddog_CharSlice ruby_value_type_to_char_slice(enum ruby_value_type type);
37
20
 
38
21
  // Returns a dynamically allocated string from the provided char slice.
39
22
  // WARN: The returned string must be explicitly freed with ruby_xfree.
40
- inline static char* string_from_char_slice(ddog_CharSlice slice) {
23
+ static inline char* string_from_char_slice(ddog_CharSlice slice) {
41
24
  return ruby_strndup(slice.ptr, slice.len);
42
25
  }
43
-
44
- ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration);
45
-
46
- ddog_Vec_Tag convert_tags(VALUE tags_as_array);