resurfaceio-logger 1.8.3 → 1.10.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
- SHA1:
3
- metadata.gz: 6325802c6b0b9f45a243d514552865acafe0cf8a
4
- data.tar.gz: 549e12382335f21c169d8657313cf2f60c241bda
2
+ SHA256:
3
+ metadata.gz: '081b638ef0c63585d851de54a9b30ef9b54de58cf68f880785c2e1a8d214cb54'
4
+ data.tar.gz: a71c49ec92a27637f7d77b52177df39d0b197757a056154e5247f5e40aa350d1
5
5
  SHA512:
6
- metadata.gz: 99ec978f7215220b3d35ac7148aa436ddf1e4981983f884836338760a5e6cf6b55b16fd27f6b930bf16b1a85b8b801e3d05a425ec07c0dfb9804a81765726502
7
- data.tar.gz: 1b126b84b901f850adf3e701a5d97242305f33b844fb72de1c5c2ffcaf04a5006bba7a9a0ff48825884767e55d5b71fd674f2dc9aed8cf2cc9221ef9dc41e9af
6
+ metadata.gz: f2f2c6be12c8977756ab185cc34c64cc29b0956940139315a1d9c023f4df0756cbea1c3fdb8eaab9207070ddda63ee1dac34688d8272d1782d5664b531de94a3
7
+ data.tar.gz: 8eed5ac226184687025edf8d3f213585b73d1577c8c6a5420f71b4bc5205add88470672e350746edef7e2a48bf3441276517fcb7ec176bdb16f88b21f9059c7a
@@ -1,12 +1,15 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  require 'resurfaceio/base_logger'
5
5
  require 'resurfaceio/http_logger'
6
6
  require 'resurfaceio/http_logger_for_rack'
7
7
  require 'resurfaceio/http_logger_for_rails'
8
+ require 'resurfaceio/http_message'
8
9
  require 'resurfaceio/http_request_impl'
9
10
  require 'resurfaceio/http_response_impl'
11
+ require 'resurfaceio/http_rule'
12
+ require 'resurfaceio/http_rules'
10
13
  require 'resurfaceio/usage_loggers'
11
14
 
12
15
  module Resurfaceio
@@ -23,12 +26,21 @@ module Resurfaceio
23
26
  class HttpLoggerForRails < HttpLoggerForRails
24
27
  end
25
28
 
29
+ class HttpMessage < HttpMessage
30
+ end
31
+
26
32
  class HttpRequestImpl < HttpRequestImpl
27
33
  end
28
34
 
29
35
  class HttpResponseImpl < HttpResponseImpl
30
36
  end
31
37
 
38
+ class HttpRule < HttpRule
39
+ end
40
+
41
+ class HttpRules < HttpRules
42
+ end
43
+
32
44
  class UsageLoggers < UsageLoggers
33
45
  end
34
46
 
@@ -1,9 +1,10 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  require 'uri'
5
5
  require 'net/http'
6
6
  require 'net/https'
7
+ require 'socket'
7
8
  require 'zlib'
8
9
  require 'resurfaceio/usage_loggers'
9
10
 
@@ -11,6 +12,7 @@ class BaseLogger
11
12
 
12
13
  def initialize(agent, options = {})
13
14
  @agent = agent
15
+ @host = BaseLogger.host_lookup
14
16
  @skip_compression = false
15
17
  @skip_submission = false
16
18
  @version = BaseLogger.version_lookup
@@ -48,6 +50,8 @@ class BaseLogger
48
50
  @enabled = false
49
51
  end
50
52
  end
53
+
54
+ @enableable = !@queue.nil? || !@url.nil?
51
55
  end
52
56
 
53
57
  def agent
@@ -60,14 +64,26 @@ class BaseLogger
60
64
  end
61
65
 
62
66
  def enable
63
- @enabled = true unless @queue.nil? && @url.nil?
67
+ @enabled = true if @enableable
64
68
  self
65
69
  end
66
70
 
71
+ def enableable?
72
+ @enableable
73
+ end
74
+
67
75
  def enabled?
68
76
  @enabled && UsageLoggers.enabled?
69
77
  end
70
78
 
79
+ def host
80
+ @host
81
+ end
82
+
83
+ def queue
84
+ @queue
85
+ end
86
+
71
87
  def skip_compression?
72
88
  @skip_compression
73
89
  end
@@ -84,11 +100,11 @@ class BaseLogger
84
100
  @skip_submission = value
85
101
  end
86
102
 
87
- def submit(json)
88
- if @skip_submission || !enabled?
103
+ def submit(msg)
104
+ if msg.nil? || @skip_submission || !enabled?
89
105
  true
90
106
  elsif @queue
91
- @queue << json
107
+ @queue << msg
92
108
  true
93
109
  else
94
110
  begin
@@ -97,10 +113,10 @@ class BaseLogger
97
113
  @url_connection.use_ssl = @url.include?('https')
98
114
  request = Net::HTTP::Post.new(@url_parsed.path)
99
115
  if @skip_compression
100
- request.body = json
116
+ request.body = msg
101
117
  else
102
118
  request.add_field('Content-Encoding', 'deflated')
103
- request.body = Zlib::Deflate.deflate(json)
119
+ request.body = Zlib::Deflate.deflate(msg)
104
120
  end
105
121
  response = @url_connection.request(request)
106
122
  response.code.to_i == 204
@@ -119,6 +135,16 @@ class BaseLogger
119
135
  @version
120
136
  end
121
137
 
138
+ def self.host_lookup
139
+ dyno = ENV['DYNO']
140
+ return dyno unless dyno.nil?
141
+ begin
142
+ Socket.gethostname
143
+ rescue
144
+ 'unknown'
145
+ end
146
+ end
147
+
122
148
  def self.version_lookup
123
149
  Gem.loaded_specs['resurfaceio-logger'].version.to_s
124
150
  end
@@ -1,107 +1,124 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  require 'json'
5
5
  require 'resurfaceio/base_logger'
6
+ require 'resurfaceio/http_message'
7
+ require 'resurfaceio/http_rule'
8
+ require 'resurfaceio/http_rules'
6
9
 
7
10
  class HttpLogger < BaseLogger
8
11
 
9
12
  AGENT = 'http_logger.rb'.freeze
10
13
 
11
- def initialize(options={})
12
- super(AGENT, options)
13
- end
14
+ @@default_rules = HttpRules.strict_rules
14
15
 
15
- def format(request, response, response_body=nil, request_body=nil, now=nil)
16
- message = []
17
- append_value message, 'request_method', request.request_method
18
- append_value message, 'request_url', request.url
19
- append_value message, 'response_code', response.status
20
- append_request_headers message, request
21
- append_request_params message, request
22
- append_response_headers message, response
23
- append_value message, 'request_body', request_body unless request_body == ''
24
- final_response_body = response_body.nil? ? response.body : response_body
25
- append_value message, 'response_body', final_response_body unless final_response_body == ''
26
- message << ['agent', @agent]
27
- message << ['version', @version]
28
- message << ['now', now.nil? ? (Time.now.to_f * 1000).floor.to_s : now]
29
- JSON.generate message
16
+ def self.default_rules
17
+ @@default_rules
30
18
  end
31
19
 
32
- def log(request, response, response_body=nil, request_body=nil)
33
- !enabled? || submit(format(request, response, response_body, request_body))
20
+ def self.default_rules=(val)
21
+ @@default_rules = val.gsub(/^\s*include default\s*$/, '')
34
22
  end
35
23
 
36
24
  def self.string_content_type?(s)
37
25
  !s.nil? && !(s =~ /^(text\/(html|plain|xml))|(application\/(json|soap|xml|x-www-form-urlencoded))/i).nil?
38
26
  end
39
27
 
40
- protected
41
-
42
- def append_request_headers(message, request)
43
- respond_to_env = request.respond_to?(:env)
44
- if respond_to_env || request.respond_to?(:headers)
45
- headers = respond_to_env ? request.env : request.headers
46
- headers.each do |name, value|
47
- unless value.nil?
48
- if name =~ /^CONTENT_TYPE/
49
- message << ['request_header:content-type', value]
50
- end
51
- if name =~ /^HTTP_/
52
- message << ["request_header:#{name[5..-1].downcase.tr('_', '-')}", value]
53
- end
54
- end
55
- end unless headers.nil?
56
- end
57
- end
28
+ def initialize(options = {})
29
+ super(AGENT, options)
58
30
 
59
- def append_request_params(message, request)
60
- respond_to_env = request.respond_to?(:env)
61
- if respond_to_env || request.respond_to?(:form_hash)
62
- hash = respond_to_env ? request.env['rack.request.form_hash'] : request.form_hash
63
- hash.each do |name, value|
64
- append_value message, "request_param:#{name.downcase}", value
65
- end unless hash.nil?
31
+ # read rules from param or defaults
32
+ 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
35
+ else
36
+ @rules = @@default_rules
66
37
  end
67
- if respond_to_env || request.respond_to?(:query_hash)
68
- hash = respond_to_env ? request.env['rack.request.query_hash'] : request.query_hash
69
- hash.each do |name, value|
70
- append_value message, "request_param:#{name.downcase}", value
71
- end unless hash.nil?
38
+
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
61
+ @enableable = false
62
+ @enabled = false
72
63
  end
73
64
  end
74
65
 
75
- def append_response_headers(message, response)
76
- found_content_type = false
77
- if response.respond_to?(:headers)
78
- response.headers.each do |name, value|
79
- unless value.nil?
80
- name = name.downcase
81
- found_content_type = true if name =~ /^content-type/
82
- message << ["response_header:#{name}", value]
83
- end
84
- end unless response.headers.nil?
85
- end
86
- unless found_content_type || response.content_type.nil?
87
- message << ['response_header:content-type', response.content_type]
88
- end
66
+ def rules
67
+ @rules
68
+ end
69
+
70
+ def log(request, response, response_body = nil, request_body = nil)
71
+ !enabled? || submit(format(request, response, response_body, request_body))
89
72
  end
90
73
 
91
- def append_value(message, key, value=nil)
92
- unless key.nil?
93
- unless value.nil?
94
- case value
95
- when Array
96
- message << [key, value.join]
97
- when String
98
- message << [key, value]
99
- else
100
- message << [key, value.to_s]
74
+ def format(request, response, response_body = nil, request_body = nil, now = nil)
75
+ details = HttpMessage.build(request, response, response_body, request_body)
76
+
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)}
101
83
  end
102
84
  end
103
85
  end
104
- message
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]
118
+ details << ['agent', @agent]
119
+ details << ['host', @host]
120
+ details << ['version', @version]
121
+ JSON.generate details
105
122
  end
106
123
 
107
124
  end
@@ -1,12 +1,12 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  require 'rack'
5
5
  require 'resurfaceio/http_logger'
6
6
 
7
7
  class HttpLoggerForRack # http://rack.rubyforge.org/doc/SPEC.html
8
8
 
9
- def initialize(app, options={})
9
+ def initialize(app, options = {})
10
10
  @app = app
11
11
  @logger = HttpLogger.new(options)
12
12
  end
@@ -21,7 +21,7 @@ class HttpLoggerForRack # http://rack.rubyforge.org/doc/SPEC.html
21
21
  response = Rack::Response.new(body, status, headers)
22
22
  if HttpLogger::string_content_type?(response.content_type)
23
23
  request = Rack::Request.new(env)
24
- @logger.log(request, response)
24
+ @logger.submit(@logger.format(request, response))
25
25
  end
26
26
  end
27
27
  [status, headers, body]
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  require 'resurfaceio/http_logger'
5
5
 
6
6
  class HttpLoggerForRails
7
7
 
8
- def initialize(options={})
8
+ def initialize(options = {})
9
9
  @logger = HttpLogger.new(options)
10
10
  end
11
11
 
@@ -15,11 +15,13 @@ class HttpLoggerForRails
15
15
 
16
16
  def around(controller)
17
17
  yield
18
- request = controller.request
19
- response = controller.response
20
- status = response.status
21
- if (status < 300 || status == 302) && HttpLogger::string_content_type?(response.content_type)
22
- @logger.log(request, response)
18
+ if @logger.enabled?
19
+ request = controller.request
20
+ response = controller.response
21
+ status = response.status
22
+ if (status < 300 || status == 302) && HttpLogger::string_content_type?(response.content_type)
23
+ @logger.submit(@logger.format(request, response))
24
+ end
23
25
  end
24
26
  end
25
27
 
@@ -0,0 +1,89 @@
1
+ # coding: utf-8
2
+ # © 2016-2019 Resurface Labs Inc.
3
+
4
+ require 'json'
5
+
6
+ class HttpMessage
7
+
8
+ def self.build(request, response, response_body = nil, request_body = nil)
9
+ message = []
10
+ append_value message, 'request_method', request.request_method unless request.request_method.nil?
11
+ append_value message, 'request_url', request.url unless request.url.nil?
12
+ append_value message, 'response_code', response.status unless response.status.nil?
13
+ append_request_headers message, request
14
+ append_request_params message, request
15
+ append_response_headers message, response
16
+ append_value message, 'request_body', request_body unless request_body == ''
17
+ final_response_body = response_body.nil? ? response.body : response_body
18
+ append_value message, 'response_body', final_response_body unless final_response_body == ''
19
+ return message
20
+ end
21
+
22
+ protected
23
+
24
+ def self.append_request_headers(message, request)
25
+ respond_to_env = request.respond_to?(:env)
26
+ if respond_to_env || request.respond_to?(:headers)
27
+ headers = respond_to_env ? request.env : request.headers
28
+ headers.each do |name, value|
29
+ unless value.nil?
30
+ if name =~ /^CONTENT_TYPE/
31
+ message << ['request_header:content-type', value]
32
+ end
33
+ if name =~ /^HTTP_/
34
+ message << ["request_header:#{name[5..-1].downcase.tr('_', '-')}", value]
35
+ end
36
+ end
37
+ end unless headers.nil?
38
+ end
39
+ end
40
+
41
+ def self.append_request_params(message, request)
42
+ respond_to_env = request.respond_to?(:env)
43
+ if respond_to_env || request.respond_to?(:form_hash)
44
+ hash = respond_to_env ? request.env['rack.request.form_hash'] : request.form_hash
45
+ hash.each do |name, value|
46
+ append_value message, "request_param:#{name.downcase}", value
47
+ end unless hash.nil?
48
+ end
49
+ if respond_to_env || request.respond_to?(:query_hash)
50
+ hash = respond_to_env ? request.env['rack.request.query_hash'] : request.query_hash
51
+ hash.each do |name, value|
52
+ append_value message, "request_param:#{name.downcase}", value
53
+ end unless hash.nil?
54
+ end
55
+ end
56
+
57
+ def self.append_response_headers(message, response)
58
+ found_content_type = false
59
+ if response.respond_to?(:headers)
60
+ response.headers.each do |name, value|
61
+ unless value.nil?
62
+ name = name.downcase
63
+ found_content_type = true if name =~ /^content-type/
64
+ message << ["response_header:#{name}", value]
65
+ end
66
+ end unless response.headers.nil?
67
+ end
68
+ unless found_content_type || response.content_type.nil?
69
+ message << ['response_header:content-type', response.content_type]
70
+ end
71
+ end
72
+
73
+ def self.append_value(message, key, value = nil)
74
+ unless key.nil?
75
+ unless value.nil?
76
+ 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]
83
+ end
84
+ end
85
+ end
86
+ message
87
+ end
88
+
89
+ end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  class HttpRequestImpl
5
5
 
@@ -7,6 +7,7 @@ class HttpRequestImpl
7
7
  @form_hash = Hash.new
8
8
  @headers = Hash.new
9
9
  @query_hash = Hash.new
10
+ @session = Hash.new
10
11
  end
11
12
 
12
13
  def add_header(key, value)
@@ -40,6 +41,10 @@ class HttpRequestImpl
40
41
  @query_hash
41
42
  end
42
43
 
44
+ def session
45
+ @session
46
+ end
47
+
43
48
  attr_accessor :request_method
44
49
  attr_accessor :url
45
50
 
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  class HttpResponseImpl
5
5
 
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+ # © 2016-2019 Resurface Labs Inc.
3
+
4
+ class HttpRule
5
+
6
+ def initialize(verb, scope = nil, param1 = nil, param2 = nil)
7
+ @verb = verb
8
+ @scope = scope
9
+ @param1 = param1
10
+ @param2 = param2
11
+ end
12
+
13
+ attr_reader :verb, :scope, :param1, :param2
14
+
15
+ end
@@ -0,0 +1,130 @@
1
+ # coding: utf-8
2
+ # © 2016-2019 Resurface Labs Inc.
3
+
4
+ class HttpRules
5
+
6
+ def self.debug_rules
7
+ "allow_http_url\ncopy_session_field /.*/\n"
8
+ end
9
+
10
+ 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
+ )
15
+ end
16
+
17
+ 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
35
+ end
36
+
37
+ def self.parse_rule(r)
38
+ if r.nil? || r.match(REGEX_BLANK_OR_COMMENT)
39
+ nil
40
+ elsif r.match(REGEX_ALLOW_HTTP_URL)
41
+ HttpRule.new('allow_http_url')
42
+ elsif (m = r.match(REGEX_COPY_SESSION_FIELD))
43
+ HttpRule.new('copy_session_field', nil, parse_regex(r, m[1]))
44
+ elsif (m = r.match(REGEX_REMOVE))
45
+ HttpRule.new('remove', parse_regex(r, m[1]))
46
+ elsif (m = r.match(REGEX_REMOVE_IF))
47
+ HttpRule.new('remove_if', parse_regex(r, m[1]), parse_regex(r, m[2]))
48
+ elsif (m = r.match(REGEX_REMOVE_IF_FOUND))
49
+ HttpRule.new('remove_if_found', parse_regex(r, m[1]), parse_regex_find(r, m[2]))
50
+ elsif (m = r.match(REGEX_REMOVE_UNLESS))
51
+ HttpRule.new('remove_unless', parse_regex(r, m[1]), parse_regex(r, m[2]))
52
+ elsif (m = r.match(REGEX_REMOVE_UNLESS_FOUND))
53
+ HttpRule.new('remove_unless_found', parse_regex(r, m[1]), parse_regex_find(r, m[2]))
54
+ elsif (m = r.match(REGEX_REPLACE))
55
+ HttpRule.new('replace', parse_regex(r, m[1]), parse_regex_find(r, m[2]), parse_string(r, m[3]))
56
+ elsif (m = r.match(REGEX_SAMPLE))
57
+ m1 = m[1].to_i
58
+ raise RuntimeError.new("Invalid sample percent: #{m1}") if m1 < 1 || m1 > 99
59
+ HttpRule.new('sample', nil, m1)
60
+ elsif r.match(REGEX_SKIP_COMPRESSION)
61
+ HttpRule.new('skip_compression')
62
+ elsif r.match(REGEX_SKIP_SUBMISSION)
63
+ HttpRule.new('skip_submission')
64
+ elsif (m = r.match(REGEX_STOP))
65
+ HttpRule.new('stop', parse_regex(r, m[1]))
66
+ elsif (m = r.match(REGEX_STOP_IF))
67
+ HttpRule.new('stop_if', parse_regex(r, m[1]), parse_regex(r, m[2]))
68
+ elsif (m = r.match(REGEX_STOP_IF_FOUND))
69
+ HttpRule.new('stop_if_found', parse_regex(r, m[1]), parse_regex_find(r, m[2]))
70
+ elsif (m = r.match(REGEX_STOP_UNLESS))
71
+ HttpRule.new('stop_unless', parse_regex(r, m[1]), parse_regex(r, m[2]))
72
+ elsif (m = r.match(REGEX_STOP_UNLESS_FOUND))
73
+ HttpRule.new('stop_unless_found', parse_regex(r, m[1]), parse_regex_find(r, m[2]))
74
+ else
75
+ raise RuntimeError.new("Invalid rule: #{r}")
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ def self.parse_regex(r, regex)
82
+ s = parse_string(r, regex)
83
+ raise RuntimeError.new("Invalid regex (#{regex}) in rule: #{r}") if '*' == s || '+' == s || '?' == s
84
+ s = "^#{s}" unless s.start_with?('^')
85
+ s = "#{s}$" unless s.end_with?('$')
86
+ begin
87
+ return Regexp.compile(s)
88
+ rescue RegexpError
89
+ raise RuntimeError.new("Invalid regex (#{regex}) in rule: #{r}")
90
+ end
91
+ end
92
+
93
+ def self.parse_regex_find(r, regex)
94
+ begin
95
+ return Regexp.compile(parse_string(r, regex))
96
+ rescue RegexpError
97
+ raise RuntimeError.new("Invalid regex (#{regex}) in rule: #{r}")
98
+ end
99
+ end
100
+
101
+ def self.parse_string(r, expr)
102
+ %w(~ ! % | /).each do |sep|
103
+ if (m = expr.match(/^[#{sep}](.*)[#{sep}]$/))
104
+ m1 = m[1]
105
+ raise RuntimeError.new("Unescaped separator (#{sep}) in rule: #{r}") if m1.match(/^[#{sep}].*|.*[^\\][#{sep}].*/)
106
+ return m1.gsub("\\#{sep}", sep)
107
+ end
108
+ end
109
+ raise RuntimeError.new("Invalid expression (#{expr}) in rule: #{r}")
110
+ end
111
+
112
+ REGEX_ALLOW_HTTP_URL = /^\s*allow_http_url\s*(#.*)?$/.freeze
113
+ REGEX_BLANK_OR_COMMENT = /^\s*([#].*)*$/.freeze
114
+ REGEX_COPY_SESSION_FIELD = /^\s*copy_session_field\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
115
+ REGEX_REMOVE = /^\s*([~!%|\/].+[~!%|\/])\s*remove\s*(#.*)?$/.freeze
116
+ REGEX_REMOVE_IF = /^\s*([~!%|\/].+[~!%|\/])\s*remove_if\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
117
+ REGEX_REMOVE_IF_FOUND = /^\s*([~!%|\/].+[~!%|\/])\s*remove_if_found\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
118
+ REGEX_REMOVE_UNLESS = /^\s*([~!%|\/].+[~!%|\/])\s*remove_unless\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
119
+ REGEX_REMOVE_UNLESS_FOUND = /^\s*([~!%|\/].+[~!%|\/])\s*remove_unless_found\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
120
+ REGEX_REPLACE = /^\s*([~!%|\/].+[~!%|\/])\s*replace[\s]+([~!%|\/].+[~!%|\/]),[\s]+([~!%|\/].*[~!%|\/])\s*(#.*)?$/.freeze
121
+ REGEX_SAMPLE = /^\s*sample\s+(\d+)\s*(#.*)?$/.freeze
122
+ REGEX_SKIP_COMPRESSION = /^\s*skip_compression\s*(#.*)?$/.freeze
123
+ REGEX_SKIP_SUBMISSION = /^\s*skip_submission\s*(#.*)?$/.freeze
124
+ REGEX_STOP = /^\s*([~!%|\/].+[~!%|\/])\s*stop\s*(#.*)?$/.freeze
125
+ REGEX_STOP_IF = /^\s*([~!%|\/].+[~!%|\/])\s*stop_if\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
126
+ REGEX_STOP_IF_FOUND = /^\s*([~!%|\/].+[~!%|\/])\s*stop_if_found\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
127
+ REGEX_STOP_UNLESS = /^\s*([~!%|\/].+[~!%|\/])\s*stop_unless\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
128
+ REGEX_STOP_UNLESS_FOUND = /^\s*([~!%|\/].+[~!%|\/])\s*stop_unless_found\s+([~!%|\/].+[~!%|\/])\s*(#.*)?$/.freeze
129
+
130
+ end
@@ -1,18 +1,18 @@
1
1
  # coding: utf-8
2
- # © 2016-2017 Resurface Labs LLC
2
+ # © 2016-2019 Resurface Labs Inc.
3
3
 
4
4
  class UsageLoggers
5
5
 
6
- @@DISABLED = 'true'.eql?(ENV['USAGE_LOGGERS_DISABLE'])
6
+ @@BRICKED = 'true'.eql?(ENV['USAGE_LOGGERS_DISABLE'])
7
7
 
8
- @@disabled = @@DISABLED
8
+ @@disabled = @@BRICKED
9
9
 
10
10
  def self.disable
11
11
  @@disabled = true
12
12
  end
13
13
 
14
14
  def self.enable
15
- @@disabled = false unless @@DISABLED
15
+ @@disabled = false unless @@BRICKED
16
16
  end
17
17
 
18
18
  def self.enabled?
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.8.3
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - RobDickinson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-11 00:00:00.000000000 Z
11
+ date: 2019-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -77,8 +77,11 @@ files:
77
77
  - lib/resurfaceio/http_logger.rb
78
78
  - lib/resurfaceio/http_logger_for_rack.rb
79
79
  - lib/resurfaceio/http_logger_for_rails.rb
80
+ - lib/resurfaceio/http_message.rb
80
81
  - lib/resurfaceio/http_request_impl.rb
81
82
  - lib/resurfaceio/http_response_impl.rb
83
+ - lib/resurfaceio/http_rule.rb
84
+ - lib/resurfaceio/http_rules.rb
82
85
  - lib/resurfaceio/usage_loggers.rb
83
86
  homepage: https://github.com/resurfaceio/logger-ruby
84
87
  licenses:
@@ -100,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
103
  version: '0'
101
104
  requirements: []
102
105
  rubyforge_project:
103
- rubygems_version: 2.5.2
106
+ rubygems_version: 2.7.7
104
107
  signing_key:
105
108
  specification_version: 4
106
109
  summary: Library for usage logging