resurfaceio-logger 1.10.0 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '081b638ef0c63585d851de54a9b30ef9b54de58cf68f880785c2e1a8d214cb54'
4
- data.tar.gz: a71c49ec92a27637f7d77b52177df39d0b197757a056154e5247f5e40aa350d1
3
+ metadata.gz: 78d67f05915dcaee82ef7e3809856549bf09d01ac1f26d32f4dcb02003d317f3
4
+ data.tar.gz: f3d3598661aed83877882554183991ef228ac92d3f875f087eafddd3221cfa59
5
5
  SHA512:
6
- metadata.gz: f2f2c6be12c8977756ab185cc34c64cc29b0956940139315a1d9c023f4df0756cbea1c3fdb8eaab9207070ddda63ee1dac34688d8272d1782d5664b531de94a3
7
- data.tar.gz: 8eed5ac226184687025edf8d3f213585b73d1577c8c6a5420f71b4bc5205add88470672e350746edef7e2a48bf3441276517fcb7ec176bdb16f88b21f9059c7a
6
+ metadata.gz: 5aa5de88c997daddb5f345e4e41d5a173e59adb449dec141ee015747a48ef2f82a7ec623a6b1630d913f5a018f72c4aa1907e310fa1a7808f5c5c579db0281d9
7
+ data.tar.gz: e998c80806e0488c0790e551285e3ae90b7897aa7e027019ad18fd9c9794f0bb37add6d5aaeddb8eb275e66da18b3b9e21b042af636009966d9b6773f200ae88
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  require 'resurfaceio/base_logger'
5
5
  require 'resurfaceio/http_logger'
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  require 'uri'
5
5
  require 'net/http'
@@ -51,7 +51,12 @@ class BaseLogger
51
51
  end
52
52
  end
53
53
 
54
+ # finalize internal properties
54
55
  @enableable = !@queue.nil? || !@url.nil?
56
+ @submit_failures = 0
57
+ @submit_failures_lock = Mutex.new
58
+ @submit_successes = 0
59
+ @submit_successes_lock = Mutex.new
55
60
  end
56
61
 
57
62
  def agent
@@ -102,10 +107,10 @@ class BaseLogger
102
107
 
103
108
  def submit(msg)
104
109
  if msg.nil? || @skip_submission || !enabled?
105
- true
110
+ # do nothing
106
111
  elsif @queue
107
112
  @queue << msg
108
- true
113
+ @submit_successes_lock.synchronize { @submit_successes += 1 }
109
114
  else
110
115
  begin
111
116
  @url_parsed ||= URI.parse(@url)
@@ -119,14 +124,26 @@ class BaseLogger
119
124
  request.body = Zlib::Deflate.deflate(msg)
120
125
  end
121
126
  response = @url_connection.request(request)
122
- response.code.to_i == 204
127
+ if response.code.to_i == 204
128
+ @submit_successes_lock.synchronize { @submit_successes += 1 }
129
+ else
130
+ @submit_failures_lock.synchronize { @submit_failures += 1 }
131
+ end
123
132
  rescue SocketError
133
+ @submit_failures_lock.synchronize { @submit_failures += 1 }
124
134
  @url_connection = nil
125
- false
126
135
  end
127
136
  end
128
137
  end
129
138
 
139
+ def submit_failures
140
+ @submit_failures
141
+ end
142
+
143
+ def submit_successes
144
+ @submit_successes
145
+ end
146
+
130
147
  def url
131
148
  @url
132
149
  end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  require 'json'
5
5
  require 'resurfaceio/base_logger'
@@ -11,53 +11,20 @@ class HttpLogger < BaseLogger
11
11
 
12
12
  AGENT = 'http_logger.rb'.freeze
13
13
 
14
- @@default_rules = HttpRules.strict_rules
15
-
16
- def self.default_rules
17
- @@default_rules
18
- end
19
-
20
- def self.default_rules=(val)
21
- @@default_rules = val.gsub(/^\s*include default\s*$/, '')
22
- end
23
-
24
- def self.string_content_type?(s)
25
- !s.nil? && !(s =~ /^(text\/(html|plain|xml))|(application\/(json|soap|xml|x-www-form-urlencoded))/i).nil?
26
- end
27
-
28
14
  def initialize(options = {})
29
15
  super(AGENT, options)
30
16
 
31
- # read rules from param or defaults
17
+ # parse specified rules
32
18
  if options.respond_to?(:has_key?) && options.has_key?(:rules)
33
- @rules = options[:rules].gsub(/^\s*include default\s*$/, @@default_rules)
34
- @rules = @@default_rules unless @rules.strip.length > 0
19
+ @rules = HttpRules.new(options[:rules])
35
20
  else
36
- @rules = @@default_rules
21
+ @rules = HttpRules.new(nil)
37
22
  end
38
23
 
39
- # parse and break rules out by verb
40
- prs = HttpRules.parse(@rules)
41
- @rules_allow_http_url = prs.select {|r| 'allow_http_url' == r.verb}.length > 0
42
- @rules_copy_session_field = prs.select {|r| 'copy_session_field' == r.verb}
43
- @rules_remove = prs.select {|r| 'remove' == r.verb}
44
- @rules_remove_if = prs.select {|r| 'remove_if' == r.verb}
45
- @rules_remove_if_found = prs.select {|r| 'remove_if_found' == r.verb}
46
- @rules_remove_unless = prs.select {|r| 'remove_unless' == r.verb}
47
- @rules_remove_unless_found = prs.select {|r| 'remove_unless_found' == r.verb}
48
- @rules_replace = prs.select {|r| 'replace' == r.verb}
49
- @rules_sample = prs.select {|r| 'sample' == r.verb}
50
- @rules_stop = prs.select {|r| 'stop' == r.verb}
51
- @rules_stop_if = prs.select {|r| 'stop_if' == r.verb}
52
- @rules_stop_if_found = prs.select {|r| 'stop_if_found' == r.verb}
53
- @rules_stop_unless = prs.select {|r| 'stop_unless' == r.verb}
54
- @rules_stop_unless_found = prs.select {|r| 'stop_unless_found' == r.verb}
55
- @skip_compression = prs.select {|r| 'skip_compression' == r.verb}.length > 0
56
- @skip_submission = prs.select {|r| 'skip_submission' == r.verb}.length > 0
57
-
58
- # finish validating rules
59
- raise RuntimeError.new('Multiple sample rules') if @rules_sample.length > 1
60
- unless @url.nil? || @url.start_with?('https') || @rules_allow_http_url
24
+ # apply configuration rules
25
+ @skip_compression = @rules.skip_compression
26
+ @skip_submission = @rules.skip_submission
27
+ unless @url.nil? || @url.start_with?('https') || @rules.allow_http_url
61
28
  @enableable = false
62
29
  @enabled = false
63
30
  end
@@ -67,58 +34,21 @@ class HttpLogger < BaseLogger
67
34
  @rules
68
35
  end
69
36
 
70
- def log(request, response, response_body = nil, request_body = nil)
71
- !enabled? || submit(format(request, response, response_body, request_body))
72
- end
73
-
74
- def format(request, response, response_body = nil, request_body = nil, now = nil)
75
- details = HttpMessage.build(request, response, response_body, request_body)
37
+ def submit_if_passing(details)
38
+ # apply active rules
39
+ details = @rules.apply(details)
40
+ return nil if details.nil?
76
41
 
77
- # copy data from session if configured
78
- unless @rules_copy_session_field.empty?
79
- ssn = request.session
80
- if !ssn.nil? && ssn.respond_to?(:keys)
81
- @rules_copy_session_field.each do |r|
82
- ssn.keys.each {|d| (details << ["session_field:#{d}", ssn[d].to_s]) if r.param1.match(d)}
83
- end
84
- end
85
- end
86
-
87
- # quit early based on stop rules if configured
88
- @rules_stop.each {|r| details.each {|d| return nil if r.scope.match(d[0])}}
89
- @rules_stop_if_found.each {|r| details.each {|d| return nil if r.scope.match(d[0]) && r.param1.match(d[1])}}
90
- @rules_stop_if.each {|r| details.each {|d| return nil if r.scope.match(d[0]) && r.param1.match(d[1])}}
91
- passed = 0
92
- @rules_stop_unless_found.each {|r| details.each {|d| passed += 1 if r.scope.match(d[0]) && r.param1.match(d[1])}}
93
- return nil if passed != @rules_stop_unless_found.length
94
- passed = 0
95
- @rules_stop_unless.each {|r| details.each {|d| passed += 1 if r.scope.match(d[0]) && r.param1.match(d[1])}}
96
- return nil if passed != @rules_stop_unless.length
97
-
98
- # do sampling if configured
99
- return nil if !@rules_sample[0].nil? && (rand * 100 >= @rules_sample[0].param1)
100
-
101
- # winnow sensitive details based on remove rules if configured
102
- @rules_remove.each {|r| details.delete_if {|d| r.scope.match(d[0])}}
103
- @rules_remove_unless_found.each {|r| details.delete_if {|d| r.scope.match(d[0]) && !r.param1.match(d[1])}}
104
- @rules_remove_if_found.each {|r| details.delete_if {|d| r.scope.match(d[0]) && r.param1.match(d[1])}}
105
- @rules_remove_unless.each {|r| details.delete_if {|d| r.scope.match(d[0]) && !r.param1.match(d[1])}}
106
- @rules_remove_if.each {|r| details.delete_if {|d| r.scope.match(d[0]) && r.param1.match(d[1])}}
107
- return nil if details.empty?
108
-
109
- # mask sensitive details based on replace rules if configured
110
- @rules_replace.each {|r| details.each {|d| d[1] = d[1].gsub(r.param1, r.param2) if r.scope.match(d[0])}}
111
-
112
- # remove any details with empty values
113
- details.delete_if {|d| '' == d[1]}
114
- return nil if details.empty?
115
-
116
- # finish message
117
- details << ['now', now.nil? ? (Time.now.to_f * 1000).floor.to_s : now]
42
+ # finalize message
118
43
  details << ['agent', @agent]
119
44
  details << ['host', @host]
120
45
  details << ['version', @version]
121
- JSON.generate details
46
+
47
+ # let's do this thing
48
+ submit(JSON.generate(details))
122
49
  end
123
50
 
51
+ def self.string_content_type?(s)
52
+ !s.nil? && !(s =~ /^(text\/(html|plain|xml))|(application\/(json|soap|xml|x-www-form-urlencoded))/i).nil?
53
+ end
124
54
  end
@@ -1,8 +1,9 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  require 'rack'
5
5
  require 'resurfaceio/http_logger'
6
+ require 'resurfaceio/http_message'
6
7
 
7
8
  class HttpLoggerForRack # http://rack.rubyforge.org/doc/SPEC.html
8
9
 
@@ -21,7 +22,7 @@ class HttpLoggerForRack # http://rack.rubyforge.org/doc/SPEC.html
21
22
  response = Rack::Response.new(body, status, headers)
22
23
  if HttpLogger::string_content_type?(response.content_type)
23
24
  request = Rack::Request.new(env)
24
- @logger.submit(@logger.format(request, response))
25
+ HttpMessage.send(logger, request, response) # todo add timing details
25
26
  end
26
27
  end
27
28
  [status, headers, body]
@@ -1,7 +1,8 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  require 'resurfaceio/http_logger'
5
+ require 'resurfaceio/http_message'
5
6
 
6
7
  class HttpLoggerForRails
7
8
 
@@ -20,7 +21,7 @@ class HttpLoggerForRails
20
21
  response = controller.response
21
22
  status = response.status
22
23
  if (status < 300 || status == 302) && HttpLogger::string_content_type?(response.content_type)
23
- @logger.submit(@logger.format(request, response))
24
+ HttpMessage.send(logger, request, response) # todo add timing details
24
25
  end
25
26
  end
26
27
  end
@@ -1,10 +1,33 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  require 'json'
5
5
 
6
6
  class HttpMessage
7
7
 
8
+ def self.send(logger, request, response, response_body = nil, request_body = nil, now = nil, interval = nil)
9
+ return unless logger.enabled?
10
+
11
+ # copy details from request & response
12
+ message = build(request, response, response_body, request_body)
13
+
14
+ # copy details from active session
15
+ unless logger.rules.copy_session_field.empty?
16
+ ssn = request.session
17
+ if !ssn.nil? && ssn.respond_to?(:keys)
18
+ logger.rules.copy_session_field.each do |r|
19
+ ssn.keys.each {|d| (message << ["session_field:#{d}", ssn[d].to_s]) if r.param1.match(d)}
20
+ end
21
+ end
22
+ end
23
+
24
+ # add timing details
25
+ message << ['now', now.nil? ? (Time.now.to_f * 1000).floor.to_s : now]
26
+ message << ['interval', interval] unless interval.nil?
27
+
28
+ logger.submit_if_passing(message)
29
+ end
30
+
8
31
  def self.build(request, response, response_body = nil, request_body = nil)
9
32
  message = []
10
33
  append_value message, 'request_method', request.request_method unless request.request_method.nil?
@@ -19,8 +42,6 @@ class HttpMessage
19
42
  return message
20
43
  end
21
44
 
22
- protected
23
-
24
45
  def self.append_request_headers(message, request)
25
46
  respond_to_env = request.respond_to?(:env)
26
47
  if respond_to_env || request.respond_to?(:headers)
@@ -74,12 +95,12 @@ class HttpMessage
74
95
  unless key.nil?
75
96
  unless value.nil?
76
97
  case value
77
- when Array
78
- message << [key, value.join]
79
- when String
80
- message << [key, value]
81
- else
82
- message << [key, value.to_s]
98
+ when Array
99
+ message << [key, value.join]
100
+ when String
101
+ message << [key, value]
102
+ else
103
+ message << [key, value.to_s]
83
104
  end
84
105
  end
85
106
  end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  class HttpRequestImpl
5
5
 
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  class HttpResponseImpl
5
5
 
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  class HttpRule
5
5
 
@@ -1,37 +1,39 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  class HttpRules
5
5
 
6
+ DEBUG_RULES = "allow_http_url\ncopy_session_field /.*/\n".freeze
7
+
8
+ STANDARD_RULES = %q(/request_header:cookie|response_header:set-cookie/ remove
9
+ /(request|response)_body|request_param/ replace /[a-zA-Z0-9.!#$%&’*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)/, /x@y.com/
10
+ /request_body|request_param|response_body/ replace /[0-9\.\-\/]{9,}/, /xyxy/
11
+ ).freeze
12
+
13
+ STRICT_RULES = %q(/request_url/ replace /([^\?;]+).*/, !\\\\1!
14
+ /request_body|response_body|request_param:.*|request_header:(?!user-agent).*|response_header:(?!(content-length)|(content-type)).*/ remove
15
+ ).freeze
16
+
17
+ @@default_rules = STRICT_RULES
18
+
19
+ def self.default_rules
20
+ @@default_rules
21
+ end
22
+
23
+ def self.default_rules=(val)
24
+ @@default_rules = val.gsub(/^\s*include default\s*$/, '')
25
+ end
26
+
6
27
  def self.debug_rules
7
- "allow_http_url\ncopy_session_field /.*/\n"
28
+ DEBUG_RULES
8
29
  end
9
30
 
10
31
  def self.standard_rules
11
- %q(/request_header:cookie|response_header:set-cookie/ remove
12
- /(request|response)_body|request_param/ replace /[a-zA-Z0-9.!#$%&’*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)/, /x@y.com/
13
- /request_body|request_param|response_body/ replace /[0-9\.\-\/]{9,}/, /xyxy/
14
- )
32
+ STANDARD_RULES
15
33
  end
16
34
 
17
35
  def self.strict_rules
18
- %q(/request_url/ replace /([^\?;]+).*/, !\\\\1!
19
- /request_body|response_body|request_param:.*|request_header:(?!user-agent).*|response_header:(?!(content-length)|(content-type)).*/ remove
20
- )
21
- end
22
-
23
- def self.parse(rules)
24
- result = []
25
- unless rules.nil?
26
- rules = rules.gsub(/^\s*include debug\s*$/, debug_rules)
27
- rules = rules.gsub(/^\s*include standard\s*$/, standard_rules)
28
- rules = rules.gsub(/^\s*include strict\s*$/, strict_rules)
29
- rules.each_line do |rule|
30
- parsed = parse_rule(rule)
31
- result << parsed unless parsed.nil?
32
- end
33
- end
34
- result
36
+ STRICT_RULES
35
37
  end
36
38
 
37
39
  def self.parse_rule(r)
@@ -76,8 +78,6 @@ class HttpRules
76
78
  end
77
79
  end
78
80
 
79
- protected
80
-
81
81
  def self.parse_regex(r, regex)
82
82
  s = parse_string(r, regex)
83
83
  raise RuntimeError.new("Invalid regex (#{regex}) in rule: #{r}") if '*' == s || '+' == s || '?' == s
@@ -109,6 +109,154 @@ class HttpRules
109
109
  raise RuntimeError.new("Invalid expression (#{expr}) in rule: #{r}")
110
110
  end
111
111
 
112
+ def initialize(rules)
113
+ rules = HttpRules.default_rules if rules.nil?
114
+
115
+ # todo load rules from external files
116
+
117
+ # force default rules if necessary
118
+ rules = rules.gsub(/^\s*include default\s*$/, HttpRules.default_rules)
119
+ rules = HttpRules.default_rules unless rules.strip.length > 0
120
+
121
+ # expand rule inclues
122
+ rules = rules.gsub(/^\s*include debug\s*$/, DEBUG_RULES)
123
+ rules = rules.gsub(/^\s*include standard\s*$/, STANDARD_RULES)
124
+ rules = rules.gsub(/^\s*include strict\s*$/, STRICT_RULES)
125
+ @text = rules
126
+
127
+ # parse all rules
128
+ prs = []
129
+ rules.each_line do |rule|
130
+ parsed = HttpRules.parse_rule(rule)
131
+ prs << parsed unless parsed.nil?
132
+ end
133
+ @length = prs.length
134
+
135
+ # break out rules by verb
136
+ @allow_http_url = prs.select {|r| 'allow_http_url' == r.verb}.length > 0
137
+ @copy_session_field = prs.select {|r| 'copy_session_field' == r.verb}
138
+ @remove = prs.select {|r| 'remove' == r.verb}
139
+ @remove_if = prs.select {|r| 'remove_if' == r.verb}
140
+ @remove_if_found = prs.select {|r| 'remove_if_found' == r.verb}
141
+ @remove_unless = prs.select {|r| 'remove_unless' == r.verb}
142
+ @remove_unless_found = prs.select {|r| 'remove_unless_found' == r.verb}
143
+ @replace = prs.select {|r| 'replace' == r.verb}
144
+ @sample = prs.select {|r| 'sample' == r.verb}
145
+ @skip_compression = prs.select {|r| 'skip_compression' == r.verb}.length > 0
146
+ @skip_submission = prs.select {|r| 'skip_submission' == r.verb}.length > 0
147
+ @stop = prs.select {|r| 'stop' == r.verb}
148
+ @stop_if = prs.select {|r| 'stop_if' == r.verb}
149
+ @stop_if_found = prs.select {|r| 'stop_if_found' == r.verb}
150
+ @stop_unless = prs.select {|r| 'stop_unless' == r.verb}
151
+ @stop_unless_found = prs.select {|r| 'stop_unless_found' == r.verb}
152
+
153
+ # validate rules
154
+ raise RuntimeError.new('Multiple sample rules') if @sample.length > 1
155
+ end
156
+
157
+ def allow_http_url
158
+ @allow_http_url
159
+ end
160
+
161
+ def copy_session_field
162
+ @copy_session_field
163
+ end
164
+
165
+ def length
166
+ @length
167
+ end
168
+
169
+ def remove
170
+ @remove
171
+ end
172
+
173
+ def remove_if
174
+ @remove_if
175
+ end
176
+
177
+ def remove_if_found
178
+ @remove_if_found
179
+ end
180
+
181
+ def remove_unless
182
+ @remove_unless
183
+ end
184
+
185
+ def remove_unless_found
186
+ @remove_unless_found
187
+ end
188
+
189
+ def replace
190
+ @replace
191
+ end
192
+
193
+ def sample
194
+ @sample
195
+ end
196
+
197
+ def skip_compression
198
+ @skip_compression
199
+ end
200
+
201
+ def skip_submission
202
+ @skip_submission
203
+ end
204
+
205
+ def stop
206
+ @stop
207
+ end
208
+
209
+ def stop_if
210
+ @stop_if
211
+ end
212
+
213
+ def stop_if_found
214
+ @stop_if_found
215
+ end
216
+
217
+ def stop_unless
218
+ @stop_unless
219
+ end
220
+
221
+ def stop_unless_found
222
+ @stop_unless_found
223
+ end
224
+
225
+ def text
226
+ @text
227
+ end
228
+
229
+ def apply(details)
230
+ # stop rules come first
231
+ @stop.each {|r| details.each {|d| return nil if r.scope.match(d[0])}}
232
+ @stop_if_found.each {|r| details.each {|d| return nil if r.scope.match(d[0]) && r.param1.match(d[1])}}
233
+ @stop_if.each {|r| details.each {|d| return nil if r.scope.match(d[0]) && r.param1.match(d[1])}}
234
+ passed = 0
235
+ @stop_unless_found.each {|r| details.each {|d| passed += 1 if r.scope.match(d[0]) && r.param1.match(d[1])}}
236
+ return nil if passed != @stop_unless_found.length
237
+ passed = 0
238
+ @stop_unless.each {|r| details.each {|d| passed += 1 if r.scope.match(d[0]) && r.param1.match(d[1])}}
239
+ return nil if passed != @stop_unless.length
240
+
241
+ # do sampling if configured
242
+ return nil if !@sample[0].nil? && (rand * 100 >= @sample[0].param1)
243
+
244
+ # winnow sensitive details based on remove rules if configured
245
+ @remove.each {|r| details.delete_if {|d| r.scope.match(d[0])}}
246
+ @remove_unless_found.each {|r| details.delete_if {|d| r.scope.match(d[0]) && !r.param1.match(d[1])}}
247
+ @remove_if_found.each {|r| details.delete_if {|d| r.scope.match(d[0]) && r.param1.match(d[1])}}
248
+ @remove_unless.each {|r| details.delete_if {|d| r.scope.match(d[0]) && !r.param1.match(d[1])}}
249
+ @remove_if.each {|r| details.delete_if {|d| r.scope.match(d[0]) && r.param1.match(d[1])}}
250
+ return nil if details.empty?
251
+
252
+ # mask sensitive details based on replace rules if configured
253
+ @replace.each {|r| details.each {|d| d[1] = d[1].gsub(r.param1, r.param2) if r.scope.match(d[0])}}
254
+
255
+ # remove any details with empty values
256
+ details.delete_if {|d| '' == d[1]}
257
+ details.empty? ? nil : details
258
+ end
259
+
112
260
  REGEX_ALLOW_HTTP_URL = /^\s*allow_http_url\s*(#.*)?$/.freeze
113
261
  REGEX_BLANK_OR_COMMENT = /^\s*([#].*)*$/.freeze
114
262
  REGEX_COPY_SESSION_FIELD = /^\s*copy_session_field\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2019 Resurface Labs Inc.
2
+ # © 2016-2020 Resurface Labs Inc.
3
3
 
4
4
  class UsageLoggers
5
5
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resurfaceio-logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - RobDickinson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-06 00:00:00.000000000 Z
11
+ date: 2020-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler