datadog 2.0.0.beta2 → 2.0.0.rc1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -1
  3. data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +1 -1
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +8 -20
  5. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +18 -10
  6. data/ext/datadog_profiling_native_extension/crashtracker.c +108 -0
  7. data/ext/datadog_profiling_native_extension/extconf.rb +9 -23
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +38 -3
  9. data/ext/datadog_profiling_native_extension/heap_recorder.h +5 -0
  10. data/ext/datadog_profiling_native_extension/http_transport.c +0 -93
  11. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +86 -0
  12. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +4 -0
  13. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +2 -12
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +25 -86
  15. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  16. data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -5
  17. data/ext/datadog_profiling_native_extension/stack_recorder.c +156 -55
  18. data/lib/datadog/appsec/contrib/devise/tracking.rb +8 -0
  19. data/lib/datadog/core/configuration/settings.rb +10 -79
  20. data/lib/datadog/core/remote/client.rb +1 -5
  21. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  22. data/lib/datadog/core/remote/dispatcher.rb +3 -3
  23. data/lib/datadog/core/telemetry/emitter.rb +1 -1
  24. data/lib/datadog/core/telemetry/http/response.rb +4 -0
  25. data/lib/datadog/opentelemetry/sdk/span_processor.rb +18 -1
  26. data/lib/datadog/profiling/component.rb +26 -2
  27. data/lib/datadog/profiling/crashtracker.rb +91 -0
  28. data/lib/datadog/profiling/exporter.rb +6 -3
  29. data/lib/datadog/profiling/http_transport.rb +7 -11
  30. data/lib/datadog/profiling/profiler.rb +9 -2
  31. data/lib/datadog/profiling/stack_recorder.rb +6 -2
  32. data/lib/datadog/profiling.rb +1 -0
  33. data/lib/datadog/tracing/component.rb +5 -1
  34. data/lib/datadog/tracing/configuration/dynamic.rb +39 -1
  35. data/lib/datadog/tracing/configuration/settings.rb +1 -0
  36. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -0
  37. data/lib/datadog/tracing/contrib/active_record/integration.rb +10 -0
  38. data/lib/datadog/tracing/contrib/configuration/resolver.rb +43 -0
  39. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +1 -1
  40. data/lib/datadog/tracing/remote.rb +5 -1
  41. data/lib/datadog/tracing/sampling/ext.rb +5 -1
  42. data/lib/datadog/tracing/sampling/matcher.rb +60 -31
  43. data/lib/datadog/tracing/sampling/rule.rb +12 -5
  44. data/lib/datadog/tracing/sampling/rule_sampler.rb +17 -1
  45. data/lib/datadog/tracing/sampling/span/matcher.rb +13 -41
  46. data/lib/datadog/tracing/span_link.rb +12 -6
  47. data/lib/datadog/tracing/span_operation.rb +6 -4
  48. data/lib/datadog/version.rb +1 -1
  49. metadata +7 -5
@@ -6,6 +6,9 @@ module Datadog
6
6
  # Checks if a trace conforms to a matching criteria.
7
7
  # @abstract
8
8
  class Matcher
9
+ # Pattern that matches any string
10
+ MATCH_ALL_PATTERN = '*'
11
+
9
12
  # Returns `true` if the trace should conforms to this rule, `false` otherwise
10
13
  #
11
14
  # @param [TraceOperation] trace
@@ -13,20 +16,49 @@ module Datadog
13
16
  def match?(trace)
14
17
  raise NotImplementedError
15
18
  end
16
- end
17
19
 
18
- # A {Datadog::Sampling::Matcher} that supports matching a trace by
19
- # trace name and/or service name.
20
- class SimpleMatcher < Matcher
21
- # Returns `true` for case equality (===) with any object
20
+ # Converts a glob pattern String to a case-insensitive String matcher object.
21
+ # The match object will only return `true` if it matches the complete String.
22
+ #
23
+ # The following special characters are supported:
24
+ # - `?` matches any single character
25
+ # - `*` matches any substring
26
+ #
27
+ # @param glob [String]
28
+ # @return [#match?(String)]
29
+ def self.glob_to_regex(glob)
30
+ # Optimization for match-all case
31
+ return MATCH_ALL if glob == MATCH_ALL_PATTERN
32
+
33
+ # Ensure no undesired characters are treated as regex.
34
+ glob = Regexp.quote(glob)
35
+
36
+ # Our valid special characters, `?` and `*`, were just escaped
37
+ # by `Regexp.quote` above. We need to unescape them:
38
+ glob.gsub!('\?', '.') # Any single character
39
+ glob.gsub!('\*', '.*') # Any substring
40
+
41
+ # Patterns have to match the whole input string
42
+ glob = "\\A#{glob}\\z"
43
+
44
+ Regexp.new(glob, Regexp::IGNORECASE)
45
+ end
46
+
47
+ # Returns `true` for any input
22
48
  MATCH_ALL = Class.new do
23
- # DEV: A class that implements `#===` is ~20% faster than
24
- # DEV: a `Proc` that always returns `true`.
25
- def ===(other)
49
+ def match?(_other)
26
50
  true
27
51
  end
52
+
53
+ def inspect
54
+ "MATCH_ALL:Matcher('*')"
55
+ end
28
56
  end.new
57
+ end
29
58
 
59
+ # A {Datadog::Sampling::Matcher} that supports matching a trace by
60
+ # trace name and/or service name.
61
+ class SimpleMatcher < Matcher
30
62
  attr_reader :name, :service, :resource, :tags
31
63
 
32
64
  # @param name [String,Regexp,Proc] Matcher for case equality (===) with the trace name,
@@ -35,16 +67,30 @@ module Datadog
35
67
  # defaults to always match
36
68
  # @param resource [String,Regexp,Proc] Matcher for case equality (===) with the resource name,
37
69
  # defaults to always match
38
- def initialize(name: MATCH_ALL, service: MATCH_ALL, resource: MATCH_ALL, tags: {})
70
+ def initialize(
71
+ name: MATCH_ALL_PATTERN,
72
+ service: MATCH_ALL_PATTERN,
73
+ resource: MATCH_ALL_PATTERN,
74
+ tags: {}
75
+ )
39
76
  super()
40
- @name = name
41
- @service = service
42
- @resource = resource
77
+
78
+ name = Matcher.glob_to_regex(name)
79
+ service = Matcher.glob_to_regex(service)
80
+ resource = Matcher.glob_to_regex(resource)
81
+ tags = tags.transform_values { |matcher| Matcher.glob_to_regex(matcher) }
82
+
83
+ @name = name || Datadog::Tracing::Sampling::Matcher::MATCH_ALL
84
+ @service = service || Datadog::Tracing::Sampling::Matcher::MATCH_ALL
85
+ @resource = resource || Datadog::Tracing::Sampling::Matcher::MATCH_ALL
43
86
  @tags = tags
44
87
  end
45
88
 
46
89
  def match?(trace)
47
- name === trace.name && service === trace.service && resource === trace.resource && tags_match?(trace)
90
+ @name.match?(trace.name) &&
91
+ @service.match?(trace.service) &&
92
+ @resource.match?(trace.resource) &&
93
+ tags_match?(trace)
48
94
  end
49
95
 
50
96
  private
@@ -59,27 +105,10 @@ module Datadog
59
105
  # can affect exact string matching (e.g. '400' matching '400.0').
60
106
  tag = format('%g', tag) if tag.is_a?(Numeric)
61
107
 
62
- matcher === tag
108
+ matcher.match?(tag)
63
109
  end
64
110
  end
65
111
  end
66
-
67
- # A {Datadog::Tracing::Sampling::Matcher} that allows for arbitrary trace matching
68
- # based on the return value of a provided block.
69
- class ProcMatcher < Matcher
70
- attr_reader :block
71
-
72
- # @yield [name, service] Provides trace name and service to the block
73
- # @yieldreturn [Boolean] Whether the trace conforms to this matcher
74
- def initialize(&block)
75
- super()
76
- @block = block
77
- end
78
-
79
- def match?(trace)
80
- block.call(trace.name, trace.service)
81
- end
82
- end
83
112
  end
84
113
  end
85
114
  end
@@ -10,13 +10,18 @@ module Datadog
10
10
  # a specific criteria and what sampling strategy to
11
11
  # apply in case of a positive match.
12
12
  class Rule
13
- attr_reader :matcher, :sampler
13
+ PROVENANCE_LOCAL = :local
14
+ PROVENANCE_REMOTE_USER = :customer
15
+ PROVENANCE_REMOTE_DYNAMIC = :dynamic
16
+
17
+ attr_reader :matcher, :sampler, :provenance
14
18
 
15
19
  # @param [Matcher] matcher A matcher to verify trace conformity against
16
20
  # @param [Sampler] sampler A sampler to be consulted on a positive match
17
- def initialize(matcher, sampler)
21
+ def initialize(matcher, sampler, provenance)
18
22
  @matcher = matcher
19
23
  @sampler = sampler
24
+ @provenance = provenance
20
25
  end
21
26
 
22
27
  # Evaluates if the provided `trace` conforms to the `matcher`.
@@ -55,8 +60,10 @@ module Datadog
55
60
  # defaults to always match
56
61
  # @param sample_rate [Float] Sampling rate between +[0,1]+
57
62
  def initialize(
58
- name: SimpleMatcher::MATCH_ALL, service: SimpleMatcher::MATCH_ALL,
59
- resource: SimpleMatcher::MATCH_ALL, tags: {}, sample_rate: 1.0
63
+ name: SimpleMatcher::MATCH_ALL_PATTERN, service: SimpleMatcher::MATCH_ALL_PATTERN,
64
+ resource: SimpleMatcher::MATCH_ALL_PATTERN, tags: {},
65
+ provenance: Rule::PROVENANCE_LOCAL,
66
+ sample_rate: 1.0
60
67
  )
61
68
  # We want to allow 0.0 to drop all traces, but {Datadog::Tracing::Sampling::RateSampler}
62
69
  # considers 0.0 an invalid rate and falls back to 100% sampling.
@@ -69,7 +76,7 @@ module Datadog
69
76
  sampler = RateSampler.new
70
77
  sampler.sample_rate = sample_rate
71
78
 
72
- super(SimpleMatcher.new(name: name, service: service, resource: resource, tags: tags), sampler)
79
+ super(SimpleMatcher.new(name: name, service: service, resource: resource, tags: tags), sampler, provenance)
73
80
  end
74
81
  end
75
82
  end
@@ -65,6 +65,12 @@ module Datadog
65
65
  resource: rule['resource'],
66
66
  tags: rule['tags'],
67
67
  sample_rate: sample_rate,
68
+ provenance: if (provenance = rule['provenance'])
69
+ # `Rule::PROVENANCE_*` values are symbols, so convert strings to match
70
+ provenance.to_sym
71
+ else
72
+ Rule::PROVENANCE_LOCAL
73
+ end,
68
74
  }
69
75
 
70
76
  kwargs.compact!
@@ -118,7 +124,17 @@ module Datadog
118
124
  rate_limiter.allow?(1).tap do |allowed|
119
125
  set_priority(trace, allowed)
120
126
  set_limiter_metrics(trace, rate_limiter.effective_rate)
121
- trace.set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, Ext::Decision::TRACE_SAMPLING_RULE)
127
+
128
+ provenance = case rule.provenance
129
+ when Rule::PROVENANCE_REMOTE_USER
130
+ Ext::Decision::REMOTE_USER_RULE
131
+ when Rule::PROVENANCE_REMOTE_DYNAMIC
132
+ Ext::Decision::REMOTE_DYNAMIC_RULE
133
+ else
134
+ Ext::Decision::TRACE_SAMPLING_RULE
135
+ end
136
+
137
+ trace.set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, provenance)
122
138
  end
123
139
  rescue StandardError => e
124
140
  Datadog.logger.error(
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../matcher'
4
+
3
5
  module Datadog
4
6
  module Tracing
5
7
  module Sampling
@@ -31,29 +33,19 @@ module Datadog
31
33
  # @param name_pattern [String] a pattern to be matched against {SpanOperation#name}
32
34
  # @param service_pattern [String] a pattern to be matched against {SpanOperation#service}
33
35
  def initialize(name_pattern: MATCH_ALL_PATTERN, service_pattern: MATCH_ALL_PATTERN)
34
- @name = pattern_to_regex(name_pattern)
35
- @service = pattern_to_regex(service_pattern)
36
+ @name = Sampling::Matcher.glob_to_regex(name_pattern)
37
+ @service = Sampling::Matcher.glob_to_regex(service_pattern)
36
38
  end
37
39
 
38
- # {Regexp#match?} was added in Ruby 2.4, and it's measurably
39
- # the least costly way to get a boolean result for a Regexp match.
40
- # @see https://www.ruby-lang.org/en/news/2016/12/25/ruby-2-4-0-released/
41
- if Regexp.method_defined?(:match?)
42
- # Returns `true` if the span conforms to the configured patterns,
43
- # `false` otherwise
44
- #
45
- # @param [SpanOperation] span
46
- # @return [Boolean]
47
- def match?(span)
48
- # Matching is performed at the end of the lifecycle of a Span,
49
- # thus both `name` and `service` are guaranteed to be not `nil`.
50
- @name.match?(span.name) && @service.match?(span.service)
51
- end
52
- else
53
- # DEV: Remove when support for Ruby 2.3 and older is removed.
54
- def match?(span)
55
- @name === span.name && @service === span.service
56
- end
40
+ # Returns `true` if the span conforms to the configured patterns,
41
+ # `false` otherwise
42
+ #
43
+ # @param [SpanOperation] span
44
+ # @return [Boolean]
45
+ def match?(span)
46
+ # Matching is performed at the end of the lifecycle of a Span,
47
+ # thus both `name` and `service` are guaranteed to be not `nil`.
48
+ @name.match?(span.name) && @service.match?(span.service)
57
49
  end
58
50
 
59
51
  def ==(other)
@@ -62,26 +54,6 @@ module Datadog
62
54
  name == other.name &&
63
55
  service == other.service
64
56
  end
65
-
66
- private
67
-
68
- # @param pattern [String]
69
- # @return [Regexp]
70
- def pattern_to_regex(pattern)
71
- # Ensure no undesired characters are treated as regex.
72
- # Our valid special characters, `?` and `*`,
73
- # will be escaped so...
74
- pattern = Regexp.quote(pattern)
75
-
76
- # ...we account for that here:
77
- pattern.gsub!('\?', '.') # Any single character
78
- pattern.gsub!('\*', '.*') # Any substring
79
-
80
- # Patterns have to match the whole input string
81
- pattern = "\\A#{pattern}\\z"
82
-
83
- Regexp.new(pattern)
84
- end
85
57
  end
86
58
  end
87
59
  end
@@ -41,13 +41,19 @@ module Datadog
41
41
  attr_reader :dropped_attributes
42
42
 
43
43
  def initialize(
44
- attributes: nil,
45
- digest: nil
44
+ digest,
45
+ attributes: nil
46
46
  )
47
- @span_id = digest&.span_id
48
- @trace_id = digest&.trace_id
49
- @trace_flags = digest&.trace_flags
50
- @trace_state = digest&.trace_state && digest&.trace_state.dup
47
+ @span_id = digest.span_id
48
+ @trace_id = digest.trace_id
49
+ @trace_flags = if digest.trace_sampling_priority.nil?
50
+ nil
51
+ elsif digest.trace_sampling_priority > 0
52
+ 1
53
+ else
54
+ 0
55
+ end
56
+ @trace_state = digest.trace_state && digest.trace_state.dup
51
57
  @dropped_attributes = 0
52
58
  @attributes = (attributes && attributes.dup) || {}
53
59
  end
@@ -35,9 +35,7 @@ module Datadog
35
35
  :start_time,
36
36
  :trace_id,
37
37
  :type
38
-
39
- attr_accessor \
40
- :status
38
+ attr_accessor :links, :status
41
39
 
42
40
  def initialize(
43
41
  name,
@@ -49,7 +47,8 @@ module Datadog
49
47
  start_time: nil,
50
48
  tags: nil,
51
49
  trace_id: nil,
52
- type: nil
50
+ type: nil,
51
+ links: nil
53
52
  )
54
53
  # Ensure dynamically created strings are UTF-8 encoded.
55
54
  #
@@ -66,6 +65,8 @@ module Datadog
66
65
  @trace_id = trace_id || Tracing::Utils::TraceId.next_id
67
66
 
68
67
  @status = 0
68
+ # stores array of span links
69
+ @links = links || []
69
70
 
70
71
  # start_time and end_time track wall clock. In Ruby, wall clock
71
72
  # has less accuracy than monotonic clock, so if possible we look to only use wall clock
@@ -452,6 +453,7 @@ module Datadog
452
453
  status: @status,
453
454
  type: @type,
454
455
  trace_id: @trace_id,
456
+ links: @links,
455
457
  service_entry: parent.nil? || (service && parent.service != service)
456
458
  )
457
459
  end
@@ -5,7 +5,7 @@ module Datadog
5
5
  MAJOR = 2
6
6
  MINOR = 0
7
7
  PATCH = 0
8
- PRE = 'beta2'
8
+ PRE = 'rc1'
9
9
  BUILD = nil
10
10
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow
11
11
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta2
4
+ version: 2.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-18 00:00:00.000000000 Z
11
+ date: 2024-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 7.0.0.1.0
61
+ version: 9.0.0.1.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 7.0.0.1.0
68
+ version: 9.0.0.1.0
69
69
  description: |
70
70
  datadog is Datadog's client library for Ruby. It includes a suite of tools
71
71
  which provide visibility into the performance and security of Ruby applications,
@@ -106,6 +106,7 @@ files:
106
106
  - ext/datadog_profiling_native_extension/collectors_stack.h
107
107
  - ext/datadog_profiling_native_extension/collectors_thread_context.c
108
108
  - ext/datadog_profiling_native_extension/collectors_thread_context.h
109
+ - ext/datadog_profiling_native_extension/crashtracker.c
109
110
  - ext/datadog_profiling_native_extension/extconf.rb
110
111
  - ext/datadog_profiling_native_extension/heap_recorder.c
111
112
  - ext/datadog_profiling_native_extension/heap_recorder.h
@@ -351,6 +352,7 @@ files:
351
352
  - lib/datadog/profiling/collectors/stack.rb
352
353
  - lib/datadog/profiling/collectors/thread_context.rb
353
354
  - lib/datadog/profiling/component.rb
355
+ - lib/datadog/profiling/crashtracker.rb
354
356
  - lib/datadog/profiling/exporter.rb
355
357
  - lib/datadog/profiling/ext.rb
356
358
  - lib/datadog/profiling/ext/forking.rb
@@ -856,7 +858,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
856
858
  - !ruby/object:Gem::Version
857
859
  version: 2.0.0
858
860
  requirements: []
859
- rubygems_version: 3.4.21
861
+ rubygems_version: 3.4.10
860
862
  signing_key:
861
863
  specification_version: 4
862
864
  summary: Datadog tracing code for your Ruby applications