ddtrace 0.46.0 → 0.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +52 -12
  3. data/.circleci/images/primary/{Dockerfile-jruby-9.2 → Dockerfile-jruby-9.2-latest} +2 -1
  4. data/.circleci/images/primary/Dockerfile-jruby-9.2.0.0 +73 -0
  5. data/.circleci/images/primary/Dockerfile-truffleruby-21.0.0 +73 -0
  6. data/.github/workflows/create-next-milestone.yml +2 -2
  7. data/.rubocop_todo.yml +3 -2
  8. data/.simplecov +6 -0
  9. data/Appraisals +1 -1
  10. data/CHANGELOG.md +83 -1
  11. data/Gemfile +19 -4
  12. data/LICENSE-3rdparty.csv +2 -0
  13. data/docker-compose.yml +75 -7
  14. data/docs/GettingStarted.md +61 -8
  15. data/lib/ddtrace/configuration.rb +92 -23
  16. data/lib/ddtrace/configuration/options.rb +2 -4
  17. data/lib/ddtrace/context_provider.rb +0 -2
  18. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +97 -26
  19. data/lib/ddtrace/contrib/aws/services.rb +1 -0
  20. data/lib/ddtrace/contrib/configurable.rb +63 -39
  21. data/lib/ddtrace/contrib/configuration/resolver.rb +70 -5
  22. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +19 -17
  23. data/lib/ddtrace/contrib/configuration/settings.rb +7 -6
  24. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -0
  25. data/lib/ddtrace/contrib/extensions.rb +26 -3
  26. data/lib/ddtrace/contrib/httpclient/instrumentation.rb +12 -16
  27. data/lib/ddtrace/contrib/httpclient/patcher.rb +5 -2
  28. data/lib/ddtrace/contrib/httprb/instrumentation.rb +12 -17
  29. data/lib/ddtrace/contrib/httprb/patcher.rb +5 -2
  30. data/lib/ddtrace/contrib/patcher.rb +8 -5
  31. data/lib/ddtrace/contrib/presto/patcher.rb +5 -2
  32. data/lib/ddtrace/contrib/rails/patcher.rb +6 -2
  33. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +11 -4
  34. data/lib/ddtrace/contrib/resque/integration.rb +1 -1
  35. data/lib/ddtrace/ext/runtime.rb +2 -0
  36. data/lib/ddtrace/patcher.rb +23 -1
  37. data/lib/ddtrace/pin.rb +5 -9
  38. data/lib/ddtrace/runtime/cgroup.rb +1 -1
  39. data/lib/ddtrace/runtime/container.rb +25 -27
  40. data/lib/ddtrace/runtime/identity.rb +8 -0
  41. data/lib/ddtrace/sync_writer.rb +5 -2
  42. data/lib/ddtrace/tracer.rb +6 -4
  43. data/lib/ddtrace/transport/http.rb +14 -5
  44. data/lib/ddtrace/transport/http/adapters/net.rb +18 -4
  45. data/lib/ddtrace/transport/http/builder.rb +5 -1
  46. data/lib/ddtrace/transport/http/env.rb +8 -0
  47. data/lib/ddtrace/transport/io/response.rb +1 -3
  48. data/lib/ddtrace/transport/io/traces.rb +6 -0
  49. data/lib/ddtrace/transport/traces.rb +15 -1
  50. data/lib/ddtrace/utils/compression.rb +27 -0
  51. data/lib/ddtrace/utils/object_set.rb +41 -0
  52. data/lib/ddtrace/utils/only_once.rb +40 -0
  53. data/lib/ddtrace/utils/sequence.rb +17 -0
  54. data/lib/ddtrace/utils/string_table.rb +45 -0
  55. data/lib/ddtrace/utils/time.rb +7 -0
  56. data/lib/ddtrace/vendor/multipart-post/LICENSE +11 -0
  57. data/lib/ddtrace/vendor/multipart-post/multipart.rb +12 -0
  58. data/lib/ddtrace/vendor/multipart-post/multipart/post.rb +8 -0
  59. data/lib/ddtrace/vendor/multipart-post/multipart/post/composite_read_io.rb +116 -0
  60. data/lib/ddtrace/vendor/multipart-post/multipart/post/multipartable.rb +57 -0
  61. data/lib/ddtrace/vendor/multipart-post/multipart/post/parts.rb +135 -0
  62. data/lib/ddtrace/vendor/multipart-post/multipart/post/version.rb +9 -0
  63. data/lib/ddtrace/vendor/multipart-post/net/http/post/multipart.rb +32 -0
  64. data/lib/ddtrace/version.rb +1 -1
  65. data/lib/ddtrace/workers/async.rb +3 -3
  66. data/lib/ddtrace/workers/loop.rb +14 -3
  67. data/lib/ddtrace/workers/queue.rb +1 -0
  68. data/lib/ddtrace/workers/trace_writer.rb +1 -0
  69. data/lib/ddtrace/writer.rb +4 -1
  70. metadata +21 -4
@@ -0,0 +1,17 @@
1
+ module Datadog
2
+ module Utils
3
+ # Generates values from a consistent sequence
4
+ class Sequence
5
+ def initialize(seed = 0, &block)
6
+ @current = seed
7
+ @next_item = block
8
+ end
9
+
10
+ def next
11
+ next_item = @next_item ? @next_item.call(@current) : @current
12
+ @current += 1
13
+ next_item
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ require 'ddtrace/utils/sequence'
2
+
3
+ module Datadog
4
+ module Utils
5
+ # Tracks strings and returns IDs
6
+ class StringTable
7
+ def initialize
8
+ @sequence = Sequence.new
9
+ @ids = { ''.freeze => @sequence.next }
10
+ end
11
+
12
+ # Returns an ID for the string
13
+ def fetch(string)
14
+ @ids[string.to_s] ||= @sequence.next
15
+ end
16
+
17
+ # Returns the canonical copy of this string
18
+ # Typically used for psuedo interning; reduce
19
+ # identical copies of a string to one object.
20
+ def fetch_string(string)
21
+ return nil if string.nil?
22
+
23
+ # Co-erce to string
24
+ string = string.to_s
25
+
26
+ # Add to string table if no match
27
+ @ids[string] = @sequence.next unless @ids.key?(string)
28
+
29
+ # Get and return matching string in table
30
+ # NOTE: Have to resolve the key and retrieve from table again
31
+ # because "string" argument is not same object as string key.
32
+ id = @ids[string]
33
+ @ids.key(id)
34
+ end
35
+
36
+ def [](id)
37
+ @ids.key(id)
38
+ end
39
+
40
+ def strings
41
+ @ids.keys
42
+ end
43
+ end
44
+ end
45
+ end
@@ -33,6 +33,13 @@ module Datadog
33
33
  def now_provider=(block)
34
34
  define_singleton_method(:now, &block)
35
35
  end
36
+
37
+ def measure
38
+ before = get_time
39
+ yield
40
+ after = get_time
41
+ after - before
42
+ end
36
43
  end
37
44
  end
38
45
  end
@@ -0,0 +1,11 @@
1
+ Released under the MIT license.
2
+
3
+ Copyright, 2007-2013, by Nick Sieger.
4
+ Copyright, 2017, by Samuel G. D. Williams.
5
+ Copyright, 2019, by Patrick Davey.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,12 @@
1
+ #--
2
+ # Copyright (c) 2007-2013 Nick Sieger.
3
+ # See the file README.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ module Datadog
8
+ module Vendor
9
+ module Multipart
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Datadog
2
+ module Vendor
3
+ module Multipart
4
+ module Post
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,116 @@
1
+ #--
2
+ # Copyright (c) 2007-2012 Nick Sieger.
3
+ # See the file README.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ # Concatenate together multiple IO objects into a single, composite IO object
8
+ # for purposes of reading as a single stream.
9
+ #
10
+ # @example
11
+ # crio = CompositeReadIO.new(StringIO.new('one'),
12
+ # StringIO.new('two'),
13
+ # StringIO.new('three'))
14
+ # puts crio.read # => "onetwothree"
15
+ module Datadog
16
+ module Vendor
17
+ module Multipart
18
+ module Post
19
+ class CompositeReadIO
20
+ # Create a new composite-read IO from the arguments, all of which should
21
+ # respond to #read in a manner consistent with IO.
22
+ def initialize(*ios)
23
+ @ios = ios.flatten
24
+ @index = 0
25
+ end
26
+
27
+ # Read from IOs in order until `length` bytes have been received.
28
+ def read(length = nil, outbuf = nil)
29
+ got_result = false
30
+ outbuf = outbuf ? outbuf.replace("") : ""
31
+
32
+ while io = current_io
33
+ if result = io.read(length)
34
+ got_result ||= !result.nil?
35
+ result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
36
+ outbuf << result
37
+ length -= result.length if length
38
+ break if length == 0
39
+ end
40
+ advance_io
41
+ end
42
+ (!got_result && length) ? nil : outbuf
43
+ end
44
+
45
+ def rewind
46
+ @ios.each { |io| io.rewind }
47
+ @index = 0
48
+ end
49
+
50
+ private
51
+
52
+ def current_io
53
+ @ios[@index]
54
+ end
55
+
56
+ def advance_io
57
+ @index += 1
58
+ end
59
+ end
60
+
61
+ # Convenience methods for dealing with files and IO that are to be uploaded.
62
+ class UploadIO
63
+ attr_reader :content_type, :original_filename, :local_path, :io, :opts
64
+
65
+ # Create an upload IO suitable for including in the params hash of a
66
+ # Net::HTTP::Post::Multipart.
67
+ #
68
+ # Can take two forms. The first accepts a filename and content type, and
69
+ # opens the file for reading (to be closed by finalizer).
70
+ #
71
+ # The second accepts an already-open IO, but also requires a third argument,
72
+ # the filename from which it was opened (particularly useful/recommended if
73
+ # uploading directly from a form in a framework, which often save the file to
74
+ # an arbitrarily named RackMultipart file in /tmp).
75
+ #
76
+ # @example
77
+ # UploadIO.new("file.txt", "text/plain")
78
+ # UploadIO.new(file_io, "text/plain", "file.txt")
79
+ def initialize(filename_or_io, content_type, filename = nil, opts = {})
80
+ io = filename_or_io
81
+ local_path = ""
82
+ if io.respond_to? :read
83
+ # in Ruby 1.9.2, StringIOs no longer respond to path
84
+ # (since they respond to :length, so we don't need their local path, see parts.rb:41)
85
+ local_path = filename_or_io.respond_to?(:path) ? filename_or_io.path : "local.path"
86
+ else
87
+ io = File.open(filename_or_io)
88
+ local_path = filename_or_io
89
+ end
90
+ filename ||= local_path
91
+
92
+ @content_type = content_type
93
+ @original_filename = File.basename(filename)
94
+ @local_path = local_path
95
+ @io = io
96
+ @opts = opts
97
+ end
98
+
99
+ def self.convert!(io, content_type, original_filename, local_path)
100
+ raise ArgumentError, "convert! has been removed. You must now wrap IOs " \
101
+ "using:\nUploadIO.new(filename_or_io, content_type, " \
102
+ "filename=nil)\nPlease update your code."
103
+ end
104
+
105
+ def method_missing(*args)
106
+ @io.send(*args)
107
+ end
108
+
109
+ def respond_to?(meth, include_all = false)
110
+ @io.respond_to?(meth, include_all) || super(meth, include_all)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,57 @@
1
+ #--
2
+ # Copyright (c) 2007-2013 Nick Sieger.
3
+ # See the file README.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ require 'ddtrace/vendor/multipart-post/multipart/post/parts'
8
+ require 'ddtrace/vendor/multipart-post/multipart/post/composite_read_io'
9
+ require 'securerandom'
10
+
11
+ module Datadog
12
+ module Vendor
13
+ module Multipart
14
+ module Post
15
+ module Multipartable
16
+ def self.secure_boundary
17
+ # https://tools.ietf.org/html/rfc7230
18
+ # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
19
+ # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
20
+ # / DIGIT / ALPHA
21
+
22
+ # https://tools.ietf.org/html/rfc2046
23
+ # bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
24
+ # "+" / "_" / "," / "-" / "." /
25
+ # "/" / ":" / "=" / "?"
26
+
27
+ "--#{SecureRandom.uuid}"
28
+ end
29
+
30
+ def initialize(path, params, headers={}, boundary = Multipartable.secure_boundary)
31
+ headers = headers.clone # don't want to modify the original variable
32
+ parts_headers = headers.delete(:parts) || {}
33
+ super(path, headers)
34
+ parts = params.map do |k,v|
35
+ case v
36
+ when Array
37
+ v.map {|item| Parts::Part.new(boundary, "#{k}[]", item, parts_headers[k]) }
38
+ else
39
+ Parts::Part.new(boundary, k, v, parts_headers[k])
40
+ end
41
+ end.flatten
42
+ parts << Parts::EpiloguePart.new(boundary)
43
+ ios = parts.map {|p| p.to_io }
44
+ self.set_content_type(headers["Content-Type"] || "multipart/form-data",
45
+ { "boundary" => boundary })
46
+ self.content_length = parts.inject(0) {|sum,i| sum + i.length }
47
+ self.body_stream = CompositeReadIO.new(*ios)
48
+
49
+ @boundary = boundary
50
+ end
51
+
52
+ attr :boundary
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,135 @@
1
+ #--
2
+ # Copyright (c) 2007-2013 Nick Sieger.
3
+ # See the file README.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ module Datadog
8
+ module Vendor
9
+ module Multipart
10
+ module Post
11
+ module Parts
12
+ module Part
13
+ def self.new(boundary, name, value, headers = {})
14
+ headers ||= {} # avoid nil values
15
+ if file?(value)
16
+ FilePart.new(boundary, name, value, headers)
17
+ else
18
+ ParamPart.new(boundary, name, value, headers)
19
+ end
20
+ end
21
+
22
+ def self.file?(value)
23
+ value.respond_to?(:content_type) && value.respond_to?(:original_filename)
24
+ end
25
+
26
+ def length
27
+ @part.length
28
+ end
29
+
30
+ def to_io
31
+ @io
32
+ end
33
+ end
34
+
35
+ # Represents a parametric part to be filled with given value.
36
+ class ParamPart
37
+ include Part
38
+
39
+ # @param boundary [String]
40
+ # @param name [#to_s]
41
+ # @param value [String]
42
+ # @param headers [Hash] Content-Type and Content-ID are used, if present.
43
+ def initialize(boundary, name, value, headers = {})
44
+ @part = build_part(boundary, name, value, headers)
45
+ @io = StringIO.new(@part)
46
+ end
47
+
48
+ def length
49
+ @part.bytesize
50
+ end
51
+
52
+ # @param boundary [String]
53
+ # @param name [#to_s]
54
+ # @param value [String]
55
+ # @param headers [Hash] Content-Type is used, if present.
56
+ def build_part(boundary, name, value, headers = {})
57
+ part = ''
58
+ part << "--#{boundary}\r\n"
59
+ part << "Content-ID: #{headers["Content-ID"]}\r\n" if headers["Content-ID"]
60
+ part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n"
61
+ part << "Content-Type: #{headers["Content-Type"]}\r\n" if headers["Content-Type"]
62
+ part << "\r\n"
63
+ part << "#{value}\r\n"
64
+ end
65
+ end
66
+
67
+ # Represents a part to be filled from file IO.
68
+ class FilePart
69
+ include Part
70
+
71
+ attr_reader :length
72
+
73
+ # @param boundary [String]
74
+ # @param name [#to_s]
75
+ # @param io [IO]
76
+ # @param headers [Hash]
77
+ def initialize(boundary, name, io, headers = {})
78
+ file_length = io.respond_to?(:length) ? io.length : File.size(io.local_path)
79
+ @head = build_head(boundary, name, io.original_filename, io.content_type, file_length,
80
+ io.respond_to?(:opts) ? io.opts.merge(headers) : headers)
81
+ @foot = "\r\n"
82
+ @length = @head.bytesize + file_length + @foot.length
83
+ @io = CompositeReadIO.new(StringIO.new(@head), io, StringIO.new(@foot))
84
+ end
85
+
86
+ # @param boundary [String]
87
+ # @param name [#to_s]
88
+ # @param filename [String]
89
+ # @param type [String]
90
+ # @param content_len [Integer]
91
+ # @param opts [Hash]
92
+ def build_head(boundary, name, filename, type, content_len, opts = {})
93
+ opts = opts.clone
94
+
95
+ trans_encoding = opts.delete("Content-Transfer-Encoding") || "binary"
96
+ content_disposition = opts.delete("Content-Disposition") || "form-data"
97
+
98
+ part = ''
99
+ part << "--#{boundary}\r\n"
100
+ part << "Content-Disposition: #{content_disposition}; name=\"#{name.to_s}\"; filename=\"#{filename}\"\r\n"
101
+ part << "Content-Length: #{content_len}\r\n"
102
+ if content_id = opts.delete("Content-ID")
103
+ part << "Content-ID: #{content_id}\r\n"
104
+ end
105
+
106
+ if opts["Content-Type"] != nil
107
+ part << "Content-Type: " + opts["Content-Type"] + "\r\n"
108
+ else
109
+ part << "Content-Type: #{type}\r\n"
110
+ end
111
+
112
+ part << "Content-Transfer-Encoding: #{trans_encoding}\r\n"
113
+
114
+ opts.each do |k, v|
115
+ part << "#{k}: #{v}\r\n"
116
+ end
117
+
118
+ part << "\r\n"
119
+ end
120
+ end
121
+
122
+ # Represents the epilogue or closing boundary.
123
+ class EpiloguePart
124
+ include Part
125
+
126
+ def initialize(boundary)
127
+ @part = "--#{boundary}--\r\n"
128
+ @io = StringIO.new(@part)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,9 @@
1
+ module Datadog
2
+ module Vendor
3
+ module Multipart
4
+ module Post
5
+ VERSION = "2.1.1"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ #--
2
+ # Copyright (c) 2007-2012 Nick Sieger.
3
+ # See the file README.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ require 'net/http'
8
+ require 'stringio'
9
+ require 'cgi'
10
+ require 'ddtrace/vendor/multipart-post/multipart/post/parts'
11
+ require 'ddtrace/vendor/multipart-post/multipart/post/composite_read_io'
12
+ require 'ddtrace/vendor/multipart-post/multipart/post/multipartable'
13
+
14
+ module Datadog
15
+ module Vendor
16
+ module Net
17
+ class HTTP
18
+ class Put
19
+ class Multipart < ::Net::HTTP::Put
20
+ include ::Datadog::Vendor::Multipart::Post::Multipartable
21
+ end
22
+ end
23
+
24
+ class Post
25
+ class Multipart < ::Net::HTTP::Post
26
+ include ::Datadog::Vendor::Multipart::Post::Multipartable
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end