supergood 0.1.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a20e9c78ef66594eaed117db23b1581b3531497aaf3a087ad92466f76a8e07a8
4
- data.tar.gz: 22e62c82c3cea5bfba10a8d5199ebf1a385bab78861c6f20efcd55921e65eee0
3
+ metadata.gz: 5ee319f07b495599aa2deafcf5b6c995402e55b4d7a58ddb82d55379aa6ba99a
4
+ data.tar.gz: 15ab686e3bec0c37771e8fa2892f7cdb69312595cc8726c0d690855681eeb26d
5
5
  SHA512:
6
- metadata.gz: da801337729a2975cd42231da0de2e773aafdcc0a391a69111b4acb55dfe1d8126e1017e72481688dcf410d23a072c51204e9885e8938d9903ed1f947de94bfc
7
- data.tar.gz: b9848d4363bcb7b04bb19b46dc61f8adcb8bbf9b911664a3ba367721f171e2ad950c3fdcb3d236192fe5c160e4d33aa926615583647c7b3e44b0038fc4ed6c27
6
+ metadata.gz: 11eed3208aeec8618d71cb7a832988ef0e88cfb1d55fed315b203418cb93ab4bfba251b22ef978afd0ec672b4b849d2af28ad03435d20003db1020e154faa74c
7
+ data.tar.gz: 583dacf60c012289be925e8c49471a14d401be64a00ef0cf299e758797bd318dadb0bb3d3a64cb53ef925ba0620fe253213d6406e1ffc35e094c0c5b5e69a239
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "editor.codeActionsOnSave": {
3
- "source.fixAll.eslint": true
3
+ "source.fixAll.eslint": "explicit"
4
4
  },
5
5
  "editor.tabSize": 2,
6
6
  }
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- supergood (0.1.3)
4
+ supergood (1.0.0)
5
5
  rudash (~> 4.0, >= 4.0.2)
6
6
 
7
7
  GEM
data/lib/supergood/api.rb CHANGED
@@ -8,7 +8,9 @@ module Supergood
8
8
  @base_url = base_url
9
9
  @header_options = {
10
10
  'Content-Type' => 'application/json',
11
- 'Authorization' => 'Basic ' + Base64.encode64(client_id + ':' + client_secret).gsub(/\n/, '')
11
+ 'Authorization' => "Basic #{Base64.encode64("#{client_id}:#{client_secret}").gsub(/\n/, '')}",
12
+ 'supergood-api' => 'supergood-rb',
13
+ 'supergood-api-version' => VERSION
12
14
  }
13
15
  @local_only = client_id == LOCAL_CLIENT_ID && client_secret == LOCAL_CLIENT_SECRET
14
16
  end
@@ -29,11 +31,12 @@ module Supergood
29
31
  if @local_only
30
32
  @log.debug(payload)
31
33
  else
32
- uri = URI(@base_url + '/events')
34
+ uri = URI("#{@base_url}/events")
33
35
  response = Net::HTTP.post(uri, payload.to_json, @header_options)
34
- if response.code == '200'
35
- return JSON.parse(response.body, symbolize_names: true)
36
- elsif response.code == '401'
36
+
37
+ return JSON.parse(response.body) if response.code == '200'
38
+
39
+ if response.code == '401'
37
40
  raise SupergoodException.new ERRORS[:UNAUTHORIZED]
38
41
  elsif response.code != '200' && response.code != '201'
39
42
  raise SupergoodException.new ERRORS[:POSTING_EVENTS]
@@ -45,14 +48,20 @@ module Supergood
45
48
  if @local_only
46
49
  @log.debug(payload)
47
50
  else
48
- uri = URI(@base_url + '/errors')
51
+ uri = URI("#{@base_url}/errors")
49
52
  response = Net::HTTP.post(uri, payload.to_json, @header_options)
50
- if response.code == '200'
51
- return JSON.parse(response.body, symbolize_names: true)
52
- else
53
- @log.warn(ERRORS[:POSTING_ERRORS])
54
- end
53
+ return JSON.parse(response.body, symbolize_names: true) if response.code == '200'
54
+
55
+ @log.warn(ERRORS[:POSTING_ERRORS])
55
56
  end
56
57
  end
58
+
59
+ def get_remote_config
60
+ uri = URI(@base_url + '/config')
61
+ response = Net::HTTP.get_response(uri, @header_options)
62
+ return JSON.parse(response.body) if response.code == '200'
63
+
64
+ raise SupergoodException.new ERRORS[:CONFIG_FETCH_ERROR]
65
+ end
57
66
  end
58
67
  end
@@ -31,7 +31,6 @@ module Supergood
31
31
 
32
32
  @allowed_domains = @config[:allowedDomains]
33
33
  @ignored_domains = @config[:ignoredDomains]
34
- @keys_to_hash = @config[:keysToHash]
35
34
  @logger = Supergood::Logger.new(@api, @config, @api.header_options)
36
35
 
37
36
  @api.set_logger(@logger)
@@ -40,13 +39,15 @@ module Supergood
40
39
  @response_cache = {}
41
40
 
42
41
  @interval_thread = set_interval(@config[:flushInterval]) { flush_cache }
42
+ @remote_config_thread = set_interval(@config[:remoteConfigFetchInterval]) { fetch_and_process_remote_config }
43
43
 
44
44
  @http_clients = [
45
45
  Supergood::Vendor::NetHTTP,
46
46
  Supergood::Vendor::HTTPrb
47
47
  ]
48
48
 
49
- patch_all()
49
+ fetch_and_process_remote_config
50
+ patch_all
50
51
  self
51
52
  end
52
53
 
@@ -58,6 +59,15 @@ module Supergood
58
59
  @api
59
60
  end
60
61
 
62
+ def fetch_and_process_remote_config
63
+ begin
64
+ remote_config = @api.get_remote_config
65
+ @config = @config.merge({ :remote_config => Supergood::Utils.process_remote_config(remote_config) })
66
+ rescue => e
67
+ log.error({}, e, ERRORS[:CONFIG_FETCH_ERROR])
68
+ end
69
+ end
70
+
61
71
  def flush_cache(force = false)
62
72
  # If there's notthing in the response cache, and we're not forcing a flush, then return
63
73
 
@@ -67,11 +77,8 @@ module Supergood
67
77
  return
68
78
  end
69
79
 
70
- data = @response_cache.values
71
-
72
- if force
73
- data += @request_cache.values
74
- end
80
+ data = Supergood::Utils.prepare_data(@response_cache.values, @config[:remote_config], @config[:forceRedactAll])
81
+ data += Supergood::Utils.prepare_data(@request_cache.values, @config[:remote_config], @config[:forceRedactAll]) if force
75
82
 
76
83
  begin
77
84
  api.post_events(data)
@@ -86,6 +93,7 @@ module Supergood
86
93
 
87
94
  def cleanup()
88
95
  @interval_thread.kill
96
+ @remote_config_thread.kill
89
97
  unpatch_all()
90
98
  end
91
99
 
@@ -117,16 +125,25 @@ module Supergood
117
125
  end
118
126
 
119
127
  def intercept(request)
128
+ remote_config = @config[:remote_config]
129
+
130
+ if remote_config.nil?
131
+ response = yield
132
+ return response[:original_response]
133
+ end
134
+
120
135
  request_id = SecureRandom.uuid
121
136
  requested_at = Time.now
122
- if !ignored?(request[:domain])
123
- puts "Caching Request"
137
+
138
+ endpoint_config = Supergood::Utils.get_endpoint_config(request.transform_keys(&:to_s), remote_config)
139
+ ignore_endpoint = endpoint_config ? endpoint_config['ignored'] : false
140
+
141
+ if !ignore_endpoint && !ignored?(request[:domain])
124
142
  cache_request(request_id, requested_at, request)
125
143
  end
126
144
 
127
145
  response = yield
128
- if !ignored?(request[:domain]) && defined?(response)
129
- puts "Caching Response"
146
+ if !ignore_endpoint && !ignored?(request[:domain]) && defined?(response)
130
147
  cache_response(request_id, requested_at, response)
131
148
  end
132
149
 
@@ -134,41 +151,47 @@ module Supergood
134
151
  end
135
152
 
136
153
  def cache_request(request_id, requested_at, request)
154
+ if !@config[:remote_config]
155
+ return
156
+ end
157
+
137
158
  begin
138
159
  request_payload = {
139
- id: request_id,
140
- headers: request[:headers],
141
- method: request[:method],
142
- url: request[:url],
143
- path: request[:path],
144
- search: request[:search] || '',
145
- body: Supergood::Utils.safe_parse_json(request[:body]),
146
- requestedAt: requested_at
160
+ 'id' => request_id,
161
+ 'headers' => Supergood::Utils.safe_parse_json(request[:headers]),
162
+ 'method' => request[:method],
163
+ 'url' => request[:url],
164
+ 'path' => request[:path],
165
+ 'search' => request[:search] || '',
166
+ 'body' => Supergood::Utils.safe_parse_json(request[:body]),
167
+ 'requestedAt' => requested_at
147
168
  }
148
169
  @request_cache[request_id] = {
149
- request: request_payload
170
+ 'request' => request_payload
150
171
  }
151
172
  rescue => e
152
- log.error({ request: request }, e, ERRORS[:CACHING_REQUEST])
173
+ log.error({ 'request' => request }, e, ERRORS[:CACHING_REQUEST])
153
174
  end
154
175
  end
155
176
 
156
177
  def cache_response(request_id, requested_at, response)
178
+ if !@config[:remote_config]
179
+ return
180
+ end
181
+
157
182
  begin
158
183
  responded_at = Time.now
159
184
  duration = (responded_at - requested_at) * 1000
160
185
  request_payload = @request_cache[request_id]
161
186
  response_payload = {
162
- headers: response[:headers],
163
- status: response[:status],
164
- statusText: response[:statusText],
165
- body: Supergood::Utils.safe_parse_json(response[:body]),
166
- respondedAt: responded_at,
167
- duration: duration.round,
187
+ 'headers' => Supergood::Utils.safe_parse_json(response[:headers]),
188
+ 'status' => response[:status],
189
+ 'statusText' => response[:statusText],
190
+ 'body' => Supergood::Utils.safe_parse_json(response[:body]),
191
+ 'respondedAt' => responded_at,
192
+ 'duration' => duration.round
168
193
  }
169
- @response_cache[request_id] = Supergood::Utils.hash_values_from_keys(request_payload.merge({
170
- response: response_payload
171
- }), @keys_to_hash)
194
+ @response_cache[request_id] = request_payload.merge({ 'response' => response_payload })
172
195
  @request_cache.delete(request_id)
173
196
  rescue => e
174
197
  log.error(
@@ -179,7 +202,7 @@ module Supergood
179
202
  end
180
203
 
181
204
  def ignored?(domain)
182
- base_domain = URI.parse(@base_url).hostname
205
+ base_domain = Supergood::Utils.get_host_without_www(@base_url)
183
206
  if domain == base_domain
184
207
  return true
185
208
  elsif @allowed_domains.any?
@@ -5,7 +5,8 @@ ERRORS = {
5
5
  POSTING_EVENTS: 'Error Posting Events',
6
6
  POSTING_ERRORS: 'Error Posting Errors',
7
7
  WRITING_TO_DISK: 'Error writing to disk',
8
- TEST_ERROR: 'Test Error for Testing Purpos es',
8
+ TEST_ERROR: 'Test Error for Testing Purposes',
9
+ CONFIG_FETCH_ERROR: 'Error Fetching Remote Config',
9
10
  UNAUTHORIZED: 'Unauthorized: Invalid Client ID or Secret. Exiting.',
10
11
  NO_CLIENT_ID:
11
12
  'No Client ID Provided, set SUPERGOOD_CLIENT_ID or pass it as an argument',
@@ -16,13 +17,14 @@ ERRORS = {
16
17
  LOCAL_CLIENT_ID = 'local-client-id';
17
18
  LOCAL_CLIENT_SECRET = 'local-client-secret';
18
19
 
19
- DEFAULT_SUPERGOOD_BYTE_LIMIT = 500000
20
+ DEFAULT_SUPERGOOD_BYTE_LIMIT = 500_000
20
21
 
21
22
  DEFAULT_CONFIG = {
22
- keysToHash: [],
23
23
  flushInterval: 1000,
24
+ remoteConfigFetchInterval: 10_000,
24
25
  ignoredDomains: [],
25
26
  allowedDomains: [],
27
+ forceRedactAll: true
26
28
  }
27
29
 
28
30
  # GZIP_START_BYTES = b'\x1f\x8b'
@@ -13,7 +13,9 @@ module Supergood
13
13
  end
14
14
 
15
15
  def error(data, error, msg)
16
- super(error)
16
+ if(ENV['SUPERGOOD_LOG_LEVEL'] == 'debug')
17
+ super(error)
18
+ end
17
19
  @api.post_errors(
18
20
  {
19
21
  error: error.backtrace.join('\n'),
@@ -1,62 +1,28 @@
1
1
  require 'rudash'
2
2
  require 'digest'
3
+ require 'uri'
4
+ require 'json'
3
5
 
4
6
  module Supergood
5
7
  module Utils
6
- def self.hash_value(input)
7
- hash = Digest::SHA1.new
8
- if input == nil
9
- return ''
10
- elsif input.class == Array
11
- return [Base64.strict_encode64(hash.update(input.to_json).to_s)]
12
- elsif input.class == Hash
13
- return {'hashed': Base64.strict_encode64(hash.update(input.to_json).to_s)}
14
- elsif input.class == String
15
- return Base64.strict_encode64(hash.update(input).to_s)
16
- end
17
- end
18
-
19
- # Hash values from specified keys, or hash if the bodies exceed a byte limit
20
- def self.hash_values_from_keys(obj, keys_to_hash, byte_limit=DEFAULT_SUPERGOOD_BYTE_LIMIT)
21
- _obj = obj
22
-
23
- if !keys_to_hash.include?('response.body')
24
- payload = R_.get(_obj, 'response.body')
25
- payload_size = payload.to_s.length()
26
- if(payload_size >= byte_limit)
27
- R_.set(_obj, 'response.body', Supergood::Utils.hash_value(payload))
28
- end
29
- end
30
-
31
- if !keys_to_hash.include?('request.body')
32
- payload = R_.get(_obj, 'request.body')
33
- payload_size = payload.to_s.length()
34
- if(payload_size >= byte_limit)
35
- R_.set(_obj, 'request.body', Supergood::Utils.hash_value(payload))
36
- end
37
- end
38
-
39
- keys_to_hash.each { |key|
40
- value = R_.get(_obj, key)
41
- if !!value
42
- R_.set(_obj, key, Supergood::Utils.hash_value(value))
43
- end
44
- }
45
8
 
46
- return _obj
9
+ def self.get_host_without_www(url)
10
+ uri = URI.parse(url)
11
+ uri = URI.parse("http://#{url}") if uri.scheme.nil?
12
+ host = uri.host.downcase
13
+ host.start_with?('www.') ? host[4..] : host
47
14
  end
48
15
 
49
16
  def self.safe_parse_json(input)
50
- if !input || input == ''
51
- return ''
52
- end
17
+ return '' if !input || input == ''
53
18
 
54
19
  begin
55
- return JSON.parse(input)
20
+ JSON.parse(input)
56
21
  rescue => e
57
22
  input
58
23
  end
59
24
  end
25
+
60
26
  def self.get_header(request_or_response)
61
27
  header = {}
62
28
  request_or_response.each_header do |k,v|
@@ -66,11 +32,250 @@ module Supergood
66
32
  end
67
33
 
68
34
  def self.request_url(http, request)
69
- URI::DEFAULT_PARSER.unescape("http#{"s" if http.use_ssl?}://#{http.address}#{request.path}")
35
+ URI::DEFAULT_PARSER.unescape("http#{'s' if http.use_ssl?}://#{http.address}#{request.path}")
70
36
  end
71
37
 
72
38
  def self.make_config(config)
73
- return DEFAULT_CONFIG.merge(config)
39
+ DEFAULT_CONFIG.merge(config)
40
+ end
41
+
42
+ def self.process_remote_config(remote_config_payload)
43
+ remote_config_payload ||= []
44
+ remote_config_payload.reduce({}) do |remote_config, domain_config|
45
+ domain = domain_config['domain']
46
+ endpoints = domain_config['endpoints']
47
+ endpoint_config = endpoints.reduce({}) do |config, endpoint|
48
+ matching_regex = endpoint['matchingRegex']
49
+ regex = matching_regex['regex']
50
+ location = matching_regex['location']
51
+
52
+ endpoint_configuration = endpoint['endpointConfiguration']
53
+ action = endpoint_configuration['action']
54
+ sensitive_keys = endpoint_configuration['sensitiveKeys'] || []
55
+ sensitive_keys = sensitive_keys.map { |key| key['keyPath'] }
56
+
57
+ config[regex] = {
58
+ 'location' => location,
59
+ 'regex' => regex,
60
+ 'ignored' => action == 'Ignore',
61
+ 'sensitive_keys' => sensitive_keys
62
+ }
63
+
64
+ config
65
+ end
66
+
67
+ remote_config[domain] = endpoint_config
68
+ remote_config
69
+ end
70
+ end
71
+
72
+ def self.get_str_representation_from_path(request, location)
73
+ url = URI(request['url'])
74
+
75
+ case location
76
+ when 'domain'
77
+ get_host_without_www(url)
78
+ when 'url'
79
+ url.to_s
80
+ when 'path'
81
+ url.path
82
+ when 'requestHeaders'
83
+ request['headers'].to_s
84
+ when 'requestBody'
85
+ request['body'].to_s
86
+ else
87
+ request[location.to_sym].to_s if request.key?(location.to_sym)
88
+ end
89
+ end
90
+
91
+ def self.get_endpoint_config(request, remote_config)
92
+ domain = remote_config.keys.find { |d| get_host_without_www(request['url']).include?(d) }
93
+ return nil unless domain
94
+
95
+ endpoint_configs = remote_config[domain]
96
+ endpoint_configs.each_value do |endpoint_config|
97
+ regex = endpoint_config['regex']
98
+ location = endpoint_config['location']
99
+ regex_obj = Regexp.new(regex)
100
+ str_representation = get_str_representation_from_path(request, location)
101
+ next unless str_representation
102
+ return endpoint_config if regex_obj.match?(str_representation)
103
+ end
104
+ nil
105
+ end
106
+
107
+ def self.expand(parts, obj, key_path)
108
+ path = key_path
109
+ return [path] if parts.empty?
110
+
111
+ part = parts.first
112
+ is_property = !part.start_with?('[')
113
+ separator = !path.empty? && is_property ? '.' : ''
114
+
115
+ # Check for array notations
116
+ if part.match?(/\[\*?\]/)
117
+ return [] unless obj.is_a?(Array)
118
+
119
+ # Expand for each element in the array
120
+ obj.flat_map.with_index do |_, index|
121
+ expand(parts[1..], obj[index], "#{path}#{separator}[#{index}]")
122
+ end
123
+ elsif part.start_with?('[') && part.end_with?(']')
124
+ # Specific index in the array
125
+ index = part[1...-1].to_i
126
+ if index.is_a?(Numeric) && index < obj.length
127
+ expand(parts[1..], obj[index], "#{path}#{separator}#{part}")
128
+ else
129
+ []
130
+ end
131
+ else
132
+ if obj && obj.is_a?(Hash) && obj.key?(part)
133
+ expand(parts[1..], obj[part], "#{path}#{separator}#{part}")
134
+ else
135
+ []
136
+ end
137
+ end
138
+ end
139
+
140
+ def self.expand_key(key, obj)
141
+ parts = key.scan(/[^.\[\]]+|\[\d*\]|\[\*\]/) || []
142
+ expand(parts, obj, '')
143
+ end
144
+
145
+ def self.expand_sensitive_key_set_for_arrays(obj, sensitive_keys)
146
+ sensitive_keys.flat_map { |key| expand_key(key, obj) }
147
+ end
148
+
149
+ def self.marshal_key_path(keypath)
150
+ keypath.gsub(/^requestHeaders/, 'request.headers')
151
+ .gsub(/^requestBody/, 'request.body')
152
+ .gsub(/^responseHeaders/, 'response.headers')
153
+ .gsub(/^responseBody/, 'response.body')
154
+ end
155
+
156
+ def self.unmarshal_key_path(keypath)
157
+ keypath.gsub(/^request\.headers/, 'requestHeaders')
158
+ .gsub(/^request\.body/, 'requestBody')
159
+ .gsub(/^response\.headers/, 'responseHeaders')
160
+ .gsub(/^response\.body/, 'responseBody')
161
+ end
162
+
163
+ def self.set_value_to_nil(hash, key_path)
164
+ keys = key_path.split('.')
165
+ current_key = keys.first
166
+ index = current_key.match(/\[(\d+)\]/)
167
+
168
+ index = index[1].to_i if index
169
+
170
+ # Convert current_key to symbol if necessary
171
+ current_key = current_key.gsub(/\[\d+\]/, '') if index
172
+
173
+ return hash unless hash.keys.include?(current_key)
174
+
175
+ if keys.length == 1
176
+ index ? hash[current_key][index] = nil : hash[current_key] = nil
177
+ elsif hash[current_key].is_a?(Hash)
178
+ set_value_to_nil(hash[current_key], keys[1..].join('.'))
179
+ elsif hash[current_key].is_a?(Array)
180
+ set_value_to_nil(hash[current_key][index], keys[1..].join('.'))
181
+ end
182
+
183
+ hash
184
+ end
185
+
186
+ def self.find_leaf_key_paths(structure, current_path = [])
187
+ key_paths = []
188
+
189
+ if structure.is_a?(Hash)
190
+ # Iterate through each key-value pair in the hash
191
+ structure.each do |key, value|
192
+ # Recursively find key paths in the value
193
+ key_paths += find_leaf_key_paths(value, current_path + [key.to_s])
194
+ end
195
+ elsif structure.is_a?(Array)
196
+ # Iterate through each element in the array
197
+ structure.each_with_index do |element, index|
198
+ # Modify how indices are appended to the path
199
+ # Check if the last element in the current_path is a hash key or an array index
200
+ if current_path.last && current_path.last.include?('[')
201
+ new_path = current_path[0...-1] + ["#{current_path.last}[#{index}]"]
202
+ else
203
+ new_path = current_path + ["[#{index}]"]
204
+ end
205
+
206
+ # Recursively find key paths in the element
207
+ key_paths += find_leaf_key_paths(element, new_path)
208
+ end
209
+ else
210
+ # Leaf node: construct the key path and add it to the list
211
+ key_path = current_path.join('.').gsub('.[', '[')
212
+ key_paths << key_path unless key_path.empty?
213
+ end
214
+
215
+ key_paths
216
+ end
217
+
218
+ def self.redact_values_from_keys(event, remote_config, force_redact_all)
219
+ sensitive_key_metadata = []
220
+ endpoint_config = get_endpoint_config(event['request'], remote_config)
221
+
222
+ unless (endpoint_config && endpoint_config['sensitive_keys'].any?) || force_redact_all
223
+ return { 'event' => event, 'sensitive_key_metadata' => sensitive_key_metadata }
224
+ end
225
+
226
+ if force_redact_all
227
+ # Need response.body in path
228
+ sensitive_keys = find_leaf_key_paths(event['response']['body'], ['response', 'body'])
229
+ sensitive_keys += find_leaf_key_paths(event['request']['body'], ['request', 'body'])
230
+ sensitive_keys += find_leaf_key_paths(event['request']['headers'], ['request', 'headers'])
231
+ sensitive_keys += find_leaf_key_paths(event['response']['headers'], ['response', 'headers'])
232
+ else
233
+ sensitive_keys = endpoint_config['sensitive_keys']
234
+ end
235
+
236
+ sensitive_keys = expand_sensitive_key_set_for_arrays(
237
+ event, sensitive_keys.map { |key| marshal_key_path(key) }
238
+ )
239
+ sensitive_keys.each do |key_path|
240
+ value = R_.get(event, key_path)
241
+ event = set_value_to_nil(event, key_path)
242
+ # Add sensitive key for array expansion
243
+ sensitive_key_metadata << { 'keyPath' => unmarshal_key_path(key_path) }.merge(redact_value(value))
244
+ end
245
+
246
+ { 'event' => event, 'sensitive_key_metadata' => sensitive_key_metadata }
247
+ end
248
+
249
+ def self.redact_value(input)
250
+ data_length = 0
251
+ data_type = 'null'
252
+ case input
253
+ when Array
254
+ data_length = input.size
255
+ data_type = 'array'
256
+ when Hash
257
+ data_length = input.to_json.bytesize
258
+ data_type = 'object'
259
+ when String
260
+ data_length = input.size
261
+ data_type = 'string'
262
+ when Numeric
263
+ data_length = input.to_s.size
264
+ data_type = input.integer? ? 'integer' : 'float'
265
+ when TrueClass, FalseClass # This is a better way to check for booleans
266
+ data_length = 1
267
+ data_type = 'boolean'
268
+ end
269
+ { 'length' => data_length, 'type' => data_type }
270
+ end
271
+
272
+ def self.prepare_data(events, remote_config, force_redact_all)
273
+ events.map do |event|
274
+ redacted_event_with_metadata = redact_values_from_keys(event, remote_config, force_redact_all)
275
+ redacted_event_with_metadata['event'].merge(
276
+ 'metadata': { 'sensitiveKeys': redacted_event_with_metadata['sensitive_key_metadata'] }
277
+ )
278
+ end
74
279
  end
75
280
  end
76
281
  end
@@ -14,7 +14,7 @@ module Supergood
14
14
  url: original_request_payload.uri.to_s,
15
15
  path: original_request_payload.uri.path,
16
16
  search: original_request_payload.uri.query,
17
- domain: original_request_payload.uri.host
17
+ domain: Supergood::Utils.get_host_without_www(original_request_payload.uri.host)
18
18
  }
19
19
  Supergood.intercept(request) do
20
20
  original_response = original_perform(original_request_payload, original_options)
@@ -10,7 +10,7 @@ module Supergood
10
10
  block = lambda do |x|
11
11
  alias original_request_method request
12
12
  def request(original_request_payload, body = nil, &block)
13
- http = self;
13
+ http = self
14
14
  url = Supergood::Utils.request_url(http, original_request_payload)
15
15
  uri = URI.parse(url)
16
16
  request = {
@@ -20,7 +20,7 @@ module Supergood
20
20
  url: url,
21
21
  path: original_request_payload.path,
22
22
  search: uri.query,
23
- domain: uri.host,
23
+ domain: Supergood::Utils.get_host_without_www(uri.host)
24
24
  }
25
25
  Supergood.intercept(request) do
26
26
  original_response = original_request_method(original_request_payload, body, &block)
@@ -1,3 +1,3 @@
1
1
  module Supergood
2
- VERSION = '0.1.5'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: supergood
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Klarfeld