ddtrace 1.4.2 → 1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -2
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +0 -2
- data/lib/datadog/appsec/configuration/settings.rb +0 -2
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +0 -2
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/ci/ext/environment.rb +16 -4
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +0 -3
- data/lib/datadog/core/configuration/components.rb +8 -2
- data/lib/datadog/core/configuration/settings.rb +69 -2
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/header_collection.rb +41 -0
- data/lib/datadog/core/telemetry/collector.rb +0 -2
- data/lib/datadog/core/workers/async.rb +0 -2
- data/lib/datadog/profiling/collectors/old_stack.rb +1 -1
- data/lib/datadog/profiling.rb +1 -1
- data/lib/datadog/tracing/client_ip.rb +153 -0
- data/lib/datadog/tracing/configuration/ext.rb +12 -0
- data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +0 -2
- data/lib/datadog/tracing/contrib/ext.rb +19 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -2
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -4
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +92 -38
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +83 -9
- data/lib/datadog/tracing/flush.rb +57 -35
- data/lib/datadog/tracing/metadata/ext.rb +3 -9
- data/lib/datadog/tracing/metadata/tagging.rb +9 -0
- data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +10 -0
- data/lib/datadog/tracing/sampling/span/ext.rb +29 -0
- data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
- data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
- data/lib/datadog/tracing/sampling/span/sampler.rb +64 -0
- data/lib/datadog/tracing/span_operation.rb +0 -2
- data/lib/datadog/tracing/trace_operation.rb +22 -3
- data/lib/datadog/tracing/trace_segment.rb +1 -2
- data/lib/datadog/tracing/tracer.rb +31 -5
- data/lib/ddtrace/version.rb +2 -2
- metadata +19 -5
@@ -3,7 +3,6 @@
|
|
3
3
|
module Datadog
|
4
4
|
module Tracing
|
5
5
|
module Contrib
|
6
|
-
# rubocop:disable Metrics/ModuleLength:
|
7
6
|
module Aws
|
8
7
|
SERVICES = %w[
|
9
8
|
ACM
|
@@ -117,7 +116,6 @@ module Datadog
|
|
117
116
|
XRay
|
118
117
|
].freeze
|
119
118
|
end
|
120
|
-
# rubocop:enable Metrics/ModuleLength:
|
121
119
|
end
|
122
120
|
end
|
123
121
|
end
|
@@ -18,7 +18,6 @@ module Datadog
|
|
18
18
|
end
|
19
19
|
|
20
20
|
# InstanceMethods - implementing instrumentation
|
21
|
-
# rubocop:disable Metrics/ModuleLength
|
22
21
|
module InstanceMethods
|
23
22
|
include Contrib::HttpAnnotationHelper
|
24
23
|
|
@@ -168,7 +167,6 @@ module Datadog
|
|
168
167
|
datadog_configuration[:analytics_sample_rate]
|
169
168
|
end
|
170
169
|
end
|
171
|
-
# rubocop:enable Metrics/ModuleLength
|
172
170
|
end
|
173
171
|
end
|
174
172
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Tracing
|
5
|
+
module Contrib
|
6
|
+
# Contrib specific constants
|
7
|
+
module Ext
|
8
|
+
# @public_api
|
9
|
+
module DB
|
10
|
+
TAG_INSTANCE = 'db.instance'
|
11
|
+
TAG_USER = 'db.user'
|
12
|
+
TAG_SYSTEM = 'db.system'
|
13
|
+
TAG_STATEMENT = 'db.statement'
|
14
|
+
TAG_ROW_COUNT = 'db.row_count'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -39,8 +39,7 @@ module Datadog
|
|
39
39
|
|
40
40
|
def annotate!(span, env, options)
|
41
41
|
span.resource = resource_name(env)
|
42
|
-
service_name(env[:url].host, options)
|
43
|
-
span.service = options[:split_by_domain] ? env[:url].host : options[:service_name]
|
42
|
+
span.service = service_name(env[:url].host, options)
|
44
43
|
span.span_type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
|
45
44
|
|
46
45
|
span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
|
@@ -9,7 +9,6 @@ module Datadog
|
|
9
9
|
module Tracing
|
10
10
|
module Contrib
|
11
11
|
module Grape
|
12
|
-
# rubocop:disable Metrics/ModuleLength
|
13
12
|
# Endpoint module includes a list of subscribers to create
|
14
13
|
# traces when a Grape endpoint is hit
|
15
14
|
module Endpoint
|
@@ -245,7 +244,6 @@ module Datadog
|
|
245
244
|
end
|
246
245
|
end
|
247
246
|
end
|
248
|
-
# rubocop:enable Metrics/ModuleLength
|
249
247
|
end
|
250
248
|
end
|
251
249
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../metadata/ext'
|
4
4
|
require_relative '../analytics'
|
5
|
+
require_relative '../ext'
|
5
6
|
require_relative 'ext'
|
6
7
|
|
7
8
|
module Datadog
|
@@ -95,9 +96,9 @@ module Datadog
|
|
95
96
|
span.set_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE, service)
|
96
97
|
span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, host)
|
97
98
|
|
98
|
-
span.set_tag(
|
99
|
-
span.set_tag(
|
100
|
-
span.set_tag(
|
99
|
+
span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, db)
|
100
|
+
span.set_tag(Contrib::Ext::DB::TAG_USER, user)
|
101
|
+
span.set_tag(Contrib::Ext::DB::TAG_SYSTEM, Ext::SPAN_SYSTEM)
|
101
102
|
|
102
103
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, host)
|
103
104
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, port)
|
@@ -106,7 +107,7 @@ module Datadog
|
|
106
107
|
end
|
107
108
|
|
108
109
|
def annotate_span_with_result!(span, result)
|
109
|
-
span.set_tag(
|
110
|
+
span.set_tag(Contrib::Ext::DB::TAG_ROW_COUNT, result.ntuples)
|
110
111
|
end
|
111
112
|
|
112
113
|
def datadog_configuration
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../../../core/header_collection'
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Tracing
|
5
|
+
module Contrib
|
6
|
+
module Rack
|
7
|
+
# Classes and utilities for handling headers in Rack.
|
8
|
+
module Header
|
9
|
+
# An implementation of a header collection that looks up headers from a Rack environment.
|
10
|
+
class RequestHeaderCollection < Datadog::Core::HeaderCollection
|
11
|
+
# Creates a header collection from a rack environment.
|
12
|
+
def initialize(env)
|
13
|
+
super()
|
14
|
+
@env = env
|
15
|
+
end
|
16
|
+
|
17
|
+
# Gets the value of the header with the given name.
|
18
|
+
def get(header_name)
|
19
|
+
@env[Header.to_rack_header(header_name)]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Tests whether a header with the given name exists in the environment.
|
23
|
+
def key?(header_name)
|
24
|
+
@env.key?(Header.to_rack_header(header_name))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.to_rack_header(name)
|
29
|
+
"HTTP_#{name.to_s.upcase.gsub(/[-\s]/, '_')}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -3,12 +3,14 @@
|
|
3
3
|
require 'date'
|
4
4
|
|
5
5
|
require_relative '../../../core/environment/variable_helpers'
|
6
|
+
require_relative '../../client_ip'
|
6
7
|
require_relative '../../metadata/ext'
|
7
8
|
require_relative '../../propagation/http'
|
8
9
|
require_relative '../analytics'
|
10
|
+
require_relative '../utils/quantization/http'
|
9
11
|
require_relative 'ext'
|
12
|
+
require_relative 'header_collection'
|
10
13
|
require_relative 'request_queue'
|
11
|
-
require_relative '../utils/quantization/http'
|
12
14
|
|
13
15
|
module Datadog
|
14
16
|
module Tracing
|
@@ -121,20 +123,13 @@ module Datadog
|
|
121
123
|
# rubocop:disable Metrics/PerceivedComplexity
|
122
124
|
# rubocop:disable Metrics/MethodLength
|
123
125
|
def set_request_tags!(trace, request_span, env, status, headers, response, original_env)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
#
|
129
|
-
#
|
130
|
-
|
131
|
-
#
|
132
|
-
# REQUEST_URI is only available depending on what web server is running though.
|
133
|
-
# So when its not available, we want the original, unmutated PATH_INFO, which
|
134
|
-
# is just the relative path without query strings.
|
135
|
-
url = env['REQUEST_URI'] || original_env['PATH_INFO']
|
136
|
-
request_headers = parse_request_headers(env)
|
137
|
-
response_headers = parse_response_headers(headers || {})
|
126
|
+
request_header_collection = Header::RequestHeaderCollection.new(env)
|
127
|
+
request_headers_tags = parse_request_headers(request_header_collection)
|
128
|
+
response_headers_tags = parse_response_headers(headers || {})
|
129
|
+
|
130
|
+
# request_headers is subject to filtering and configuration so we
|
131
|
+
# get the user agent separately
|
132
|
+
user_agent = parse_user_agent_header(request_header_collection)
|
138
133
|
|
139
134
|
# The priority
|
140
135
|
# 1. User overrides span.resource
|
@@ -169,8 +164,14 @@ module Datadog
|
|
169
164
|
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_METHOD, env['REQUEST_METHOD'])
|
170
165
|
end
|
171
166
|
|
167
|
+
url = parse_url(env, original_env)
|
168
|
+
|
172
169
|
if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_URL).nil?
|
173
|
-
options = configuration[:quantize]
|
170
|
+
options = configuration[:quantize] || {}
|
171
|
+
|
172
|
+
# Quantization::HTTP.url base defaults to :show, but we are transitioning
|
173
|
+
options[:base] ||= :exclude
|
174
|
+
|
174
175
|
request_span.set_tag(
|
175
176
|
Tracing::Metadata::Ext::HTTP::TAG_URL,
|
176
177
|
Contrib::Utils::Quantization::HTTP.url(url, options)
|
@@ -178,29 +179,43 @@ module Datadog
|
|
178
179
|
end
|
179
180
|
|
180
181
|
if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_BASE_URL).nil?
|
181
|
-
|
182
|
+
options = configuration[:quantize]
|
182
183
|
|
183
|
-
|
184
|
-
|
185
|
-
else
|
186
|
-
# Compatibility for older Rack versions
|
187
|
-
request_obj.url.chomp(request_obj.fullpath)
|
188
|
-
end
|
184
|
+
unless options[:base] == :show
|
185
|
+
base_url = Contrib::Utils::Quantization::HTTP.base_url(url)
|
189
186
|
|
190
|
-
|
187
|
+
unless base_url.empty?
|
188
|
+
request_span.set_tag(
|
189
|
+
Tracing::Metadata::Ext::HTTP::TAG_BASE_URL,
|
190
|
+
base_url
|
191
|
+
)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
|
197
|
+
Tracing::ClientIp.set_client_ip_tag(
|
198
|
+
request_span,
|
199
|
+
headers: request_header_collection,
|
200
|
+
remote_ip: env['REMOTE_ADDR']
|
201
|
+
)
|
191
202
|
end
|
192
203
|
|
193
204
|
if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE).nil? && status
|
194
205
|
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, status)
|
195
206
|
end
|
196
207
|
|
208
|
+
if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_USER_AGENT).nil? && user_agent
|
209
|
+
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_USER_AGENT, user_agent)
|
210
|
+
end
|
211
|
+
|
197
212
|
# Request headers
|
198
|
-
|
213
|
+
request_headers_tags.each do |name, value|
|
199
214
|
request_span.set_tag(name, value) if request_span.get_tag(name).nil?
|
200
215
|
end
|
201
216
|
|
202
217
|
# Response headers
|
203
|
-
|
218
|
+
response_headers_tags.each do |name, value|
|
204
219
|
request_span.set_tag(name, value) if request_span.get_tag(name).nil?
|
205
220
|
end
|
206
221
|
|
@@ -219,14 +234,57 @@ module Datadog
|
|
219
234
|
Datadog.configuration.tracing[:rack]
|
220
235
|
end
|
221
236
|
|
222
|
-
def
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
237
|
+
def parse_url(env, original_env)
|
238
|
+
request_obj = ::Rack::Request.new(env)
|
239
|
+
|
240
|
+
# scheme, host, and port
|
241
|
+
base_url = if request_obj.respond_to?(:base_url)
|
242
|
+
request_obj.base_url
|
243
|
+
else
|
244
|
+
# Compatibility for older Rack versions
|
245
|
+
request_obj.url.chomp(request_obj.fullpath)
|
246
|
+
end
|
247
|
+
|
248
|
+
# https://github.com/rack/rack/blob/main/SPEC.rdoc
|
249
|
+
#
|
250
|
+
# The source of truth in Rack is the PATH_INFO key that holds the
|
251
|
+
# URL for the current request; but some frameworks may override that
|
252
|
+
# value, especially during exception handling.
|
253
|
+
#
|
254
|
+
# Because of this, we prefer to use REQUEST_URI, if available, which is the
|
255
|
+
# relative path + query string, and doesn't mutate.
|
256
|
+
#
|
257
|
+
# REQUEST_URI is only available depending on what web server is running though.
|
258
|
+
# So when its not available, we want the original, unmutated PATH_INFO, which
|
259
|
+
# is just the relative path without query strings.
|
260
|
+
#
|
261
|
+
# SCRIPT_NAME is the first part of the request URL path, so that
|
262
|
+
# the application can know its virtual location. It should be
|
263
|
+
# prepended to PATH_INFO to reflect the correct user visible path.
|
264
|
+
request_uri = env['REQUEST_URI'].to_s
|
265
|
+
fullpath = if request_uri.empty?
|
266
|
+
query_string = original_env['QUERY_STRING'].to_s
|
267
|
+
path = original_env['SCRIPT_NAME'].to_s + original_env['PATH_INFO'].to_s
|
268
|
+
|
269
|
+
query_string.empty? ? path : "#{path}?#{query_string}"
|
270
|
+
else
|
271
|
+
request_uri
|
272
|
+
end
|
273
|
+
|
274
|
+
base_url + fullpath
|
275
|
+
end
|
276
|
+
|
277
|
+
def parse_user_agent_header(headers)
|
278
|
+
headers.get(Tracing::Metadata::Ext::HTTP::HEADER_USER_AGENT)
|
279
|
+
end
|
280
|
+
|
281
|
+
def parse_request_headers(headers)
|
282
|
+
whitelist = configuration[:headers][:request] || []
|
283
|
+
whitelist.each_with_object({}) do |header, result|
|
284
|
+
header_value = headers.get(header)
|
285
|
+
unless header_value.nil?
|
286
|
+
header_tag = Tracing::Metadata::Ext::HTTP::RequestHeaders.to_tag(header)
|
287
|
+
result[header_tag] = header_value
|
230
288
|
end
|
231
289
|
end
|
232
290
|
end
|
@@ -248,10 +306,6 @@ module Datadog
|
|
248
306
|
end
|
249
307
|
end
|
250
308
|
end
|
251
|
-
|
252
|
-
def header_to_rack_header(name)
|
253
|
-
"HTTP_#{name.to_s.upcase.gsub(/[-\s]/, '_')}"
|
254
|
-
end
|
255
309
|
end
|
256
310
|
end
|
257
311
|
end
|
@@ -22,6 +22,14 @@ module Datadog
|
|
22
22
|
options[:placeholder] || PLACEHOLDER
|
23
23
|
end
|
24
24
|
|
25
|
+
def base_url(url, options = {})
|
26
|
+
URI.parse(url).tap do |uri|
|
27
|
+
uri.path = ''
|
28
|
+
uri.query = nil
|
29
|
+
uri.fragment = nil
|
30
|
+
end.to_s
|
31
|
+
end
|
32
|
+
|
25
33
|
def url!(url, options = {})
|
26
34
|
options ||= {}
|
27
35
|
|
@@ -32,8 +40,14 @@ module Datadog
|
|
32
40
|
uri.query = (!query.nil? && query.empty? ? nil : query)
|
33
41
|
end
|
34
42
|
|
35
|
-
# Remove any URI
|
43
|
+
# Remove any URI fragments
|
36
44
|
uri.fragment = nil unless options[:fragment] == :show
|
45
|
+
|
46
|
+
if options[:base] == :exclude
|
47
|
+
uri.host = nil
|
48
|
+
uri.port = nil
|
49
|
+
uri.scheme = nil
|
50
|
+
end
|
37
51
|
end.to_s
|
38
52
|
end
|
39
53
|
|
@@ -45,22 +59,26 @@ module Datadog
|
|
45
59
|
|
46
60
|
def query!(query, options = {})
|
47
61
|
options ||= {}
|
48
|
-
options[:
|
62
|
+
options[:obfuscate] = {} if options[:obfuscate] == :internal
|
63
|
+
options[:show] = options[:show] || (options[:obfuscate] ? :all : [])
|
49
64
|
options[:exclude] = options[:exclude] || []
|
50
65
|
|
51
66
|
# Short circuit if query string is meant to exclude everything
|
52
67
|
# or if the query string is meant to include everything
|
53
68
|
return '' if options[:exclude] == :all
|
54
|
-
return query if options[:show] == :all
|
55
69
|
|
56
|
-
|
57
|
-
|
58
|
-
[
|
59
|
-
|
60
|
-
|
61
|
-
|
70
|
+
unless options[:show] == :all && !(options[:obfuscate] && options[:exclude])
|
71
|
+
query = collect_query(query, uniq: true) do |key, value|
|
72
|
+
if options[:exclude].include?(key)
|
73
|
+
[nil, nil]
|
74
|
+
else
|
75
|
+
value = options[:show] == :all || options[:show].include?(key) ? value : nil
|
76
|
+
[key, value]
|
77
|
+
end
|
62
78
|
end
|
63
79
|
end
|
80
|
+
|
81
|
+
options[:obfuscate] ? obfuscate_query(query, options[:obfuscate]) : query
|
64
82
|
end
|
65
83
|
|
66
84
|
# Iterate over each key value pair, yielding to the block given.
|
@@ -91,6 +109,62 @@ module Datadog
|
|
91
109
|
end
|
92
110
|
|
93
111
|
private_class_method :collect_query
|
112
|
+
|
113
|
+
# Scans over the query string and obfuscates sensitive data by
|
114
|
+
# replacing matches with an opaque value
|
115
|
+
def obfuscate_query(query, options = {})
|
116
|
+
options[:regex] = nil if options[:regex] == :internal
|
117
|
+
re = options[:regex] || OBFUSCATOR_REGEX
|
118
|
+
with = options[:with] || OBFUSCATOR_WITH
|
119
|
+
|
120
|
+
query.gsub(re, with)
|
121
|
+
end
|
122
|
+
|
123
|
+
private_class_method :obfuscate_query
|
124
|
+
|
125
|
+
OBFUSCATOR_WITH = '<redacted>'.freeze
|
126
|
+
|
127
|
+
# rubocop:disable Layout/LineLength
|
128
|
+
OBFUSCATOR_REGEX = %r{
|
129
|
+
(?: # JSON-ish leading quote
|
130
|
+
(?:"|%22)?
|
131
|
+
)
|
132
|
+
(?: # common keys
|
133
|
+
(?:old_?|new_?)?p(?:ass)?w(?:or)?d(?:1|2)? # pw, password variants
|
134
|
+
|pass(?:_?phrase)? # pass, passphrase variants
|
135
|
+
|secret
|
136
|
+
|(?: # key, key_id variants
|
137
|
+
api_?
|
138
|
+
|private_?
|
139
|
+
|public_?
|
140
|
+
|access_?
|
141
|
+
|secret_?
|
142
|
+
)key(?:_?id)?
|
143
|
+
|token
|
144
|
+
|consumer_?(?:id|key|secret)
|
145
|
+
|sign(?:ed|ature)?
|
146
|
+
|auth(?:entication|orization)?
|
147
|
+
)
|
148
|
+
(?:
|
149
|
+
# '=' query string separator, plus value til next '&' separator
|
150
|
+
(?:\s|%20)*(?:=|%3D)[^&]+
|
151
|
+
# JSON-ish '": "somevalue"', key being handled with case above, without the opening '"'
|
152
|
+
|(?:"|%22) # closing '"' at end of key
|
153
|
+
(?:\s|%20)*(?::|%3A)(?:\s|%20)* # ':' key-value spearator, with surrounding spaces
|
154
|
+
(?:"|%22) # opening '"' at start of value
|
155
|
+
(?:%2[^2]|%[^2]|[^"%])+ # value
|
156
|
+
(?:"|%22) # closing '"' at end of value
|
157
|
+
)
|
158
|
+
|(?: # other common secret values
|
159
|
+
bearer(?:\s|%20)+[a-z0-9._\-]+
|
160
|
+
|token(?::|%3A)[a-z0-9]{13}
|
161
|
+
|gh[opsu]_[0-9a-zA-Z]{36}
|
162
|
+
|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+/=-]|%3D|%2F|%2B)+)?
|
163
|
+
|-{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY-{5}[^\-]+-{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY(?:-{5})?(?:\n|%0A)?
|
164
|
+
|(?:ssh-(?:rsa|dss)|ecdsa-[a-z0-9]+-[a-z0-9]+)(?:\s|%20)*(?:[a-z0-9/.+]|%2F|%5C|%2B){100,}(?:=|%3D)*(?:(?:\s+)[a-z0-9._-]+)?
|
165
|
+
)
|
166
|
+
}ix.freeze
|
167
|
+
# rubocop:enable Layout/LineLength
|
94
168
|
end
|
95
169
|
end
|
96
170
|
end
|
@@ -3,71 +3,93 @@
|
|
3
3
|
module Datadog
|
4
4
|
module Tracing
|
5
5
|
module Flush
|
6
|
-
# Consumes
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
# Consumes and returns a {TraceSegment} to be flushed, from
|
7
|
+
# the provided {TraceSegment}.
|
8
|
+
#
|
9
|
+
# Only finished spans are consumed. Any spans consumed are
|
10
|
+
# removed from +trace_op+ as a side effect. Unfinished spans are
|
11
|
+
# unaffected.
|
12
|
+
#
|
13
|
+
# @abstract
|
14
|
+
class Base
|
15
|
+
# Consumes and returns a {TraceSegment} to be flushed, from
|
16
|
+
# the provided {TraceSegment}.
|
10
17
|
#
|
11
|
-
#
|
18
|
+
# Only finished spans are consumed. Any spans consumed are
|
19
|
+
# removed from +trace_op+ as a side effect. Unfinished spans are
|
20
|
+
# unaffected.
|
12
21
|
#
|
22
|
+
# @param [TraceOperation] trace_op
|
13
23
|
# @return [TraceSegment] trace to be flushed, or +nil+ if the trace is not finished
|
14
24
|
def consume!(trace_op)
|
15
|
-
return unless
|
25
|
+
return unless flush?(trace_op)
|
16
26
|
|
17
27
|
get_trace(trace_op)
|
18
28
|
end
|
19
29
|
|
20
|
-
|
21
|
-
|
30
|
+
# Should we consume spans from the +trace_op+?
|
31
|
+
# @abstract
|
32
|
+
def flush?(trace_op)
|
33
|
+
raise NotImplementedError
|
22
34
|
end
|
23
35
|
|
24
36
|
protected
|
25
37
|
|
38
|
+
# Consumes all finished spans from trace.
|
39
|
+
# @return [TraceSegment]
|
26
40
|
def get_trace(trace_op)
|
27
|
-
trace_op.flush!
|
41
|
+
trace_op.flush! do |spans|
|
42
|
+
spans.select! { |span| single_sampled?(span) } unless trace_op.sampled?
|
43
|
+
|
44
|
+
spans
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Single Span Sampling has chosen to keep this span
|
49
|
+
# regardless of the trace-level sampling decision
|
50
|
+
def single_sampled?(span)
|
51
|
+
span.get_metric(Sampling::Span::Ext::TAG_MECHANISM) == Sampling::Span::Ext::MECHANISM_SPAN_SAMPLING_RATE
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Consumes and returns completed traces (where all spans have finished),
|
56
|
+
# if any, from the provided +trace_op+.
|
57
|
+
#
|
58
|
+
# Spans consumed are removed from +trace_op+ as a side effect.
|
59
|
+
class Finished < Base
|
60
|
+
# Are all spans finished?
|
61
|
+
def flush?(trace_op)
|
62
|
+
trace_op && trace_op.finished?
|
28
63
|
end
|
29
64
|
end
|
30
65
|
|
31
|
-
#
|
32
|
-
|
66
|
+
# Consumes and returns completed or partially completed
|
67
|
+
# traces from the provided +trace_op+, if any.
|
68
|
+
#
|
69
|
+
# Partial trace flushing avoids large traces residing in memory for too long.
|
70
|
+
#
|
71
|
+
# Partially completed traces, where not all spans have finished,
|
72
|
+
# will only be returned if there are at least
|
73
|
+
# +@min_spans_for_partial+ finished spans.
|
74
|
+
#
|
75
|
+
# Spans consumed are removed from +trace_op+ as a side effect.
|
76
|
+
class Partial < Base
|
33
77
|
# Start flushing partial trace after this many active spans in one trace
|
34
78
|
DEFAULT_MIN_SPANS_FOR_PARTIAL_FLUSH = 500
|
35
79
|
|
36
80
|
attr_reader :min_spans_for_partial
|
37
81
|
|
38
82
|
def initialize(options = {})
|
83
|
+
super()
|
39
84
|
@min_spans_for_partial = options.fetch(:min_spans_before_partial_flush, DEFAULT_MIN_SPANS_FOR_PARTIAL_FLUSH)
|
40
85
|
end
|
41
86
|
|
42
|
-
|
43
|
-
# traces from the provided +trace_op+, if any.
|
44
|
-
#
|
45
|
-
# Partially completed traces, where not all spans have finished,
|
46
|
-
# will only be returned if there are at least
|
47
|
-
# +@min_spans_for_partial+ finished spans.
|
48
|
-
#
|
49
|
-
# Any spans consumed are removed from +trace_op+ as a side effect.
|
50
|
-
#
|
51
|
-
# @return [TraceSegment] partial or complete trace to be flushed, or +nil+ if no spans are finished
|
52
|
-
def consume!(trace_op)
|
53
|
-
return unless partial_flush?(trace_op)
|
54
|
-
|
55
|
-
get_trace(trace_op)
|
56
|
-
end
|
57
|
-
|
58
|
-
def partial_flush?(trace_op)
|
59
|
-
return false unless trace_op.sampled?
|
87
|
+
def flush?(trace_op)
|
60
88
|
return true if trace_op.finished?
|
61
89
|
return false if trace_op.finished_span_count < @min_spans_for_partial
|
62
90
|
|
63
91
|
true
|
64
92
|
end
|
65
|
-
|
66
|
-
protected
|
67
|
-
|
68
|
-
def get_trace(trace_op)
|
69
|
-
trace_op.flush!
|
70
|
-
end
|
71
93
|
end
|
72
94
|
end
|
73
95
|
end
|
@@ -63,11 +63,14 @@ module Datadog
|
|
63
63
|
TAG_BASE_URL = 'http.base_url'
|
64
64
|
TAG_METHOD = 'http.method'
|
65
65
|
TAG_STATUS_CODE = 'http.status_code'
|
66
|
+
TAG_USER_AGENT = 'http.useragent'
|
66
67
|
TAG_URL = 'http.url'
|
67
68
|
TYPE_INBOUND = AppTypes::TYPE_WEB.freeze
|
68
69
|
TYPE_OUTBOUND = 'http'
|
69
70
|
TYPE_PROXY = 'proxy'
|
70
71
|
TYPE_TEMPLATE = 'template'
|
72
|
+
TAG_CLIENT_IP = 'http.client_ip'
|
73
|
+
HEADER_USER_AGENT = 'User-Agent'
|
71
74
|
|
72
75
|
# General header functionality
|
73
76
|
module Headers
|
@@ -153,15 +156,6 @@ module Datadog
|
|
153
156
|
TAG_QUERY = 'sql.query'
|
154
157
|
end
|
155
158
|
|
156
|
-
# @public_api
|
157
|
-
module DB
|
158
|
-
TAG_INSTANCE = 'db.instance'
|
159
|
-
TAG_USER = 'db.user'
|
160
|
-
TAG_SYSTEM = 'db.system'
|
161
|
-
TAG_STATEMENT = 'db.statement'
|
162
|
-
TAG_ROW_COUNT = 'db.row_count'
|
163
|
-
end
|
164
|
-
|
165
159
|
# @public_api
|
166
160
|
module SpanKind
|
167
161
|
TAG_SERVER = 'server'
|
@@ -65,6 +65,15 @@ module Datadog
|
|
65
65
|
tags.each { |k, v| set_tag(k, v) }
|
66
66
|
end
|
67
67
|
|
68
|
+
# Returns true if the provided `tag` was set to a non-nil value.
|
69
|
+
# False otherwise.
|
70
|
+
#
|
71
|
+
# @param [String] tag the tag or metric to check for presence
|
72
|
+
# @return [Boolean] if the tag is present and not nil
|
73
|
+
def has_tag?(tag) # rubocop:disable Naming/PredicateName
|
74
|
+
!get_tag(tag).nil? # nil is considered not present, thus we can't use `Hash#has_key?`
|
75
|
+
end
|
76
|
+
|
68
77
|
# This method removes a tag for the given key.
|
69
78
|
def clear_tag(key)
|
70
79
|
meta.delete(key)
|
@@ -39,6 +39,9 @@ module Datadog
|
|
39
39
|
def initialize(rate, max_tokens = rate)
|
40
40
|
super()
|
41
41
|
|
42
|
+
raise ArgumentError, "rate must be a number: #{rate}" unless rate.is_a?(Numeric)
|
43
|
+
raise ArgumentError, "max_tokens must be a number: #{max_tokens}" unless max_tokens.is_a?(Numeric)
|
44
|
+
|
42
45
|
@rate = rate
|
43
46
|
@max_tokens = max_tokens
|
44
47
|
|