datadog 2.0.0.beta2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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