datadog 2.3.0 → 2.5.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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -2
  3. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
  4. data/ext/datadog_profiling_loader/extconf.rb +10 -22
  5. data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +3 -3
  6. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +198 -41
  7. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
  9. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +645 -107
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +15 -1
  11. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
  12. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
  13. data/ext/datadog_profiling_native_extension/extconf.rb +42 -25
  14. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
  15. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
  16. data/ext/datadog_profiling_native_extension/heap_recorder.c +194 -34
  17. data/ext/datadog_profiling_native_extension/heap_recorder.h +11 -0
  18. data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
  19. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +1 -1
  20. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +53 -2
  21. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
  22. data/ext/datadog_profiling_native_extension/profiling.c +1 -1
  23. data/ext/datadog_profiling_native_extension/ruby_helpers.c +14 -11
  24. data/ext/datadog_profiling_native_extension/stack_recorder.c +58 -22
  25. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
  26. data/ext/libdatadog_api/crashtracker.c +20 -18
  27. data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
  28. data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
  29. data/ext/libdatadog_extconf_helpers.rb +1 -1
  30. data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
  31. data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
  32. data/lib/datadog/appsec/component.rb +29 -8
  33. data/lib/datadog/appsec/configuration/settings.rb +10 -2
  34. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
  35. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
  36. data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
  37. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
  38. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
  39. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +14 -15
  40. data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
  41. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +7 -20
  42. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
  43. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -15
  44. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +6 -18
  45. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +7 -20
  46. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +5 -18
  47. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -1
  48. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -5
  49. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +5 -18
  50. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -10
  51. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +7 -20
  52. data/lib/datadog/appsec/event.rb +25 -1
  53. data/lib/datadog/appsec/ext.rb +4 -0
  54. data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -5
  55. data/lib/datadog/appsec/monitor/reactive/set_user.rb +7 -20
  56. data/lib/datadog/appsec/processor/context.rb +109 -0
  57. data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
  58. data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
  59. data/lib/datadog/appsec/processor.rb +42 -107
  60. data/lib/datadog/appsec/rate_limiter.rb +25 -40
  61. data/lib/datadog/appsec/remote.rb +7 -3
  62. data/lib/datadog/appsec/scope.rb +1 -4
  63. data/lib/datadog/appsec/utils/trace_operation.rb +15 -0
  64. data/lib/datadog/appsec/utils.rb +2 -0
  65. data/lib/datadog/appsec.rb +3 -2
  66. data/lib/datadog/core/configuration/agent_settings_resolver.rb +26 -25
  67. data/lib/datadog/core/configuration/components.rb +4 -3
  68. data/lib/datadog/core/configuration/settings.rb +96 -5
  69. data/lib/datadog/core/configuration.rb +1 -3
  70. data/lib/datadog/core/crashtracking/component.rb +9 -6
  71. data/lib/datadog/core/environment/execution.rb +5 -5
  72. data/lib/datadog/core/environment/yjit.rb +5 -0
  73. data/lib/datadog/core/metrics/client.rb +7 -0
  74. data/lib/datadog/core/rate_limiter.rb +183 -0
  75. data/lib/datadog/core/remote/client/capabilities.rb +4 -3
  76. data/lib/datadog/core/remote/component.rb +4 -2
  77. data/lib/datadog/core/remote/negotiation.rb +4 -4
  78. data/lib/datadog/core/remote/tie.rb +2 -0
  79. data/lib/datadog/core/remote/transport/http.rb +5 -0
  80. data/lib/datadog/core/remote/worker.rb +1 -1
  81. data/lib/datadog/core/runtime/ext.rb +1 -0
  82. data/lib/datadog/core/runtime/metrics.rb +5 -1
  83. data/lib/datadog/core/semaphore.rb +35 -0
  84. data/lib/datadog/core/telemetry/component.rb +2 -0
  85. data/lib/datadog/core/telemetry/event.rb +12 -7
  86. data/lib/datadog/core/telemetry/logger.rb +51 -0
  87. data/lib/datadog/core/telemetry/logging.rb +50 -14
  88. data/lib/datadog/core/telemetry/request.rb +13 -1
  89. data/lib/datadog/core/transport/ext.rb +1 -0
  90. data/lib/datadog/core/utils/time.rb +12 -0
  91. data/lib/datadog/core/workers/async.rb +1 -1
  92. data/lib/datadog/di/code_tracker.rb +166 -0
  93. data/lib/datadog/di/configuration/settings.rb +163 -0
  94. data/lib/datadog/di/configuration.rb +11 -0
  95. data/lib/datadog/di/error.rb +31 -0
  96. data/lib/datadog/di/extensions.rb +16 -0
  97. data/lib/datadog/di/instrumenter.rb +301 -0
  98. data/lib/datadog/di/probe.rb +162 -0
  99. data/lib/datadog/di/probe_builder.rb +47 -0
  100. data/lib/datadog/di/probe_notification_builder.rb +207 -0
  101. data/lib/datadog/di/probe_notifier_worker.rb +244 -0
  102. data/lib/datadog/di/redactor.rb +188 -0
  103. data/lib/datadog/di/serializer.rb +215 -0
  104. data/lib/datadog/di/transport.rb +67 -0
  105. data/lib/datadog/di/utils.rb +39 -0
  106. data/lib/datadog/di.rb +57 -0
  107. data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
  108. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
  109. data/lib/datadog/profiling/collectors/info.rb +12 -3
  110. data/lib/datadog/profiling/collectors/thread_context.rb +32 -8
  111. data/lib/datadog/profiling/component.rb +21 -4
  112. data/lib/datadog/profiling/http_transport.rb +6 -1
  113. data/lib/datadog/profiling/scheduler.rb +2 -0
  114. data/lib/datadog/profiling/stack_recorder.rb +40 -9
  115. data/lib/datadog/single_step_instrument.rb +12 -0
  116. data/lib/datadog/tracing/component.rb +13 -0
  117. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
  118. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
  119. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
  120. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
  121. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
  122. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
  123. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
  124. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
  125. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
  126. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
  127. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  128. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -0
  129. data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -0
  130. data/lib/datadog/tracing/contrib/faraday/middleware.rb +12 -0
  131. data/lib/datadog/tracing/contrib/grape/endpoint.rb +24 -2
  132. data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
  133. data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
  134. data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
  135. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
  136. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
  137. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +9 -0
  138. data/lib/datadog/tracing/contrib/http/instrumentation.rb +22 -15
  139. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -5
  140. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
  141. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +9 -0
  142. data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
  143. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
  144. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  145. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
  146. data/lib/datadog/tracing/contrib/patcher.rb +2 -1
  147. data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
  148. data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
  149. data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
  150. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
  151. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +3 -0
  152. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
  153. data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
  154. data/lib/datadog/tracing/distributed/propagation.rb +7 -0
  155. data/lib/datadog/tracing/metadata/ext.rb +2 -0
  156. data/lib/datadog/tracing/remote.rb +5 -2
  157. data/lib/datadog/tracing/sampling/matcher.rb +6 -1
  158. data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
  159. data/lib/datadog/tracing/sampling/rule.rb +2 -0
  160. data/lib/datadog/tracing/sampling/rule_sampler.rb +15 -9
  161. data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
  162. data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
  163. data/lib/datadog/tracing/trace_operation.rb +26 -2
  164. data/lib/datadog/tracing/tracer.rb +29 -22
  165. data/lib/datadog/tracing/transport/http/client.rb +1 -0
  166. data/lib/datadog/tracing/transport/http.rb +4 -0
  167. data/lib/datadog/tracing/transport/io/client.rb +1 -0
  168. data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
  169. data/lib/datadog/tracing/workers.rb +2 -2
  170. data/lib/datadog/tracing/writer.rb +26 -28
  171. data/lib/datadog/version.rb +1 -1
  172. metadata +40 -15
  173. data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -3,6 +3,7 @@
3
3
  require_relative '../configuration/ext'
4
4
  require_relative '../trace_digest'
5
5
  require_relative '../trace_operation'
6
+ require_relative '../../core/telemetry/logger'
6
7
 
7
8
  module Datadog
8
9
  module Tracing
@@ -43,6 +44,7 @@ module Datadog
43
44
  # DEV-2.0: if needed.
44
45
  # DEV-2.0: Ideally, we'd have a separate stream to report tracer errors and never
45
46
  # DEV-2.0: touch the active span.
47
+ # DEV-3.0: Sample trace here instead of when generating digest.
46
48
  #
47
49
  # @param digest [TraceDigest]
48
50
  # @param data [Hash]
@@ -72,6 +74,10 @@ module Datadog
72
74
  ::Datadog.logger.error(
73
75
  "Error injecting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
74
76
  )
77
+ ::Datadog::Core::Telemetry::Logger.report(
78
+ e,
79
+ description: "Error injecting distributed trace data with #{propagator.class.name}"
80
+ )
75
81
  end
76
82
 
77
83
  result
@@ -127,6 +133,7 @@ module Datadog
127
133
  )
128
134
  end
129
135
  rescue => e
136
+ # TODO: Not to report Telemetry logs for now
130
137
  ::Datadog.logger.error(
131
138
  "Error extracting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
132
139
  )
@@ -87,6 +87,8 @@ module Datadog
87
87
  TAG_STATUS_CODE = 'http.status_code'
88
88
  TAG_USER_AGENT = 'http.useragent'
89
89
  TAG_URL = 'http.url'
90
+ TAG_ROUTE = 'http.route'
91
+ TAG_ROUTE_PATH = 'http.route.path'
90
92
  TYPE_INBOUND = AppTypes::TYPE_WEB.freeze
91
93
  TYPE_OUTBOUND = 'http'
92
94
  TYPE_PROXY = 'proxy'
@@ -13,7 +13,10 @@ module Datadog
13
13
  PRODUCT = 'APM_TRACING'
14
14
 
15
15
  CAPABILITIES = [
16
- 1 << 29 # APM_TRACING_SAMPLE_RULES: Dynamic trace sampling rules configuration
16
+ 1 << 12, # APM_TRACING_SAMPLE_RATE: Dynamic trace sampling rate configuration
17
+ 1 << 13, # APM_TRACING_LOGS_INJECTION: Dynamic trace logs injection configuration
18
+ 1 << 14, # APM_TRACING_HTTP_HEADER_TAGS: Dynamic trace HTTP header tags configuration
19
+ 1 << 29, # APM_TRACING_SAMPLE_RULES: Dynamic trace sampling rules configuration
17
20
  ].freeze
18
21
 
19
22
  def products
@@ -45,7 +48,7 @@ module Datadog
45
48
  content.errored("#{e.class.name} #{e.message}: #{Array(e.backtrace).join("\n")}")
46
49
  end
47
50
 
48
- def receivers
51
+ def receivers(_telemetry)
49
52
  receiver do |repository, _changes|
50
53
  # DEV: Filter our by product. Given it will be very common
51
54
  # DEV: we can filter this out before we receive the data in this method.
@@ -28,7 +28,7 @@ module Datadog
28
28
  # @return [#match?(String)]
29
29
  def self.glob_to_regex(glob)
30
30
  # Optimization for match-all case
31
- return MATCH_ALL if glob == MATCH_ALL_PATTERN
31
+ return MATCH_ALL if /\A\*+\z/.match?(glob)
32
32
 
33
33
  # Ensure no undesired characters are treated as regex.
34
34
  glob = Regexp.quote(glob)
@@ -100,6 +100,11 @@ module Datadog
100
100
  @tags.all? do |name, matcher|
101
101
  tag = trace.get_tag(name)
102
102
 
103
+ # Floats: Matching floating point values with a non-zero decimal part is not supported.
104
+ # For floating point values with a non-zero decimal part, any all * pattern always returns true.
105
+ # Other patterns always return false.
106
+ return false if tag.is_a?(Float) && tag.truncate != tag && matcher != MATCH_ALL
107
+
103
108
  # Format metrics as strings, to allow for partial number matching (/4.*/ matching '400', '404', etc.).
104
109
  # Because metrics are floats, we use the '%g' format specifier to avoid trailing zeros, which
105
110
  # can affect exact string matching (e.g. '400' matching '400.0').
@@ -20,7 +20,7 @@ module Datadog
20
20
  super()
21
21
 
22
22
  unless sample_rate >= 0.0 && sample_rate <= 1.0
23
- Datadog.logger.error('sample rate is not between 0 and 1, falling back to 1')
23
+ Datadog.logger.warn('sample rate is not between 0 and 1, falling back to 1')
24
24
  sample_rate = 1.0
25
25
  end
26
26
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'matcher'
4
4
  require_relative 'rate_sampler'
5
+ require_relative '../../core/telemetry/logger'
5
6
 
6
7
  module Datadog
7
8
  module Tracing
@@ -35,6 +36,7 @@ module Datadog
35
36
  Datadog.logger.error(
36
37
  "Matcher failed. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
37
38
  )
39
+ Datadog::Core::Telemetry::Logger.report(e, description: 'Matcher failed')
38
40
  nil
39
41
  end
40
42
 
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'ext'
4
- require_relative 'rate_limiter'
4
+ require_relative '../../core/rate_limiter'
5
5
  require_relative 'rule'
6
+ require_relative '../../core/telemetry/logger'
6
7
 
7
8
  module Datadog
8
9
  module Tracing
@@ -28,20 +29,22 @@ module Datadog
28
29
  default_sample_rate: Datadog.configuration.tracing.sampling.default_rate,
29
30
  default_sampler: nil
30
31
  )
31
- @rules = rules
32
+ @rules = if default_sample_rate && !default_sampler
33
+ # Add to the end of the rule list a rule always matches any trace
34
+ rules << SimpleRule.new(sample_rate: default_sample_rate)
35
+ else
36
+ rules
37
+ end
32
38
  @rate_limiter = if rate_limiter
33
39
  rate_limiter
34
40
  elsif rate_limit
35
- TokenBucket.new(rate_limit)
41
+ Core::TokenBucket.new(rate_limit)
36
42
  else
37
- UnlimitedLimiter.new
43
+ Core::UnlimitedLimiter.new
38
44
  end
39
-
40
45
  @default_sampler = if default_sampler
41
46
  default_sampler
42
47
  elsif default_sample_rate
43
- # Add to the end of the rule list a rule always matches any trace
44
- @rules << SimpleRule.new(sample_rate: default_sample_rate)
45
48
  nil
46
49
  else
47
50
  # TODO: Simplify .tags access, as `Tracer#tags` can't be arbitrarily changed anymore
@@ -80,9 +83,10 @@ module Datadog
80
83
 
81
84
  new(parsed_rules, rate_limit: rate_limit, default_sample_rate: default_sample_rate)
82
85
  rescue => e
83
- Datadog.logger.error do
86
+ Datadog.logger.warn do
84
87
  "Could not parse trace sampling rules '#{rules}': #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
85
88
  end
89
+
86
90
  nil
87
91
  end
88
92
 
@@ -121,7 +125,7 @@ module Datadog
121
125
 
122
126
  return false unless sampled
123
127
 
124
- rate_limiter.allow?(1).tap do |allowed|
128
+ rate_limiter.allow?.tap do |allowed|
125
129
  set_priority(trace, allowed)
126
130
  set_limiter_metrics(trace, rate_limiter.effective_rate)
127
131
 
@@ -140,6 +144,8 @@ module Datadog
140
144
  Datadog.logger.error(
141
145
  "Rule sampling failed. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
142
146
  )
147
+ Datadog::Core::Telemetry::Logger.report(e, description: 'Rule sampling failed')
148
+
143
149
  yield(trace)
144
150
  end
145
151
 
@@ -9,7 +9,7 @@ module Datadog
9
9
  # Accept all spans (100% retention).
10
10
  DEFAULT_SAMPLE_RATE = 1.0
11
11
  # Unlimited.
12
- # @see Datadog::Tracing::Sampling::TokenBucket
12
+ # @see Datadog::Core::TokenBucket
13
13
  DEFAULT_MAX_PER_SECOND = -1
14
14
 
15
15
  # Sampling decision method used to come to the sampling decision for this span
@@ -30,7 +30,7 @@ module Datadog
30
30
  @rate_limit = rate_limit
31
31
 
32
32
  @sampler = Sampling::RateSampler.new(sample_rate)
33
- @rate_limiter = Sampling::TokenBucket.new(rate_limit)
33
+ @rate_limiter = Core::TokenBucket.new(rate_limit)
34
34
  end
35
35
 
36
36
  # This method should only be invoked for spans that are part
@@ -54,7 +54,7 @@ module Datadog
54
54
  def sample!(trace_op, span_op)
55
55
  return :not_matched unless @matcher.match?(span_op)
56
56
 
57
- if @rate_limiter.allow?(1) && @sampler.sample!(trace_op)
57
+ if @rate_limiter.allow? && @sampler.sample!(trace_op)
58
58
  span_op.set_metric(Span::Ext::TAG_MECHANISM, Sampling::Ext::Mechanism::SPAN_SAMPLING_RATE)
59
59
  span_op.set_metric(Span::Ext::TAG_RULE_RATE, @sample_rate)
60
60
  span_op.set_metric(Span::Ext::TAG_MAX_PER_SECOND, @rate_limit)
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../core/environment/identity'
4
4
  require_relative '../core/utils'
5
-
5
+ require_relative 'tracer'
6
6
  require_relative 'event'
7
7
  require_relative 'metadata/tagging'
8
8
  require_relative 'sampling/ext'
@@ -75,7 +75,9 @@ module Datadog
75
75
  metrics: nil,
76
76
  trace_state: nil,
77
77
  trace_state_unknown_fields: nil,
78
- remote_parent: false
78
+ remote_parent: false,
79
+ tracer: nil
80
+
79
81
  )
80
82
  # Attributes
81
83
  @id = id || Tracing::Utils::TraceId.next_id
@@ -98,6 +100,7 @@ module Datadog
98
100
  @profiling_enabled = profiling_enabled
99
101
  @trace_state = trace_state
100
102
  @trace_state_unknown_fields = trace_state_unknown_fields
103
+ @tracer = tracer
101
104
 
102
105
  # Generic tags
103
106
  set_tags(tags) if tags
@@ -161,6 +164,23 @@ module Datadog
161
164
  @resource || (root_span && root_span.resource)
162
165
  end
163
166
 
167
+ # When retrieving tags or metrics we need to include root span tags for sampling purposes
168
+ def get_tag(key)
169
+ super || (root_span && root_span.get_tag(key))
170
+ end
171
+
172
+ def get_metric(key)
173
+ super || (root_span && root_span.get_metric(key))
174
+ end
175
+
176
+ def tags
177
+ all_tags = {}
178
+ all_tags.merge!(root_span&.tags || {}) if root_span
179
+ all_tags.merge!(super)
180
+
181
+ all_tags
182
+ end
183
+
164
184
  # Returns true if the resource has been explicitly set
165
185
  #
166
186
  # @return [Boolean]
@@ -284,10 +304,14 @@ module Datadog
284
304
  # Returns a set of trace headers used for continuing traces.
285
305
  # Used for propagation across execution contexts.
286
306
  # Data should reflect the active state of the trace.
307
+ # DEV-3.0: Sampling is a side effect of generating the digest.
308
+ # We should move the sample call to inject and right before moving to new contexts(threads, forking etc.)
287
309
  def to_digest
288
310
  # Resolve current span ID
289
311
  span_id = @active_span && @active_span.id
290
312
  span_id ||= @parent_span_id unless finished?
313
+ # sample the trace_operation with the tracer
314
+ @tracer&.sample_trace(self) unless sampling_priority
291
315
 
292
316
  TraceDigest.new(
293
317
  span_id: span_id,
@@ -262,6 +262,17 @@ module Datadog
262
262
  context.activate!(trace, &block)
263
263
  end
264
264
 
265
+ # Sample a span, tagging the trace as appropriate.
266
+ def sample_trace(trace_op)
267
+ begin
268
+ @sampler.sample!(trace_op)
269
+ rescue StandardError => e
270
+ SAMPLE_TRACE_LOG_ONLY_ONCE.run do
271
+ Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
272
+ end
273
+ end
274
+ end
275
+
265
276
  # @!visibility private
266
277
  # TODO: make this private
267
278
  def trace_completed
@@ -331,12 +342,14 @@ module Datadog
331
342
  trace_state: digest.trace_state,
332
343
  trace_state_unknown_fields: digest.trace_state_unknown_fields,
333
344
  remote_parent: digest.span_remote,
345
+ tracer: self
334
346
  )
335
347
  else
336
348
  TraceOperation.new(
337
349
  hostname: hostname,
338
350
  profiling_enabled: profiling_enabled,
339
351
  remote_parent: false,
352
+ tracer: self
340
353
  )
341
354
  end
342
355
  end
@@ -347,7 +360,6 @@ module Datadog
347
360
  events.span_before_start.subscribe do |event_span_op, event_trace_op|
348
361
  event_trace_op.service ||= @default_service
349
362
  event_span_op.service ||= @default_service
350
- sample_trace(event_trace_op) if event_span_op && event_span_op.parent_id == 0
351
363
  end
352
364
 
353
365
  events.span_finished.subscribe do |event_span, event_trace_op|
@@ -394,7 +406,7 @@ module Datadog
394
406
  on_error: on_error,
395
407
  resource: resource,
396
408
  service: service,
397
- tags: resolve_tags(tags),
409
+ tags: resolve_tags(tags, service),
398
410
  type: type,
399
411
  id: id,
400
412
  &block
@@ -408,7 +420,7 @@ module Datadog
408
420
  resource: resource,
409
421
  service: service,
410
422
  start_time: start_time,
411
- tags: resolve_tags(tags),
423
+ tags: resolve_tags(tags, service),
412
424
  type: type,
413
425
  id: id
414
426
  )
@@ -420,15 +432,20 @@ module Datadog
420
432
  end
421
433
  # rubocop:enable Lint/UnderscorePrefixedVariableName
422
434
 
423
- def resolve_tags(tags)
424
- if @tags.any? && tags
425
- # Combine default tags with provided tags,
426
- # preferring provided tags.
427
- @tags.merge(tags)
428
- else
429
- # Use provided tags or default tags if none.
430
- tags || @tags.dup
435
+ def resolve_tags(tags, service)
436
+ merged_tags = if @tags.any? && tags
437
+ # Combine default tags with provided tags,
438
+ # preferring provided tags.
439
+ @tags.merge(tags)
440
+ else
441
+ # Use provided tags or default tags if none.
442
+ tags || @tags.dup
443
+ end
444
+ # Remove version tag if service is not the default service
445
+ if merged_tags.key?(Core::Environment::Ext::TAG_VERSION) && service != @default_service
446
+ merged_tags.delete(Core::Environment::Ext::TAG_VERSION)
431
447
  end
448
+ merged_tags
432
449
  end
433
450
 
434
451
  # Manually activate and deactivate the trace, when the span completes.
@@ -463,17 +480,6 @@ module Datadog
463
480
  end
464
481
  end
465
482
 
466
- # Sample a span, tagging the trace as appropriate.
467
- def sample_trace(trace_op)
468
- begin
469
- @sampler.sample!(trace_op)
470
- rescue StandardError => e
471
- SAMPLE_TRACE_LOG_ONLY_ONCE.run do
472
- Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
473
- end
474
- end
475
- end
476
-
477
483
  SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
478
484
  private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
479
485
 
@@ -492,6 +498,7 @@ module Datadog
492
498
 
493
499
  # Flush finished spans from the trace buffer, send them to writer.
494
500
  def flush_trace(trace_op)
501
+ sample_trace(trace_op) unless trace_op.sampling_priority
495
502
  begin
496
503
  trace = @trace_flush.consume!(trace_op)
497
504
  write(trace) if trace && !trace.empty?
@@ -38,6 +38,7 @@ module Datadog
38
38
  if stats.consecutive_errors > 0
39
39
  Datadog.logger.debug(message)
40
40
  else
41
+ # Not to report telemetry logs
41
42
  Datadog.logger.error(message)
42
43
  end
43
44
 
@@ -74,6 +74,10 @@ module Datadog
74
74
  # Add container ID, if present.
75
75
  container_id = Datadog::Core::Environment::Container.container_id
76
76
  headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CONTAINER_ID] = container_id unless container_id.nil?
77
+ # Pretend that stats computation are already done by the client
78
+ if Datadog.configuration.appsec.standalone.enabled
79
+ headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CLIENT_COMPUTED_STATS] = 'yes'
80
+ end
77
81
  end
78
82
  end
79
83
 
@@ -49,6 +49,7 @@ module Datadog
49
49
  if stats.consecutive_errors > 0
50
50
  Datadog.logger.debug(message)
51
51
  else
52
+ # Not to report telemetry logs
52
53
  Datadog.logger.error(message)
53
54
  end
54
55
 
@@ -43,7 +43,7 @@ module Datadog
43
43
  traces = process_traces(traces)
44
44
  flush_traces(traces)
45
45
  rescue StandardError => e
46
- Datadog.logger.error(
46
+ Datadog.logger.warn(
47
47
  "Error while writing traces: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
48
48
  )
49
49
  end
@@ -56,7 +56,7 @@ module Datadog
56
56
  # ensures that the thread will not die because of an exception.
57
57
  # TODO[manu]: findout the reason and reschedule the send if it's not
58
58
  # a fatal exception
59
- Datadog.logger.error(
59
+ Datadog.logger.warn(
60
60
  "Error during traces flush: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
61
61
  )
62
62
  end
@@ -70,7 +70,7 @@ module Datadog
70
70
  @run = true
71
71
  Datadog.logger.debug { "Starting thread for: #{self}" }
72
72
  @worker = Thread.new { perform }
73
- @worker.name = self.class.name unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
73
+ @worker.name = self.class.name
74
74
  @worker.thread_variable_set(:fork_safe, true)
75
75
 
76
76
  nil
@@ -68,21 +68,6 @@ module Datadog
68
68
  end
69
69
  end
70
70
 
71
- # spawns a worker for spans; they share the same transport which is thread-safe
72
- # @!visibility private
73
- def start_worker
74
- @trace_handler = ->(items, transport) { send_spans(items, transport) }
75
- @worker = Workers::AsyncTransport.new(
76
- transport: @transport,
77
- buffer_size: @buff_size,
78
- on_trace: @trace_handler,
79
- interval: @flush_interval,
80
- shutdown_timeout: @shutdown_timeout
81
- )
82
-
83
- @worker.start
84
- end
85
-
86
71
  # Gracefully shuts down this writer.
87
72
  #
88
73
  # Once stopped methods calls won't fail, but
@@ -93,19 +78,6 @@ module Datadog
93
78
  @mutex_after_fork.synchronize { stop_worker }
94
79
  end
95
80
 
96
- def stop_worker
97
- @stopped = true
98
-
99
- return if @worker.nil?
100
-
101
- @worker.stop
102
- @worker = nil
103
-
104
- true
105
- end
106
-
107
- private :start_worker, :stop_worker
108
-
109
81
  # flush spans to the trace-agent, handles spans only
110
82
  # @!visibility private
111
83
  def send_spans(traces, transport)
@@ -179,6 +151,32 @@ module Datadog
179
151
 
180
152
  private
181
153
 
154
+ # spawns a worker for spans; they share the same transport which is thread-safe
155
+ # @!visibility private
156
+ def start_worker
157
+ @trace_handler = ->(items, transport) { send_spans(items, transport) }
158
+ @worker = Workers::AsyncTransport.new(
159
+ transport: @transport,
160
+ buffer_size: @buff_size,
161
+ on_trace: @trace_handler,
162
+ interval: @flush_interval,
163
+ shutdown_timeout: @shutdown_timeout
164
+ )
165
+
166
+ @worker.start
167
+ end
168
+
169
+ def stop_worker
170
+ @stopped = true
171
+
172
+ return if @worker.nil?
173
+
174
+ @worker.stop
175
+ @worker = nil
176
+
177
+ true
178
+ end
179
+
182
180
  def reset_stats!
183
181
  @traces_flushed = 0
184
182
  @transport.stats.reset!
@@ -3,7 +3,7 @@
3
3
  module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 3
6
+ MINOR = 5
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
  BUILD = nil