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
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Rails
7
+ # Instruments the `bin/rails runner` command.
8
+ # This command executes the provided code with the host Rails application loaded.
9
+ # The command can be either:
10
+ # * `-`: for code provided through the STDIN.
11
+ # * File path: for code provided through a local file.
12
+ # * `inline code`: for code provided directly as a command line argument.
13
+ # @see https://guides.rubyonrails.org/v6.1/command_line.html#bin-rails-runner
14
+ module Runner
15
+ # Limit the maximum size of the source code captured in the source tag.
16
+ MAX_TAG_VALUE_SIZE = 4096
17
+ private_constant :MAX_TAG_VALUE_SIZE
18
+
19
+ def runner(code_or_file = nil, *_command_argv)
20
+ if code_or_file == '-'
21
+ name = Ext::SPAN_RUNNER_STDIN
22
+ resource = nil
23
+ operation = Ext::TAG_OPERATION_STDIN
24
+ # The source is not yet available for STDIN, but it will be captured in `eval`.
25
+ elsif File.exist?(code_or_file)
26
+ name = Ext::SPAN_RUNNER_FILE
27
+ resource = code_or_file
28
+ operation = Ext::TAG_OPERATION_FILE
29
+ source = File.read(code_or_file)
30
+ else
31
+ name = Ext::SPAN_RUNNER_INLINE
32
+ resource = nil
33
+ operation = Ext::TAG_OPERATION_INLINE
34
+ source = code_or_file
35
+ end
36
+
37
+ Tracing.trace(
38
+ name,
39
+ service: Datadog.configuration.tracing[:rails][:service_name],
40
+ resource: resource,
41
+ tags: {
42
+ Tracing::Metadata::Ext::TAG_COMPONENT => Ext::TAG_COMPONENT,
43
+ Tracing::Metadata::Ext::TAG_OPERATION => operation,
44
+ }
45
+ ) do |span|
46
+ if source
47
+ span.set_tag(
48
+ Ext::TAG_RUNNER_SOURCE,
49
+ Core::Utils.truncate(source, MAX_TAG_VALUE_SIZE)
50
+ )
51
+ end
52
+ Contrib::Analytics.set_rate!(span, Datadog.configuration.tracing[:rails])
53
+
54
+ super
55
+ end
56
+ end
57
+
58
+ # Capture the executed source code when provided from STDIN.
59
+ def eval(*args)
60
+ span = Datadog::Tracing.active_span
61
+ if span.name == Ext::SPAN_RUNNER_STDIN
62
+ source = args[0]
63
+ span.set_tag(
64
+ Ext::TAG_RUNNER_SOURCE,
65
+ Core::Utils.truncate(source, MAX_TAG_VALUE_SIZE)
66
+ )
67
+ end
68
+
69
+ super
70
+ end
71
+
72
+ ruby2_keywords :eval if respond_to?(:ruby2_keywords, true)
73
+ end
74
+
75
+ # The instrumentation target, {Rails::Command::RunnerCommand} is only loaded
76
+ # right before `bin/rails runner` is executed. This means there's not much
77
+ # opportunity to patch it ahead of time.
78
+ # To ensure we can patch it successfully, we patch it's caller, {Rails::Command}
79
+ # and promptly patch {Rails::Command::RunnerCommand} when it is loaded.
80
+ module Command
81
+ def find_by_namespace(*args)
82
+ ret = super
83
+ # Patch RunnerCommand if it is loaded and not already patched.
84
+ if defined?(::Rails::Command::RunnerCommand) && !(::Rails::Command::RunnerCommand < Runner)
85
+ ::Rails::Command::RunnerCommand.prepend(Runner)
86
+ end
87
+ ret
88
+ end
89
+
90
+ ruby2_keywords :find_by_namespace if respond_to?(:ruby2_keywords, true)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -46,6 +46,11 @@ module Datadog
46
46
  o.default Contrib::Propagation::SqlComment::Ext::DISABLED
47
47
  end
48
48
 
49
+ option :append_comment do |o|
50
+ o.type :bool
51
+ o.default false
52
+ end
53
+
49
54
  option :peer_service do |o|
50
55
  o.type :string, nilable: true
51
56
  o.env Ext::ENV_PEER_SERVICE
@@ -49,13 +49,16 @@ module Datadog
49
49
  # Set analytics sample rate
50
50
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
51
51
 
52
+ span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, connection_options[:database])
52
53
  span.set_tag(Ext::TAG_DB_NAME, connection_options[:database])
53
54
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, connection_options[:host])
54
55
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, connection_options[:port])
55
56
 
56
57
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
57
58
 
58
- propagation_mode = Contrib::Propagation::SqlComment::Mode.new(comment_propagation)
59
+ propagation_mode = Contrib::Propagation::SqlComment::Mode.new(
60
+ comment_propagation, datadog_configuration[:append_comment]
61
+ )
59
62
 
60
63
  Contrib::Propagation::SqlComment.annotate!(span, propagation_mode)
61
64
  sql = Contrib::Propagation::SqlComment.prepend_comment(
@@ -14,8 +14,8 @@ module Datadog
14
14
 
15
15
  def self.collect_and_log!(responses: nil)
16
16
  if log?
17
- env_data = EnvironmentCollector.collect_config!
18
- log_configuration!('TRACING', env_data.to_json)
17
+ log_configuration!('TRACING', EnvironmentCollector.collect_config!.to_json)
18
+ log_debug!('TRACING INTEGRATIONS', EnvironmentCollector.collect_integrations_settings!.to_json)
19
19
 
20
20
  if responses
21
21
  err_data = EnvironmentCollector.collect_errors!(responses)
@@ -40,7 +40,6 @@ module Datadog
40
40
  sampling_rules: sampling_rules,
41
41
  integrations_loaded: integrations_loaded,
42
42
  partial_flushing_enabled: partial_flushing_enabled,
43
- **instrumented_integrations_settings
44
43
  }
45
44
  end
46
45
 
@@ -128,6 +127,18 @@ module Datadog
128
127
  !!Datadog.configuration.tracing.partial_flush.enabled
129
128
  end
130
129
 
130
+ def collect_integrations_settings!
131
+ instrumented_integrations.each_with_object({}) do |(name, integration), result|
132
+ integration.configuration.to_h.each do |setting, value|
133
+ next if setting == :tracer # Skip internal objects
134
+
135
+ # Convert value to a string to avoid custom #to_json
136
+ # handlers possibly causing errors.
137
+ result[:"#{name}_#{setting}"] = value.to_s
138
+ end
139
+ end
140
+ end
141
+
131
142
  private
132
143
 
133
144
  def instrumented_integrations
@@ -139,19 +150,6 @@ module Datadog
139
150
 
140
151
  Datadog.configuration.tracing.instrumented_integrations
141
152
  end
142
-
143
- # Capture all active integration settings into "integrationName_settingName: value" entries.
144
- def instrumented_integrations_settings
145
- instrumented_integrations.flat_map do |name, integration|
146
- integration.configuration.to_h.flat_map do |setting, value|
147
- next [] if setting == :tracer # Skip internal Ruby objects
148
-
149
- # Convert value to a string to avoid custom #to_json
150
- # handlers possibly causing errors.
151
- [[:"integration_#{name}_#{setting}", value.to_s]]
152
- end
153
- end.to_h
154
- end
155
153
  end
156
154
  end
157
155
  end
@@ -31,7 +31,7 @@ module Datadog
31
31
 
32
32
  # DEV: We need these to be hex encoded
33
33
  data[@trace_id_key] = format('%032x', digest.trace_id)
34
- data[@span_id_key] = format('%016x', digest.span_id)
34
+ data[@span_id_key] = format('%016x', digest.span_id || 0) # # Fall back to zero (invalid) if not present
35
35
 
36
36
  if digest.trace_sampling_priority
37
37
  sampling_priority = Helpers.clamp_sampling_priority(
@@ -25,8 +25,10 @@ module Datadog
25
25
  def inject!(digest, env)
26
26
  return if digest.nil?
27
27
 
28
+ span_id = digest.span_id || 0 # Fall back to zero (invalid) if not present
29
+
28
30
  # DEV: We need these to be hex encoded
29
- value = "#{format('%032x', digest.trace_id)}-#{format('%016x', digest.span_id)}"
31
+ value = "#{format('%032x', digest.trace_id)}-#{format('%016x', span_id)}"
30
32
 
31
33
  if digest.trace_sampling_priority
32
34
  sampling_priority = Helpers.clamp_sampling_priority(
@@ -42,7 +42,7 @@ module Datadog
42
42
 
43
43
  data[@trace_id_key] = Tracing::Utils::TraceId.to_low_order(digest.trace_id).to_s
44
44
 
45
- data[@parent_id_key] = digest.span_id.to_s
45
+ data[@parent_id_key] = digest.span_id.to_s if digest.span_id
46
46
  data[@sampling_priority_key] = digest.trace_sampling_priority.to_s if digest.trace_sampling_priority
47
47
  data[@origin_key] = digest.trace_origin.to_s if digest.trace_origin
48
48
 
@@ -109,7 +109,7 @@ module Datadog
109
109
 
110
110
  return tags if high_order == 0
111
111
 
112
- tags.merge(Tracing::Metadata::Ext::Distributed::TAG_TID => high_order.to_s(16))
112
+ tags.merge(Tracing::Metadata::Ext::Distributed::TAG_TID => format('%016x', high_order))
113
113
  end
114
114
 
115
115
  # Side effect: Remove high order 64 bit hex-encoded `tid` tag from distributed tags
@@ -32,7 +32,9 @@ module Datadog
32
32
 
33
33
  # inject! populates the env with span ID, trace ID and sampling priority
34
34
  #
35
- # This method will never raise errors, but instead log them to `Datadog.logger`.
35
+ # This method will never raise errors.
36
+ # It can propagate partial data, if deemed useful, instead of failing.
37
+ # In case of unrecoverable errors, it will log them to `Datadog.logger`.
36
38
  #
37
39
  # DEV-2.0: inject! should work without arguments, injecting the active_trace's digest
38
40
  # DEV-2.0: and returning a new Hash with the injected data.
@@ -45,7 +47,7 @@ module Datadog
45
47
  # @param digest [TraceDigest]
46
48
  # @param data [Hash]
47
49
  # @return [Boolean] `true` if injected successfully, `false` if no propagation style is configured
48
- # @return [nil] in case of error, see `Datadog.logger` output for details.
50
+ # @return [nil] in case of unrecoverable errors, see `Datadog.logger` output for details.
49
51
  def inject!(digest, data)
50
52
  if digest.nil?
51
53
  ::Datadog.logger.debug('Cannot inject distributed trace data: digest is nil.')
@@ -54,6 +56,11 @@ module Datadog
54
56
 
55
57
  digest = digest.to_digest if digest.respond_to?(:to_digest)
56
58
 
59
+ if digest.trace_id.nil?
60
+ ::Datadog.logger.debug('Cannot inject distributed trace data: digest.trace_id is nil.')
61
+ return nil
62
+ end
63
+
57
64
  result = false
58
65
 
59
66
  # Inject all configured propagation styles
@@ -107,7 +107,7 @@ module Datadog
107
107
  def build_traceparent(digest)
108
108
  build_traceparent_string(
109
109
  digest.trace_id,
110
- digest.span_id,
110
+ digest.span_id || 0, # Fall back to zero (invalid) if not present
111
111
  build_trace_flags(digest)
112
112
  )
113
113
  end
@@ -198,7 +198,8 @@ module Datadog
198
198
 
199
199
  def last_dd_parent_id(digest)
200
200
  if !digest.span_remote
201
- "p:#{format('%016x', digest.span_id)};"
201
+ span_id = digest.span_id || 0 # Fall back to zero (invalid) if not present
202
+ "p:#{format('%016x', span_id)};"
202
203
  elsif digest.trace_distributed_tags&.key?(Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID)
203
204
  "p:#{digest.trace_distributed_tags[Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID]};"
204
205
  else
@@ -10,8 +10,16 @@ module Datadog
10
10
  # Adds error tagging behavior
11
11
  # @public_api
12
12
  module Errors
13
- # Mark the span with the given error.
14
13
  def set_error(e)
14
+ Datadog::Core.log_deprecation do
15
+ 'Errors.set_error(..) is deprecated. ' \
16
+ 'Use Errors.set_error_tags(..) instead.'
17
+ end
18
+ set_error_tags(e)
19
+ end
20
+
21
+ # Mark the span with the given error.
22
+ def set_error_tags(e)
15
23
  e = Core::Error.build_from(e)
16
24
 
17
25
  set_tag(Ext::Errors::TAG_TYPE, e.type) unless e.type.empty?
@@ -14,6 +14,10 @@ module Datadog
14
14
  # Type of operation being performed (e.g. )
15
15
  TAG_OPERATION = 'operation'
16
16
  # Hostname of external service interacted with
17
+ #
18
+ # This tag also doesn't strictly need to be a “hostname”. It can be a raw IP address and in some cases it
19
+ # can even be a unix domain socket (i.e. postgres client setting host=/var/run/postgres).
20
+ # It should be whatever the client uses to point at the server it’s trying to talk to.
17
21
  TAG_PEER_HOSTNAME = 'peer.hostname'
18
22
  # Name of external service that performed the work
19
23
  TAG_PEER_SERVICE = 'peer.service'
@@ -10,8 +10,8 @@ module Datadog
10
10
  # This processor executes the configured `operation` for each {Datadog::Tracing::Span}
11
11
  # in a {Datadog::Tracing::TraceSegment}.
12
12
  #
13
- # If `operation` returns a truthy value for a span, that span is kept,
14
- # otherwise the span is removed from the trace.
13
+ # If `operation` returns a truthy value for a span, that span is dropped,
14
+ # otherwise the span is kept.
15
15
  #
16
16
  # @public_api
17
17
  class SpanFilter < SpanProcessor
@@ -27,6 +27,7 @@ module Datadog
27
27
  :resource,
28
28
  :service,
29
29
  :links,
30
+ :events,
30
31
  :type,
31
32
  :start_time,
32
33
  :status,
@@ -45,6 +46,7 @@ module Datadog
45
46
  # * +parent_id+: the identifier of the parent span
46
47
  # * +trace_id+: the identifier of the root span for this trace
47
48
  # * +service_entry+: whether it is a service entry span.
49
+ # * +events+: the list of events that occurred while a span was active.
48
50
  def initialize(
49
51
  name,
50
52
  duration: nil,
@@ -60,7 +62,8 @@ module Datadog
60
62
  type: nil,
61
63
  trace_id: nil,
62
64
  service_entry: nil,
63
- links: nil
65
+ links: nil,
66
+ events: nil
64
67
  )
65
68
  @name = Core::Utils::SafeDup.frozen_or_dup(name)
66
69
  @service = Core::Utils::SafeDup.frozen_or_dup(service)
@@ -90,6 +93,8 @@ module Datadog
90
93
 
91
94
  @links = links || []
92
95
 
96
+ @events = events || []
97
+
93
98
  # Mark with the service entry span metric, if applicable
94
99
  set_metric(Metadata::Ext::TAG_TOP_LEVEL, 1.0) if service_entry
95
100
  end
@@ -112,7 +117,7 @@ module Datadog
112
117
 
113
118
  def set_error(e)
114
119
  @status = Metadata::Ext::Errors::STATUS
115
- super
120
+ set_error_tags(e)
116
121
  end
117
122
 
118
123
  # Spans with the same ID are considered the same span
@@ -149,6 +154,8 @@ module Datadog
149
154
  h[:duration] = duration_nano
150
155
  end
151
156
 
157
+ h[:meta]['events'] = @events.map(&:to_hash).to_json unless @events.empty?
158
+
152
159
  h
153
160
  end
154
161
 
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ # Represents a timestamped annotation on a span. It is analogous to structured log message.
8
+ # @public_api
9
+ class SpanEvent
10
+ # @!attribute [r] name
11
+ # @return [Integer]
12
+ attr_reader :name
13
+
14
+ # @!attribute [r] attributes
15
+ # @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
16
+ attr_reader :attributes
17
+
18
+ # @!attribute [r] time_unix_nano
19
+ # @return [Integer]
20
+ attr_reader :time_unix_nano
21
+
22
+ def initialize(
23
+ name,
24
+ attributes: nil,
25
+ time_unix_nano: nil
26
+ )
27
+ @name = name
28
+ @attributes = attributes || {}
29
+ # OpenTelemetry SDK stores span event timestamps in nanoseconds (not seconds).
30
+ # We will do the same here to avoid unnecessary conversions and inconsistencies.
31
+ @time_unix_nano = time_unix_nano || (Time.now.to_r * 1_000_000_000).to_i
32
+ end
33
+
34
+ def to_hash
35
+ h = { name: @name, time_unix_nano: @time_unix_nano }
36
+ h[:attributes] = attributes unless @attributes.empty?
37
+ h
38
+ end
39
+ end
40
+ end
41
+ end
@@ -35,7 +35,7 @@ module Datadog
35
35
  :start_time,
36
36
  :trace_id,
37
37
  :type
38
- attr_accessor :links, :status
38
+ attr_accessor :links, :status, :span_events
39
39
 
40
40
  def initialize(
41
41
  name,
@@ -48,7 +48,9 @@ module Datadog
48
48
  tags: nil,
49
49
  trace_id: nil,
50
50
  type: nil,
51
- links: nil
51
+ links: nil,
52
+ span_events: nil,
53
+ id: nil
52
54
  )
53
55
  # Ensure dynamically created strings are UTF-8 encoded.
54
56
  #
@@ -60,13 +62,15 @@ module Datadog
60
62
  self.type = type
61
63
  self.resource = resource
62
64
 
63
- @id = Tracing::Utils.next_id
65
+ @id = id.nil? ? Tracing::Utils.next_id : id
64
66
  @parent_id = parent_id || 0
65
67
  @trace_id = trace_id || Tracing::Utils::TraceId.next_id
66
68
 
67
69
  @status = 0
68
70
  # stores array of span links
69
71
  @links = links || []
72
+ # stores array of span events
73
+ @span_events = span_events || []
70
74
 
71
75
  # start_time and end_time track wall clock. In Ruby, wall clock
72
76
  # has less accuracy than monotonic clock, so if possible we look to only use wall clock
@@ -264,7 +268,7 @@ module Datadog
264
268
 
265
269
  def set_error(e)
266
270
  @status = Metadata::Ext::Errors::STATUS
267
- super
271
+ set_error_tags(e)
268
272
  end
269
273
 
270
274
  # Return a string representation of the span.
@@ -454,6 +458,7 @@ module Datadog
454
458
  type: @type,
455
459
  trace_id: @trace_id,
456
460
  links: @links,
461
+ events: @span_events,
457
462
  service_entry: parent.nil? || (service && parent.service != service)
458
463
  )
459
464
  end
@@ -181,6 +181,7 @@ module Datadog
181
181
  start_time: nil,
182
182
  tags: nil,
183
183
  type: nil,
184
+ id: nil,
184
185
  &block
185
186
  )
186
187
  # Don't allow more span measurements if the
@@ -197,7 +198,8 @@ module Datadog
197
198
  service: service,
198
199
  start_time: start_time,
199
200
  tags: tags,
200
- type: type
201
+ type: type,
202
+ id: id
201
203
  )
202
204
 
203
205
  # Start span measurement
@@ -212,7 +214,8 @@ module Datadog
212
214
  service: nil,
213
215
  start_time: nil,
214
216
  tags: nil,
215
- type: nil
217
+ type: nil,
218
+ id: nil
216
219
  )
217
220
  begin
218
221
  # Resolve span options:
@@ -249,7 +252,8 @@ module Datadog
249
252
  start_time: start_time,
250
253
  tags: tags,
251
254
  trace_id: trace_id,
252
- type: type
255
+ type: type,
256
+ id: id
253
257
  )
254
258
  rescue StandardError => e
255
259
  Datadog.logger.debug { "Failed to build new span: #{e}" }
@@ -132,10 +132,13 @@ module Datadog
132
132
  || sampling_priority == Sampling::Ext::Priority::USER_KEEP
133
133
  end
134
134
 
135
+ # Returns the high order part of the trace id as a hexadecimal string; the most significant 64 bits.
136
+ # The String returned is padded with zeros, having a fixed length of 16 characters.
137
+ # If the high order part is zero, it returns nil.
135
138
  def high_order_tid
136
139
  high_order = Tracing::Utils::TraceId.to_high_order(@id)
137
140
 
138
- high_order.to_s(16) if high_order != 0
141
+ format('%016x', high_order) if high_order != 0
139
142
  end
140
143
 
141
144
  protected
@@ -114,6 +114,7 @@ module Datadog
114
114
  # @param [Time] start_time time which the span should have started.
115
115
  # @param [Hash<String,String>] tags extra tags which should be added to the span.
116
116
  # @param [String] type the type of the span. See {Datadog::Tracing::Metadata::Ext::AppTypes}.
117
+ # @param [Integer] the id of the new span.
117
118
  # @return [Object] If a block is provided, returns the result of the block execution.
118
119
  # @return [Datadog::Tracing::SpanOperation] If no block is provided, returns the active,
119
120
  # unfinished {Datadog::Tracing::SpanOperation}.
@@ -130,6 +131,7 @@ module Datadog
130
131
  start_time: nil,
131
132
  tags: nil,
132
133
  type: nil,
134
+ id: nil,
133
135
  &block
134
136
  )
135
137
  return skip_trace(name, &block) unless enabled
@@ -162,6 +164,7 @@ module Datadog
162
164
  tags: tags,
163
165
  type: type,
164
166
  _trace: trace,
167
+ id: id,
165
168
  &block
166
169
  )
167
170
  end
@@ -178,7 +181,8 @@ module Datadog
178
181
  start_time: start_time,
179
182
  tags: tags,
180
183
  type: type,
181
- _trace: trace
184
+ _trace: trace,
185
+ id: id
182
186
  )
183
187
  end
184
188
  end
@@ -375,6 +379,7 @@ module Datadog
375
379
  tags: nil,
376
380
  type: nil,
377
381
  _trace: nil,
382
+ id: nil,
378
383
  &block
379
384
  )
380
385
  trace = _trace || start_trace(continue_from: continue_from)
@@ -391,6 +396,7 @@ module Datadog
391
396
  service: service,
392
397
  tags: resolve_tags(tags),
393
398
  type: type,
399
+ id: id,
394
400
  &block
395
401
  )
396
402
  else
@@ -403,7 +409,8 @@ module Datadog
403
409
  service: service,
404
410
  start_time: start_time,
405
411
  tags: resolve_tags(tags),
406
- type: type
412
+ type: type,
413
+ id: id
407
414
  )
408
415
 
409
416
  span.start(start_time)
@@ -72,6 +72,9 @@ module Datadog
72
72
  packer.write_map_header(number_of_elements_to_write) # Set header with how many elements in the map
73
73
  end
74
74
 
75
+ # serialize span events as meta tags
76
+ span.set_tag('events', span.events.map(&:to_hash).to_json) if span.events.any?
77
+
75
78
  # DEV: We use strings as keys here, instead of symbols, as
76
79
  # DEV: MessagePack will ultimately convert them to strings.
77
80
  # DEV: By providing strings directly, we skip this indirection operation.
@@ -23,6 +23,7 @@ module Datadog
23
23
  start_time: nil,
24
24
  tags: nil,
25
25
  type: nil,
26
+ id: nil,
26
27
  &block
27
28
  )
28
29
 
@@ -35,6 +36,7 @@ module Datadog
35
36
  start_time: start_time,
36
37
  tags: tags,
37
38
  type: type,
39
+ id: id,
38
40
  &block
39
41
  )
40
42
  end
@@ -117,9 +119,11 @@ module Datadog
117
119
  # # dd.env=prod dd.service=auth dd.version=13.8 dd.trace_id=5458478252992251 dd.span_id=7117552347370098 My message
118
120
  # ```
119
121
  #
120
- # @return [String] correlation information
122
+ # @return [String] correlation information; or an empty String if Tracing is disabled (`!enabled?`)
121
123
  # @public_api
122
124
  def log_correlation
125
+ return '' unless enabled?
126
+
123
127
  correlation.to_log_format
124
128
  end
125
129
 
@@ -3,7 +3,7 @@
3
3
  module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 1
6
+ MINOR = 3
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
  BUILD = nil
@@ -21,6 +21,6 @@ module Datadog
21
21
  # To allow testing with the next unreleased version of Ruby, the version check is performed
22
22
  # as `< #{MAXIMUM_RUBY_VERSION}`, meaning prereleases of MAXIMUM_RUBY_VERSION are allowed
23
23
  # but not stable MAXIMUM_RUBY_VERSION releases.
24
- MAXIMUM_RUBY_VERSION = '3.4'
24
+ MAXIMUM_RUBY_VERSION = '3.5'
25
25
  end
26
26
  end