atatus 1.7.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +49 -13
  4. data/LICENSE +1 -1
  5. data/atatus.gemspec +3 -3
  6. data/lib/atatus/agent.rb +10 -7
  7. data/lib/atatus/central_config.rb +19 -8
  8. data/lib/atatus/collector/layer.rb +1 -1
  9. data/lib/atatus/{sql_summarizer.rb → config/log_level_map.rb} +22 -28
  10. data/lib/atatus/config/options.rb +2 -1
  11. data/lib/atatus/config/regexp_list.rb +1 -1
  12. data/lib/atatus/config/round_float.rb +31 -0
  13. data/lib/atatus/config/server_info.rb +50 -0
  14. data/lib/atatus/config/wildcard_pattern_list.rb +3 -1
  15. data/lib/atatus/config.rb +92 -71
  16. data/lib/atatus/context/request/socket.rb +1 -2
  17. data/lib/atatus/context/response.rb +1 -3
  18. data/lib/atatus/context.rb +3 -10
  19. data/lib/atatus/context_builder.rb +3 -3
  20. data/lib/atatus/error.rb +2 -1
  21. data/lib/atatus/error_builder.rb +1 -1
  22. data/lib/atatus/fields.rb +98 -0
  23. data/lib/atatus/graphql.rb +2 -0
  24. data/lib/atatus/grpc.rb +5 -7
  25. data/lib/atatus/instrumenter.rb +29 -25
  26. data/lib/atatus/metadata/cloud_info.rb +156 -0
  27. data/lib/atatus/metadata/service_info.rb +3 -3
  28. data/lib/atatus/metadata/system_info/container_info.rb +20 -8
  29. data/lib/atatus/metadata/system_info.rb +20 -5
  30. data/lib/atatus/metadata.rb +3 -1
  31. data/lib/atatus/metrics/cpu_mem_set.rb +10 -38
  32. data/lib/atatus/metrics/jvm_set.rb +88 -0
  33. data/lib/atatus/metrics/metric.rb +2 -0
  34. data/lib/atatus/metrics.rb +33 -16
  35. data/lib/atatus/middleware.rb +8 -3
  36. data/lib/atatus/naively_hashable.rb +1 -0
  37. data/lib/atatus/normalizers/rails/active_record.rb +25 -7
  38. data/lib/atatus/normalizers.rb +2 -2
  39. data/lib/atatus/opentracing.rb +5 -3
  40. data/lib/atatus/rails.rb +1 -1
  41. data/lib/atatus/span/context/db.rb +1 -1
  42. data/lib/atatus/span/context/destination.rb +58 -32
  43. data/lib/atatus/span/context/http.rb +2 -0
  44. data/lib/atatus/span/context/links.rb +32 -0
  45. data/lib/atatus/{sql.rb → span/context/message.rb} +16 -12
  46. data/lib/atatus/span/context/service.rb +55 -0
  47. data/lib/atatus/span/context.rb +28 -3
  48. data/lib/atatus/span.rb +35 -5
  49. data/lib/atatus/span_helpers.rb +12 -23
  50. data/lib/atatus/spies/action_dispatch.rb +10 -13
  51. data/lib/atatus/spies/azure_storage_table.rb +148 -0
  52. data/lib/atatus/spies/delayed_job.rb +19 -13
  53. data/lib/atatus/spies/dynamo_db.rb +56 -15
  54. data/lib/atatus/spies/elasticsearch.rb +54 -39
  55. data/lib/atatus/spies/faraday.rb +92 -58
  56. data/lib/atatus/spies/http.rb +33 -37
  57. data/lib/atatus/spies/json.rb +5 -9
  58. data/lib/atatus/spies/mongo.rb +26 -19
  59. data/lib/atatus/spies/net_http.rb +53 -51
  60. data/lib/atatus/spies/racecar.rb +77 -0
  61. data/lib/atatus/spies/rake.rb +27 -27
  62. data/lib/atatus/spies/redis.rb +11 -12
  63. data/lib/atatus/spies/resque.rb +18 -23
  64. data/lib/atatus/spies/s3.rb +132 -0
  65. data/lib/atatus/spies/sequel.rb +11 -2
  66. data/lib/atatus/spies/shoryuken.rb +4 -6
  67. data/lib/atatus/spies/sidekiq.rb +23 -31
  68. data/lib/atatus/spies/sinatra.rb +20 -28
  69. data/lib/atatus/spies/sneakers.rb +2 -0
  70. data/lib/atatus/spies/sns.rb +126 -0
  71. data/lib/atatus/spies/sqs.rb +231 -0
  72. data/lib/atatus/spies/sucker_punch.rb +20 -22
  73. data/lib/atatus/spies/tilt.rb +10 -13
  74. data/lib/atatus/spies.rb +20 -0
  75. data/lib/atatus/sql/signature.rb +4 -2
  76. data/lib/atatus/sql/tokenizer.rb +23 -7
  77. data/lib/atatus/stacktrace/frame.rb +1 -0
  78. data/lib/atatus/stacktrace_builder.rb +12 -16
  79. data/lib/atatus/subscriber.rb +1 -0
  80. data/lib/atatus/trace_context/traceparent.rb +5 -8
  81. data/lib/atatus/trace_context/tracestate.rb +16 -14
  82. data/lib/atatus/trace_context.rb +6 -16
  83. data/lib/atatus/transaction.rb +17 -4
  84. data/lib/atatus/transport/base.rb +1 -3
  85. data/lib/atatus/transport/connection/http.rb +11 -3
  86. data/lib/atatus/transport/connection/proxy_pipe.rb +1 -2
  87. data/lib/atatus/transport/connection.rb +3 -2
  88. data/lib/atatus/transport/filters/hash_sanitizer.rb +16 -34
  89. data/lib/atatus/transport/filters/secrets_filter.rb +35 -12
  90. data/lib/atatus/transport/serializers/context_serializer.rb +1 -2
  91. data/lib/atatus/transport/serializers/metadata_serializer.rb +54 -8
  92. data/lib/atatus/transport/serializers/metricset_serializer.rb +2 -2
  93. data/lib/atatus/transport/serializers/span_serializer.rb +55 -9
  94. data/lib/atatus/transport/serializers/transaction_serializer.rb +1 -0
  95. data/lib/atatus/transport/serializers.rb +9 -6
  96. data/lib/atatus/transport/user_agent.rb +16 -9
  97. data/lib/atatus/transport/worker.rb +2 -1
  98. data/lib/atatus/util/deep_dup.rb +65 -0
  99. data/lib/atatus/util/precision_validator.rb +46 -0
  100. data/lib/atatus/util.rb +2 -0
  101. data/lib/atatus/version.rb +1 -1
  102. data/lib/atatus.rb +32 -5
  103. metadata +40 -11
@@ -69,7 +69,7 @@ module Atatus
69
69
  when '[' then scan_quoted_indentifier(']')
70
70
  when '(' then LPAREN
71
71
  when ')' then RPAREN
72
- when '/' then scan_bracketed_comment
72
+ when '/' then scan_bracketed_or_cql_comment
73
73
  when '-' then scan_simple_comment
74
74
  when "'" then scan_string_literal
75
75
  when ALPHA then scan_keyword_or_identifier(possible_keyword: true)
@@ -110,7 +110,7 @@ module Atatus
110
110
  next next_char
111
111
  end
112
112
 
113
- next next_char if peek =~ ALPHA
113
+ next next_char if ALPHA.match?(peek)
114
114
 
115
115
  break
116
116
  end
@@ -130,7 +130,7 @@ module Atatus
130
130
  end
131
131
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
132
132
 
133
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
133
+ # rubocop:disable Metrics/CyclomaticComplexity
134
134
  def scan_dollar_sign
135
135
  while (peek = peek_char)
136
136
  case peek
@@ -165,7 +165,7 @@ module Atatus
165
165
 
166
166
  OTHER
167
167
  end
168
- # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
168
+ # rubocop:enable Metrics/CyclomaticComplexity
169
169
 
170
170
  def scan_quoted_indentifier(delimiter)
171
171
  while (char = next_char)
@@ -185,10 +185,16 @@ module Atatus
185
185
  IDENT
186
186
  end
187
187
 
188
+ def scan_bracketed_or_cql_comment
189
+ case peek_char
190
+ when '*' then scan_bracketed_comment
191
+ when '/' then scan_cql_comment
192
+ else OTHER
193
+ end
194
+ end
195
+
188
196
  # rubocop:disable Metrics/CyclomaticComplexity
189
197
  def scan_bracketed_comment
190
- return OTHER unless peek_char == '*'
191
-
192
198
  nesting = 1
193
199
 
194
200
  while (char = next_char)
@@ -207,6 +213,16 @@ module Atatus
207
213
  end
208
214
  # rubocop:enable Metrics/CyclomaticComplexity
209
215
 
216
+ def scan_cql_comment
217
+ return OTHER unless peek_char == '/'
218
+
219
+ while (char = next_char)
220
+ break if char == "\n"
221
+ end
222
+
223
+ COMMENT
224
+ end
225
+
210
226
  def scan_simple_comment
211
227
  return OTHER unless peek_char == '-'
212
228
 
@@ -251,7 +267,7 @@ module Atatus
251
267
  when 'e', 'E'
252
268
  return NUMBER if exponent
253
269
  next_char
254
- next_char if peek_char =~ /[+-]/
270
+ next_char if /[+-]/.match?(peek_char)
255
271
  else break
256
272
  end
257
273
  end
@@ -38,6 +38,7 @@ module Atatus
38
38
  :module,
39
39
  :colno
40
40
  )
41
+
41
42
  def build_context(context_line_count)
42
43
  return unless abs_path && context_line_count > 0
43
44
 
@@ -23,7 +23,7 @@ require 'atatus/util/lru_cache'
23
23
  module Atatus
24
24
  # @api private
25
25
  class StacktraceBuilder
26
- JAVA_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
26
+ JAVA_FORMAT = /^(.+)\.([^.]+)\(([^:]+):(\d+)\)$/.freeze
27
27
  RUBY_FORMAT = /^(.+?):(\d+)(?::in `(.+?)')?$/.freeze
28
28
 
29
29
  RUBY_VERS_REGEX = %r{ruby(/gems)?[-/](\d+\.)+\d}.freeze
@@ -38,7 +38,9 @@ module Atatus
38
38
 
39
39
  def initialize(config)
40
40
  @config = config
41
- @cache = Util::LruCache.new(2048, &method(:build_frame))
41
+ @cache = Util::LruCache.new(2048) do |cache, frame|
42
+ build_frame(cache, frame)
43
+ end
42
44
  end
43
45
 
44
46
  attr_reader :config
@@ -59,7 +61,7 @@ module Atatus
59
61
 
60
62
  frame = Stacktrace::Frame.new
61
63
  frame.abs_path = abs_path
62
- frame.filename = strip_load_path(config, abs_path)
64
+ frame.filename = strip_load_path(abs_path)
63
65
  frame.function = function
64
66
  frame.lineno = lineno.to_i
65
67
  frame.library_frame = library_frame?(config, abs_path)
@@ -86,14 +88,13 @@ module Atatus
86
88
  [file, number, method, module_name]
87
89
  end
88
90
 
89
- # rubocop:disable Metrics/CyclomaticComplexity
90
91
  def library_frame?(config, abs_path)
91
92
  return false unless abs_path
92
93
 
93
94
  return true if abs_path.start_with?(GEMS_PATH)
94
95
 
95
96
  if abs_path.start_with?(config.__root_path)
96
- return true if abs_path.start_with?(config.__root_path + '/vendor')
97
+ return true if abs_path.start_with?("#{config.__root_path}/vendor")
97
98
  return false
98
99
  end
99
100
 
@@ -102,20 +103,15 @@ module Atatus
102
103
 
103
104
  false
104
105
  end
105
- # rubocop:enable Metrics/CyclomaticComplexity
106
106
 
107
- def strip_load_path(config, path)
107
+ def strip_load_path(path)
108
108
  return nil if path.nil?
109
109
 
110
- if path.start_with?(config.__root_path)
111
- prefix = config.__root_path
112
- else
113
- prefix =
114
- $LOAD_PATH
115
- .map(&:to_s)
116
- .select { |s| path.start_with?(s) }
117
- .max_by(&:length)
118
- end
110
+ prefix =
111
+ $LOAD_PATH
112
+ .map(&:to_s)
113
+ .select { |s| path.start_with?(s) }
114
+ .max_by(&:length)
119
115
 
120
116
  prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
121
117
  end
@@ -45,6 +45,7 @@ module Atatus
45
45
  # AS::Notifications API
46
46
 
47
47
  Notification = Struct.new(:id, :span)
48
+
48
49
  def start(name, id, payload)
49
50
  return unless (transaction = @agent.current_transaction)
50
51
 
@@ -22,27 +22,24 @@ module Atatus
22
22
  # @api private
23
23
  class Traceparent
24
24
  VERSION = '00'
25
- HEX_REGEX = /[^[:xdigit:]]/.freeze
25
+ NON_HEX_REGEX = /[^[:xdigit:]]/.freeze
26
26
 
27
27
  TRACE_ID_LENGTH = 16
28
28
  ID_LENGTH = 8
29
29
 
30
- # rubocop:disable Metrics/ParameterLists
31
30
  def initialize(
32
31
  version: VERSION,
33
32
  trace_id: nil,
34
- span_id: nil,
33
+ parent_id: nil,
35
34
  id: nil,
36
35
  recorded: true
37
36
  )
38
37
  @version = version
39
38
  @trace_id = trace_id || hex(TRACE_ID_LENGTH)
40
- # TODO: rename span_id kw arg to parent_id with next major version bump
41
- @parent_id = span_id
39
+ @parent_id = parent_id
42
40
  @id = id || hex(ID_LENGTH)
43
41
  @recorded = recorded
44
42
  end
45
- # rubocop:enable Metrics/ParameterLists
46
43
 
47
44
  attr_accessor :version, :id, :trace_id, :parent_id, :recorded
48
45
 
@@ -58,8 +55,8 @@ module Atatus
58
55
  values[-1] = Util.hex_to_bits(values[-1])
59
56
  end
60
57
 
61
- raise_invalid(header) if HEX_REGEX =~ t.trace_id
62
- raise_invalid(header) if HEX_REGEX =~ t.parent_id
58
+ raise_invalid(header) if NON_HEX_REGEX.match?(t.trace_id)
59
+ raise_invalid(header) if NON_HEX_REGEX.match?(t.parent_id)
63
60
  end
64
61
  end
65
62
 
@@ -17,6 +17,8 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
+ require 'atatus/util/precision_validator'
21
+
20
22
  module Atatus
21
23
  class TraceContext
22
24
  # @api private
@@ -35,12 +37,13 @@ module Atatus
35
37
  end
36
38
  end
37
39
 
40
+ # @api private
38
41
  class EsEntry
39
42
  ASSIGN = ':'
40
43
  SPLIT = ';'
41
44
 
42
- SHORT_TO_LONG = { 's' => 'sample_rate' }
43
- LONG_TO_SHORT = { 'sample_rate' => 's' }
45
+ SHORT_TO_LONG = { 's' => 'sample_rate' }.freeze
46
+ LONG_TO_SHORT = { 'sample_rate' => 's' }.freeze
44
47
 
45
48
  def initialize(values = nil)
46
49
  parse(values)
@@ -63,13 +66,9 @@ module Atatus
63
66
  end
64
67
 
65
68
  def sample_rate=(val)
66
- float = Float(val).round(3)
67
-
68
- return nil unless (0.0..1.0).include?(float)
69
-
70
- @sample_rate = float
71
- rescue ArgumentError => e
72
- nil
69
+ @sample_rate = Util::PrecisionValidator.validate(
70
+ val, precision: 4, minimum: 0.0001
71
+ )
73
72
  end
74
73
 
75
74
  def to_s
@@ -85,7 +84,7 @@ module Atatus
85
84
 
86
85
  values.split(SPLIT).map do |kv|
87
86
  k, v = kv.split(ASSIGN)
88
- next unless SHORT_TO_LONG.keys.include?(k)
87
+ next unless SHORT_TO_LONG.key?(k)
89
88
  send("#{SHORT_TO_LONG[k]}=", v)
90
89
  end
91
90
  end
@@ -93,6 +92,8 @@ module Atatus
93
92
 
94
93
  extend Forwardable
95
94
 
95
+ ENTRY_SPLIT_REGEX = /\s*[\n,]+\s*/
96
+
96
97
  def initialize(entries: {}, sample_rate: nil)
97
98
  @entries = entries
98
99
 
@@ -108,7 +109,7 @@ module Atatus
108
109
  split_by_nl_and_comma(header)
109
110
  .each_with_object({}) do |entry, hsh|
110
111
  k, v = entry.split('=')
111
-
112
+ next unless k && v && !k.empty? && !v.empty?
112
113
  hsh[k] =
113
114
  case k
114
115
  when 'es' then EsEntry.new(v)
@@ -138,9 +139,10 @@ module Atatus
138
139
  def split_by_nl_and_comma(str)
139
140
  # HTTP allows multiple headers with the same name, eg. multiple
140
141
  # Set-Cookie headers per response.
141
- # Rack handles this by joining the headers under the same key, separated
142
- # by newlines, see https://www.rubydoc.info/github/rack/rack/file/SPEC
143
- String(str).split("\n").map { |s| s.split(',') }.flatten
142
+ # Rack handles this by joining the headers under the same key,
143
+ # separated by newlines.
144
+ # See https://www.rubydoc.info/github/rack/rack/file/SPEC
145
+ String(str).split(ENTRY_SPLIT_REGEX).flatten
144
146
  end
145
147
  end
146
148
  end
@@ -29,10 +29,9 @@ module Atatus
29
29
 
30
30
  def initialize(
31
31
  traceparent: nil,
32
- tracestate: nil,
33
- **legacy_traceparent_attrs
32
+ tracestate: nil
34
33
  )
35
- @traceparent = traceparent || Traceparent.new(**legacy_traceparent_attrs)
34
+ @traceparent = traceparent || Traceparent.new
36
35
  @tracestate = tracestate || Tracestate.new
37
36
  end
38
37
 
@@ -42,22 +41,18 @@ module Atatus
42
41
  :version, :trace_id, :id, :parent_id, :ensure_parent_id, :recorded?
43
42
 
44
43
  class << self
45
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
46
- def parse(legacy_header = nil, env: nil, metadata: nil)
47
- unless legacy_header || env || metadata
44
+ def parse(env: nil, metadata: nil)
45
+ unless env || metadata
48
46
  raise ArgumentError, 'TraceContext expects env:, metadata: ' \
49
47
  'or single argument header string'
50
48
  end
51
49
 
52
- if legacy_header
53
- legacy_parse_from_header(legacy_header)
54
- elsif env
50
+ if env
55
51
  trace_context_from_env(env)
56
52
  elsif metadata
57
53
  trace_context_from_metadata(metadata)
58
54
  end
59
55
  end
60
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
61
56
 
62
57
  private
63
58
 
@@ -90,11 +85,6 @@ module Atatus
90
85
 
91
86
  new(traceparent: parent, tracestate: state)
92
87
  end
93
-
94
- def legacy_parse_from_header(header)
95
- parent = Traceparent.parse(header)
96
- new(traceparent: parent)
97
- end
98
88
  end
99
89
 
100
90
  def child
@@ -106,7 +96,7 @@ module Atatus
106
96
  def apply_headers
107
97
  yield 'Traceparent', traceparent.to_header
108
98
 
109
- if tracestate
99
+ if tracestate && !tracestate.to_header.empty?
110
100
  yield 'Tracestate', tracestate.to_header
111
101
  end
112
102
 
@@ -20,6 +20,17 @@
20
20
  module Atatus
21
21
  # @api private
22
22
  class Transaction
23
+ # @api private
24
+ class Outcome
25
+ FAILURE = "failure"
26
+ SUCCESS = "success"
27
+ UNKNOWN = "unknown"
28
+
29
+ def self.from_http_status(code)
30
+ code.to_i >= 500 ? FAILURE : SUCCESS
31
+ end
32
+ end
33
+
23
34
  extend Forwardable
24
35
  include ChildDurations::Methods
25
36
 
@@ -33,10 +44,10 @@ module Atatus
33
44
  def initialize(
34
45
  name = nil,
35
46
  type = nil,
47
+ config:,
36
48
  sampled: true,
37
49
  sample_rate: 1,
38
50
  context: nil,
39
- config:,
40
51
  trace_context: nil
41
52
  )
42
53
  @name = name
@@ -63,7 +74,9 @@ module Atatus
63
74
  unless (@trace_context = trace_context)
64
75
  @trace_context = TraceContext.new(
65
76
  traceparent: TraceContext::Traceparent.new(recorded: sampled),
66
- tracestate: TraceContext::Tracestate.new(sample_rate: sampled ? sample_rate : 0)
77
+ tracestate: TraceContext::Tracestate.new(
78
+ sample_rate: sampled ? sample_rate : 0
79
+ )
67
80
  )
68
81
  end
69
82
 
@@ -74,7 +87,7 @@ module Atatus
74
87
  end
75
88
  # rubocop:enable Metrics/ParameterLists
76
89
 
77
- attr_accessor :name, :type, :result, :spans, :ruby_time
90
+ attr_accessor :name, :type, :result, :outcome, :spans, :ruby_time
78
91
 
79
92
  attr_reader(
80
93
  :breakdown_metrics,
@@ -90,7 +103,7 @@ module Atatus
90
103
  :started_spans,
91
104
  :timestamp,
92
105
  :trace_context,
93
- :transaction_max_spans
106
+ :transaction_max_spans
94
107
  )
95
108
 
96
109
  alias :collect_metrics? :collect_metrics
@@ -35,7 +35,6 @@ module Atatus
35
35
  include Logging
36
36
 
37
37
  WATCHER_EXECUTION_INTERVAL = 5
38
- WATCHER_TIMEOUT_INTERVAL = 4
39
38
  WORKER_JOIN_TIMEOUT = 5
40
39
 
41
40
  def initialize(config)
@@ -112,8 +111,7 @@ module Atatus
112
111
 
113
112
  def create_watcher
114
113
  @watcher = Concurrent::TimerTask.execute(
115
- execution_interval: WATCHER_EXECUTION_INTERVAL,
116
- timeout_interval: WATCHER_TIMEOUT_INTERVAL
114
+ execution_interval: WATCHER_EXECUTION_INTERVAL
117
115
  ) { ensure_worker_count }
118
116
  end
119
117
 
@@ -74,8 +74,16 @@ module Atatus
74
74
  debug '%s: Closing request with reason %s', thread_str, reason
75
75
  @closed.make_true
76
76
 
77
- @wr&.close(reason)
78
- return if @request.nil? || @request&.join(5)
77
+ @wr&.close
78
+
79
+ if @request&.join(5)
80
+ @rd&.close
81
+ return
82
+ end
83
+
84
+ @rd&.close
85
+
86
+ return if @request.nil?
79
87
 
80
88
  error(
81
89
  '%s: APM Server not responding in time, terminating request',
@@ -85,7 +93,7 @@ module Atatus
85
93
  end
86
94
 
87
95
  def closed?
88
- @closed.true?
96
+ @rd.closed? && @closed.true?
89
97
  end
90
98
 
91
99
  def inspect
@@ -62,8 +62,7 @@ module Atatus
62
62
  @io = Zlib::GzipWriter.new(io)
63
63
  end
64
64
 
65
- def close(reason = nil)
66
- debug("Closing writer with reason #{reason}")
65
+ def close
67
66
  io.close
68
67
  end
69
68
 
@@ -42,11 +42,12 @@ module Atatus
42
42
  Metadata.new(config)
43
43
  )
44
44
  )
45
- @url = config.server_url + '/intake/v2/events'
45
+ @url = "#{config.server_url}/intake/v2/events"
46
46
  @mutex = Mutex.new
47
47
  end
48
48
 
49
49
  attr_reader :http
50
+
50
51
  def write(str)
51
52
  return false if @config.disable_send
52
53
 
@@ -104,7 +105,7 @@ module Atatus
104
105
  @close_task&.cancel
105
106
  @close_task =
106
107
  Concurrent::ScheduledTask.execute(@config.api_request_time) do
107
- flush(:timeout)
108
+ flush(:scheduled_flush)
108
109
  end
109
110
  end
110
111
  end
@@ -17,59 +17,41 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
+ require 'atatus/util/deep_dup'
21
+
20
22
  module Atatus
21
23
  module Transport
22
24
  module Filters
25
+ # @api private
23
26
  class HashSanitizer
24
27
  FILTERED = '[FILTERED]'
25
28
 
26
- KEY_FILTERS = [
27
- /passw(or)?d/i,
28
- /auth/i,
29
- /^pw$/,
30
- /secret/i,
31
- /token/i,
32
- /api[-._]?key/i,
33
- /session[-._]?id/i,
34
- /(set[-_])?cookie/i
35
- ].freeze
36
-
37
- VALUE_FILTERS = [
38
- # (probably) credit card number
39
- /^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/
40
- ].freeze
29
+ def initialize(key_patterns:)
30
+ @key_patterns = key_patterns
31
+ end
41
32
 
42
- attr_accessor :key_filters
33
+ attr_accessor :key_patterns
43
34
 
44
- def initialize
45
- @key_filters = KEY_FILTERS
35
+ def strip_from(obj)
36
+ strip_from!(Util::DeepDup.dup(obj))
46
37
  end
47
38
 
48
- def strip_from!(obj, key_filters = KEY_FILTERS)
49
- return unless obj&.is_a?(Hash)
50
-
51
- obj.each do |k, v|
52
- if filter_key?(k)
53
- next obj[k] = FILTERED
54
- end
39
+ def strip_from!(obj)
40
+ return unless obj.is_a?(Hash)
55
41
 
42
+ obj.each_pair do |k, v|
56
43
  case v
57
44
  when Hash
58
45
  strip_from!(v)
59
- when String
60
- if filter_value?(v)
61
- obj[k] = FILTERED
62
- end
46
+ else
47
+ next unless filter_key?(k)
48
+ obj[k] = FILTERED
63
49
  end
64
50
  end
65
51
  end
66
52
 
67
53
  def filter_key?(key)
68
- @key_filters.any? { |regex| regex.match(key) }
69
- end
70
-
71
- def filter_value?(value)
72
- VALUE_FILTERS.any? { |regex| regex.match(value) }
54
+ @key_patterns.any? { |regex| regex.match(key) }
73
55
  end
74
56
  end
75
57
  end
@@ -26,21 +26,44 @@ module Atatus
26
26
  class SecretsFilter
27
27
  def initialize(config)
28
28
  @config = config
29
- @sanitizer = HashSanitizer.new
30
- @sanitizer.key_filters += config.custom_key_filters +
31
- config.sanitize_field_names
29
+ @sanitizer =
30
+ HashSanitizer.new(
31
+ key_patterns: config.custom_key_filters +
32
+ config.sanitize_field_names
33
+ )
32
34
  end
33
35
 
34
36
  def call(payload)
35
- @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :headers)
36
- @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :env)
37
- @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :cookies)
38
- @sanitizer.strip_from! payload.dig(:transaction, :context, :response, :headers)
39
- @sanitizer.strip_from! payload.dig(:error, :context, :request, :headers)
40
- @sanitizer.strip_from! payload.dig(:error, :context, :request, :cookies)
41
- @sanitizer.strip_from! payload.dig(:error, :context, :response, :headers)
42
- @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :body)
43
-
37
+ @sanitizer.strip_from!(
38
+ payload.dig(:transaction, :context, :request, :body)
39
+ )
40
+ @sanitizer.strip_from!(
41
+ payload.dig(:transaction, :context, :request, :cookies)
42
+ )
43
+ @sanitizer.strip_from!(
44
+ payload.dig(:transaction, :context, :request, :env)
45
+ )
46
+ @sanitizer.strip_from!(
47
+ payload.dig(:transaction, :context, :request, :headers)
48
+ )
49
+ @sanitizer.strip_from!(
50
+ payload.dig(:transaction, :context, :response, :headers)
51
+ )
52
+ @sanitizer.strip_from!(
53
+ payload.dig(:error, :context, :request, :body)
54
+ )
55
+ @sanitizer.strip_from!(
56
+ payload.dig(:error, :context, :request, :cookies)
57
+ )
58
+ @sanitizer.strip_from!(
59
+ payload.dig(:error, :context, :request, :env)
60
+ )
61
+ @sanitizer.strip_from!(
62
+ payload.dig(:error, :context, :request, :headers)
63
+ )
64
+ @sanitizer.strip_from!(
65
+ payload.dig(:error, :context, :response, :headers)
66
+ )
44
67
  payload
45
68
  end
46
69
  end
@@ -77,8 +77,7 @@ module Atatus
77
77
  return unless socket
78
78
 
79
79
  {
80
- remote_addr: socket.remote_addr,
81
- encrypted: socket.encrypted
80
+ remote_addr: socket.remote_addr
82
81
  }
83
82
  end
84
83