sqreen 1.16.2 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -0
- data/lib/sqreen.rb +20 -13
- data/lib/sqreen/configuration.rb +13 -2
- data/lib/sqreen/events/request_record.rb +28 -0
- data/lib/sqreen/frameworks.rb +4 -3
- data/lib/sqreen/frameworks/generic.rb +39 -3
- data/lib/sqreen/instrumentation.rb +31 -36
- data/lib/sqreen/log.rb +57 -6
- data/lib/sqreen/payload_creator.rb +4 -0
- data/lib/sqreen/rules_callbacks/record_request_context.rb +2 -1
- data/lib/sqreen/runner.rb +12 -3
- data/lib/sqreen/session.rb +17 -19
- data/lib/sqreen/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edfd8cc358ff6408be042a8d11d473b85b00c2a1cf80c97cf5b154a6fa7da037
|
4
|
+
data.tar.gz: f558c9aef036f11b3e20fe0f8d41d7020b7d302233a4385d7cb760a983e91116
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa39b3c2a3af1e2b2135dd735b736dce973eab3810cbbe7dc7d017d25ca69d7f309f9029e9f0281d51cd523f996f86c75963d83b77a2294f6a359f847305f100
|
7
|
+
data.tar.gz: daa34349243dc5a56abadff975c776098db0e1d520f15720bae17443b157cc586ba77bc954ab4c7687866dab4bd4b8607cb6fee4c2e9e3bd68cc9f7b46b78faf
|
data/README.md
CHANGED
@@ -75,3 +75,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
75
75
|
## Contributing
|
76
76
|
|
77
77
|
Bug reports and pull requests are welcome on GitHub at https://github.com/sqreen/RubyAgent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
78
|
+
|
79
|
+
## LICENSE
|
80
|
+
|
81
|
+
Sqreen for Ruby is free-to-use, proprietary software.
|
82
|
+
|
data/lib/sqreen.rb
CHANGED
@@ -18,14 +18,21 @@ require 'thread'
|
|
18
18
|
|
19
19
|
Sqreen.framework.on_start do |framework|
|
20
20
|
if Sqreen.framework.on_pre_fork_preload?
|
21
|
+
Sqreen.log.debug "Sqreen detected a forking server with preloading"
|
21
22
|
next
|
23
|
+
else
|
24
|
+
Sqreen.log.debug "Sqreen detected a single-process server"
|
22
25
|
end
|
23
26
|
Thread.new do
|
24
27
|
begin
|
25
28
|
runner = nil
|
29
|
+
Sqreen.log.debug("Reading configuration")
|
26
30
|
configuration = Sqreen.config_init(framework)
|
27
|
-
Sqreen.log.debug("Starting Sqreen #{Sqreen::VERSION}")
|
28
31
|
framework.sqreen_configuration = configuration
|
32
|
+
Sqreen.log.debug("Initializing logs")
|
33
|
+
Sqreen.log_init
|
34
|
+
Sqreen.log.debug("Starting Sqreen #{Sqreen::VERSION}")
|
35
|
+
warn "[#{Process.pid}] Sqreen logging at level #{Sqreen.log.instance_eval { @logger }.level} to #{Sqreen.log.instance_eval { @logger }.instance_eval { @logdev.filename }}"
|
29
36
|
prevent_startup = Sqreen.framework.prevent_startup
|
30
37
|
if !prevent_startup
|
31
38
|
runner = Sqreen::Runner.new(configuration, framework)
|
@@ -38,33 +45,33 @@ Sqreen.framework.on_start do |framework|
|
|
38
45
|
rescue Sqreen::TokenInvalidException
|
39
46
|
Sqreen.log.error "Sorry but your Sqreen token appears to be invalid.\nYour application is NOT currently protected by Sqreen.\n\nHave you correctly filled your config/sqreen.yml?\n\n"
|
40
47
|
rescue Exception => e
|
41
|
-
Sqreen.log.
|
42
|
-
Sqreen.log.debug e.backtrace
|
48
|
+
Sqreen.log.debug("General exception caught: #{e.inspect}")
|
49
|
+
Sqreen.log.debug e.backtrace
|
43
50
|
if runner
|
44
|
-
|
51
|
+
Sqreen.log.debug("Immediately posting exception for runner #{runner.inspect}")
|
45
52
|
runner.session.post_sqreen_exception(Sqreen::RemoteException.new(e))
|
46
|
-
Sqreen.log.debug("runner = #{runner.inspect}")
|
47
53
|
begin
|
48
54
|
runner.remove_instrumentation
|
49
|
-
rescue =>
|
50
|
-
Sqreen.log.debug(
|
51
|
-
|
52
|
-
|
55
|
+
rescue => e
|
56
|
+
Sqreen.log.debug("Unexpected exception when removing instrumentation: #{e.inspect}")
|
57
|
+
Sqreen.log.debug e.backtrace
|
58
|
+
Sqreen.log.error("Terminating Sqreen thread")
|
53
59
|
return nil
|
54
60
|
end
|
55
61
|
begin
|
56
62
|
runner.logout(false)
|
57
|
-
rescue =>
|
58
|
-
Sqreen.log.debug(
|
63
|
+
rescue StandardError => e
|
64
|
+
Sqreen.log.debug("Unexpected exception when logging out: #{remove_exception.inspect}")
|
65
|
+
Sqreen.log.debug(e.backtrace)
|
59
66
|
nil
|
60
67
|
end
|
61
68
|
end
|
62
69
|
# Wait a few seconds before retrying
|
63
70
|
delay = rand(120)
|
64
|
-
Sqreen.log.debug("Sleeping #{delay} seconds before
|
71
|
+
Sqreen.log.debug("Sleeping #{delay} seconds before restarting Sqreen thread")
|
65
72
|
sleep(delay)
|
66
73
|
retry
|
67
74
|
end
|
68
|
-
Sqreen.log.debug("
|
75
|
+
Sqreen.log.debug("Shutting down Sqreen #{Sqreen::VERSION}")
|
69
76
|
end
|
70
77
|
end unless Sqreen::to_bool(ENV['SQREEN_DISABLE'])
|
data/lib/sqreen/configuration.rb
CHANGED
@@ -96,6 +96,8 @@ module Sqreen
|
|
96
96
|
if path
|
97
97
|
file_config = parse_configuration_file(path)
|
98
98
|
@config.merge!(file_config)
|
99
|
+
else
|
100
|
+
Sqreen.log.warn("could not find sqreen configuration file")
|
99
101
|
end
|
100
102
|
|
101
103
|
env_config = from_environment
|
@@ -162,8 +164,17 @@ module Sqreen
|
|
162
164
|
protected
|
163
165
|
|
164
166
|
def config_file_from_env
|
165
|
-
path = ENV[Sqreen::CONFIG_FILE_BY_ENV]
|
166
|
-
|
167
|
+
return unless (path = ENV[Sqreen::CONFIG_FILE_BY_ENV])
|
168
|
+
|
169
|
+
path = File.expand_path(path)
|
170
|
+
|
171
|
+
unless File.exist?(path)
|
172
|
+
Sqreen.log.warn("could not find sqreen configuration file provided by #{Sqreen::CONFIG_FILE_BY_ENV}: '#{path}'")
|
173
|
+
end
|
174
|
+
|
175
|
+
Sqreen.log.info("using config file provided by #{Sqreen::CONFIG_FILE_BY_ENV}: '#{path}'")
|
176
|
+
|
177
|
+
path
|
167
178
|
end
|
168
179
|
|
169
180
|
def local_config_file
|
@@ -57,10 +57,17 @@ module Sqreen
|
|
57
57
|
else
|
58
58
|
res[:request] = {}
|
59
59
|
end
|
60
|
+
if payload['response']
|
61
|
+
res[:response] = payload['response'].dup
|
62
|
+
else
|
63
|
+
res[:response] = {}
|
64
|
+
end
|
60
65
|
|
61
66
|
res[:request][:parameters] = payload['params'] if payload['params']
|
62
67
|
res[:request][:headers] = payload['headers'] if payload['headers']
|
63
68
|
|
69
|
+
res = Sqreen::EncodingSanitizer.sanitize(res)
|
70
|
+
|
64
71
|
if @redactor
|
65
72
|
res[:request] = @redactor.redact(res[:request])
|
66
73
|
end
|
@@ -108,6 +115,27 @@ module Sqreen
|
|
108
115
|
end
|
109
116
|
end
|
110
117
|
|
118
|
+
class EncodingSanitizer
|
119
|
+
def self.sanitize(obj)
|
120
|
+
case obj
|
121
|
+
when String
|
122
|
+
sanitize_string(obj)
|
123
|
+
when Array
|
124
|
+
obj.map { |e| sanitize(e) }
|
125
|
+
when Hash
|
126
|
+
obj.each_with_object({}) { |(k, v), h| h[k] = sanitize(v) }
|
127
|
+
else
|
128
|
+
obj
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.sanitize_string(s)
|
133
|
+
return s if s.encoding.name == 'UTF-8' && s.valid_encoding?
|
134
|
+
|
135
|
+
s.encode('UTF-16', :invalid => :replace, :undef => :replace).encode('UTF-8')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
111
139
|
# For redacting sensitive data and avoid having it sent to our servers
|
112
140
|
class SensitiveDataRedactor
|
113
141
|
DEFAULT_SENSITIVE_KEYS = Set.new(%w[password secret passwd authorization api_key apikey access_token]).freeze
|
data/lib/sqreen/frameworks.rb
CHANGED
@@ -20,7 +20,9 @@ module Sqreen
|
|
20
20
|
require 'sqreen/frameworks/rails3'
|
21
21
|
Sqreen::Frameworks::Rails3Framework
|
22
22
|
else
|
23
|
-
|
23
|
+
Sqreen.log.warn "Detected unsupported Rails version #{Rails.version}, but continuing"
|
24
|
+
require 'sqreen/frameworks/rails'
|
25
|
+
Sqreen::Frameworks::RailsFramework
|
24
26
|
end
|
25
27
|
when defined?(::Sinatra)
|
26
28
|
require 'sqreen/frameworks/sinatra'
|
@@ -29,8 +31,7 @@ module Sqreen
|
|
29
31
|
require 'sqreen/frameworks/sqreen_test'
|
30
32
|
Sqreen::Frameworks::SqreenTestFramework
|
31
33
|
else
|
32
|
-
|
33
|
-
STDERR.puts "Error: cannot find any framework\n"
|
34
|
+
Sqreen.log.error "Error: cannot find any framework\n"
|
34
35
|
require 'sqreen/frameworks/generic'
|
35
36
|
Sqreen::Frameworks::GenericFramework
|
36
37
|
end
|
@@ -44,6 +44,10 @@ module Sqreen
|
|
44
44
|
ENV['RACK_ENV'] == 'development'
|
45
45
|
end
|
46
46
|
|
47
|
+
def test?
|
48
|
+
ENV['RACK_ENV'] == 'test'
|
49
|
+
end
|
50
|
+
|
47
51
|
PREFERRED_IP_HEADERS = %w[HTTP_X_FORWARDED_FOR HTTP_X_REAL_IP
|
48
52
|
HTTP_CLIENT_IP HTTP_X_FORWARDED
|
49
53
|
HTTP_X_CLUSTER_CLIENT_IP HTTP_FORWARDED_FOR
|
@@ -161,6 +165,23 @@ module Sqreen
|
|
161
165
|
}
|
162
166
|
end
|
163
167
|
|
168
|
+
def response_infos
|
169
|
+
return {} if response.nil?
|
170
|
+
|
171
|
+
content_type = response.header['Content-Type']
|
172
|
+
content_length = begin
|
173
|
+
Integer(response.header['Content-Length'])
|
174
|
+
rescue ArgumentError, TypeError
|
175
|
+
nil
|
176
|
+
end
|
177
|
+
|
178
|
+
{
|
179
|
+
:status => response.status,
|
180
|
+
:content_type => content_type,
|
181
|
+
:content_length => content_length,
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
164
185
|
# Request URL path
|
165
186
|
def request_path
|
166
187
|
req = request
|
@@ -257,17 +278,26 @@ module Sqreen
|
|
257
278
|
SharedStorage.set(:request_overtime, nil)
|
258
279
|
end
|
259
280
|
|
281
|
+
def store_response(rv, _env)
|
282
|
+
SharedStorage.set(:response, Rack::Response.new([], rv[0], rv[1]))
|
283
|
+
end
|
284
|
+
|
260
285
|
# Get the currently stored request
|
261
286
|
def request
|
262
287
|
SharedStorage.get(:request)
|
263
288
|
end
|
264
289
|
|
290
|
+
def response
|
291
|
+
SharedStorage.get(:response)
|
292
|
+
end
|
293
|
+
|
265
294
|
# Cleanup request context
|
266
295
|
def clean_request
|
267
296
|
payload_creator = Sqreen::PayloadCreator.new(self)
|
268
297
|
close_request_record(Sqreen.queue, Sqreen.observations_queue, payload_creator)
|
269
298
|
self.remaining_perf_budget = nil
|
270
299
|
SharedStorage.set(:request, nil)
|
300
|
+
SharedStorage.set(:response, nil)
|
271
301
|
SharedStorage.set(:xss_params, nil)
|
272
302
|
SharedStorage.set(:whitelisted, nil)
|
273
303
|
SharedStorage.set(:request_overtime, nil)
|
@@ -397,7 +427,7 @@ module Sqreen
|
|
397
427
|
each_key_value_for_hash(p) do |value|
|
398
428
|
next unless value.is_a?(String)
|
399
429
|
next if value.size < 5
|
400
|
-
value = value.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
|
430
|
+
value = value.dup.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
|
401
431
|
next if regexp && !regexp.match?(value)
|
402
432
|
parm << value
|
403
433
|
end
|
@@ -415,7 +445,7 @@ module Sqreen
|
|
415
445
|
each_key_value_for_hash(p) do |value|
|
416
446
|
next unless value.is_a?(String)
|
417
447
|
next if value.size < 5
|
418
|
-
value = value.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
|
448
|
+
value = value.dup.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
|
419
449
|
next if regexp && !regexp.match(value)
|
420
450
|
parm << value
|
421
451
|
end
|
@@ -564,7 +594,13 @@ module Sqreen
|
|
564
594
|
end
|
565
595
|
|
566
596
|
def split_ip_addresses(ip_addresses)
|
567
|
-
|
597
|
+
return [] unless ip_addresses
|
598
|
+
|
599
|
+
r = ip_addresses.strip.split(/[,\s]+/)
|
600
|
+
r.map! do |ip|
|
601
|
+
m = /^(?:(?<ip>.*\..*)\:|\[(?<ip>.*)\]\:)/.match(ip)
|
602
|
+
m ? m[:ip] : ip
|
603
|
+
end
|
568
604
|
end
|
569
605
|
|
570
606
|
def valid_ip?(ip)
|
@@ -415,36 +415,31 @@ module Sqreen
|
|
415
415
|
end
|
416
416
|
|
417
417
|
def override_class_method(klass, meth)
|
418
|
-
|
419
|
-
|
420
|
-
|
418
|
+
original = meth.to_sym
|
419
|
+
saved_meth_name = get_saved_method_name(meth).to_sym
|
420
|
+
new_method = "#{meth}_modified".to_sym
|
421
421
|
|
422
|
-
|
423
|
-
|
424
|
-
new_method = '#{meth}_modified'.to_sym
|
422
|
+
klass.singleton_class.instance_eval do
|
423
|
+
alias_method saved_meth_name, original
|
425
424
|
|
426
|
-
|
425
|
+
p = Instrumentation.define_callback_method(original, saved_meth_name, klass)
|
426
|
+
define_method(new_method, p)
|
427
427
|
|
428
|
-
|
429
|
-
#{klass})
|
430
|
-
define_method(new_method, p)
|
428
|
+
private new_method
|
431
429
|
|
432
|
-
|
430
|
+
method_kind = nil
|
431
|
+
if public_method_defined?(original)
|
432
|
+
method_kind = :public
|
433
|
+
elsif protected_method_defined?(original)
|
434
|
+
method_kind = :protected
|
435
|
+
elsif private_method_defined?(original)
|
436
|
+
method_kind = :private
|
437
|
+
end
|
433
438
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
method_kind = :public
|
438
|
-
when protected_method_defined?(original)
|
439
|
-
method_kind = :protected
|
440
|
-
when private_method_defined?(original)
|
441
|
-
method_kind = :private
|
439
|
+
alias_method original, new_method
|
440
|
+
send(method_kind, original)
|
441
|
+
private saved_meth_name
|
442
442
|
end
|
443
|
-
alias_method original, new_method
|
444
|
-
send(method_kind, original)
|
445
|
-
private saved_meth_name
|
446
|
-
end "
|
447
|
-
eval str
|
448
443
|
end
|
449
444
|
|
450
445
|
def unoverride_instance_method(obj, meth)
|
@@ -516,19 +511,19 @@ module Sqreen
|
|
516
511
|
# WARNING We do not actually remove `meth`
|
517
512
|
def unoverride_class_method(klass, meth)
|
518
513
|
saved_meth_name = get_saved_method_name(meth)
|
514
|
+
method_kind = nil
|
519
515
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
end "
|
516
|
+
klass.singleton_class.instance_eval do
|
517
|
+
if public_method_defined?(meth.to_sym)
|
518
|
+
method_kind = :public
|
519
|
+
elsif protected_method_defined?(original)
|
520
|
+
method_kind = :protected
|
521
|
+
elsif private_method_defined?(meth.to_sym)
|
522
|
+
method_kind = :private
|
523
|
+
end
|
524
|
+
alias_method meth.to_sym, saved_meth_name.to_sym
|
525
|
+
send(method_kind, meth.to_sym)
|
526
|
+
end
|
532
527
|
end
|
533
528
|
|
534
529
|
if RUBY_VERSION < '1.9'
|
data/lib/sqreen/log.rb
CHANGED
@@ -9,18 +9,20 @@ require 'sqreen/performance_notifications/log_performance'
|
|
9
9
|
require 'sqreen/configuration'
|
10
10
|
|
11
11
|
module Sqreen
|
12
|
-
def self
|
13
|
-
@logger ||= nil
|
14
|
-
return @logger unless @logger.nil?
|
15
|
-
return NoopLogger.instance unless Sqreen.configured?
|
12
|
+
def self.log_init
|
16
13
|
@logger = Logger.new(
|
17
14
|
Sqreen.config_get(:log_level).to_s.upcase,
|
18
15
|
Sqreen.config_get(:log_location)
|
19
16
|
)
|
17
|
+
DeferredLogger.instance.flush_to(@logger.instance_eval { @logger })
|
20
18
|
rescue => e
|
21
19
|
warn "Sqreen logger exception: #{e}"
|
22
20
|
end
|
23
21
|
|
22
|
+
def self::log
|
23
|
+
@logger || DeferredLogger.instance
|
24
|
+
end
|
25
|
+
|
24
26
|
# Ruby default formatter modified to display current thread_id
|
25
27
|
class FormatterWithTid
|
26
28
|
Format = "%s, [%s#%d.%s] %5s -- %s: %s\n".freeze
|
@@ -113,7 +115,7 @@ module Sqreen
|
|
113
115
|
end
|
114
116
|
|
115
117
|
def create_error_logger
|
116
|
-
@error_logger = ::Logger.new(STDERR)
|
118
|
+
@error_logger = Kernel.const_defined?('MiniTest') ? NullLogger.instance : ::Logger.new(STDERR)
|
117
119
|
enforce_log_format(@error_logger)
|
118
120
|
end
|
119
121
|
|
@@ -122,7 +124,7 @@ module Sqreen
|
|
122
124
|
end
|
123
125
|
end
|
124
126
|
|
125
|
-
class
|
127
|
+
class NullLogger
|
126
128
|
include Singleton
|
127
129
|
|
128
130
|
def debug(_msg = nil); end
|
@@ -132,5 +134,54 @@ module Sqreen
|
|
132
134
|
def warn(_msg = nil); end
|
133
135
|
|
134
136
|
def error(_msg = nil); end
|
137
|
+
|
138
|
+
def formatter=(_); end
|
139
|
+
end
|
140
|
+
|
141
|
+
class DeferredLogger
|
142
|
+
include Singleton
|
143
|
+
|
144
|
+
def initialize
|
145
|
+
@buffer = StringIO.new
|
146
|
+
@logger = ::Logger.new(@buffer)
|
147
|
+
end
|
148
|
+
|
149
|
+
def debug(msg = nil, &block)
|
150
|
+
@logger.debug(msg, &block)
|
151
|
+
end
|
152
|
+
|
153
|
+
def info(msg = nil, &block)
|
154
|
+
@logger.info(msg, &block)
|
155
|
+
end
|
156
|
+
|
157
|
+
def warn(msg = nil, &block)
|
158
|
+
@logger.warn(msg, &block)
|
159
|
+
end
|
160
|
+
|
161
|
+
def error(msg = nil, &block)
|
162
|
+
@logger.error(msg, &block)
|
163
|
+
end
|
164
|
+
|
165
|
+
def formatter=(value)
|
166
|
+
@logger.formatter = value
|
167
|
+
end
|
168
|
+
|
169
|
+
def flush_to(logger)
|
170
|
+
logger.instance_eval { @logdev }.write(read).tap { reset }
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def read
|
176
|
+
@buffer.rewind
|
177
|
+
@buffer.read
|
178
|
+
end
|
179
|
+
|
180
|
+
def reset
|
181
|
+
buffer = StringIO.new
|
182
|
+
logger = ::Logger.new(buffer)
|
183
|
+
logger.formatter = @logger.formatter
|
184
|
+
@buffer, @logger = buffer, logger
|
185
|
+
end
|
135
186
|
end
|
136
187
|
end
|
@@ -54,6 +54,7 @@ module Sqreen
|
|
54
54
|
|
55
55
|
FULL_SECTIONS = {
|
56
56
|
'request' => 'request_infos',
|
57
|
+
'response' => 'response_infos',
|
57
58
|
'params' => 'filtered_request_params',
|
58
59
|
'headers' => 'ip_headers',
|
59
60
|
'local' => 'local_infos',
|
@@ -64,6 +65,9 @@ module Sqreen
|
|
64
65
|
'addr' => 'client_ip',
|
65
66
|
'rid' => 'request_id',
|
66
67
|
},
|
68
|
+
'response' => {
|
69
|
+
'status' => 'status',
|
70
|
+
},
|
67
71
|
'local' => {
|
68
72
|
'name' => 'hostname',
|
69
73
|
},
|
data/lib/sqreen/runner.rb
CHANGED
@@ -228,16 +228,18 @@ module Sqreen
|
|
228
228
|
|
229
229
|
|
230
230
|
def setup_instrumentation(context_infos = {})
|
231
|
-
Sqreen.log.info '
|
231
|
+
Sqreen.log.info 'Setting up instrumentation'
|
232
232
|
rulespack_id, rules = load_rules(context_infos)
|
233
233
|
@framework.instrument_when_ready!(instrumenter, rules)
|
234
|
+
Sqreen.log.info 'Instrumentation set up'
|
234
235
|
rulespack_id.to_s
|
235
236
|
end
|
236
237
|
|
237
238
|
def remove_instrumentation(_context_infos = {})
|
238
|
-
Sqreen.log.debug '
|
239
|
+
Sqreen.log.debug 'Removing instrumentation'
|
239
240
|
instrumenter.remove_all_callbacks
|
240
241
|
Sqreen::Actions::Repository.instance.clear
|
242
|
+
Sqreen.log.debug 'Instrumentation removed'
|
241
243
|
true
|
242
244
|
end
|
243
245
|
|
@@ -419,6 +421,7 @@ module Sqreen
|
|
419
421
|
|
420
422
|
def logout(retrying = true)
|
421
423
|
return unless session
|
424
|
+
Sqreen.log.debug("Logging out")
|
422
425
|
if @framework.development?
|
423
426
|
@running = false
|
424
427
|
return
|
@@ -440,7 +443,13 @@ module Sqreen
|
|
440
443
|
if exit_from_sinatra_startup? && try_again
|
441
444
|
register_exit_cb(false)
|
442
445
|
else
|
443
|
-
|
446
|
+
begin
|
447
|
+
logout
|
448
|
+
rescue StandardError => e
|
449
|
+
Sqreen.log.debug(e.inspect)
|
450
|
+
Sqreen.log.debug(e.backtrace)
|
451
|
+
nil
|
452
|
+
end
|
444
453
|
end
|
445
454
|
end
|
446
455
|
end
|
data/lib/sqreen/session.rb
CHANGED
@@ -89,16 +89,6 @@ module Sqreen
|
|
89
89
|
@http.finish if connected?
|
90
90
|
end
|
91
91
|
|
92
|
-
NET_ERRORS = [Timeout::Error,
|
93
|
-
Errno::EINVAL,
|
94
|
-
Errno::ECONNRESET,
|
95
|
-
Errno::ECONNREFUSED,
|
96
|
-
EOFError,
|
97
|
-
Net::HTTPBadResponse,
|
98
|
-
Net::HTTPHeaderSyntaxError,
|
99
|
-
SocketError,
|
100
|
-
Net::ProtocolError].freeze
|
101
|
-
|
102
92
|
def connect
|
103
93
|
return if connected?
|
104
94
|
Sqreen.log.warn "connection to #{@server_url}..."
|
@@ -106,7 +96,9 @@ module Sqreen
|
|
106
96
|
@conn_retry = 0
|
107
97
|
begin
|
108
98
|
@con = @http.start
|
109
|
-
rescue
|
99
|
+
rescue StandardError => e
|
100
|
+
Sqreen.log.debug { "Caught exception during request: #{e.inspect}" }
|
101
|
+
Sqreen.log.debug { e.backtrace }
|
110
102
|
Sqreen.log.debug "Cannot connect, retry in #{RETRY_CONNECT_SECONDS} seconds"
|
111
103
|
sleep RETRY_CONNECT_SECONDS
|
112
104
|
@conn_retry += 1
|
@@ -133,16 +125,18 @@ module Sqreen
|
|
133
125
|
end
|
134
126
|
|
135
127
|
def resiliently(retry_request_seconds, max_retry, current_retry = 0)
|
128
|
+
connect unless connected?
|
136
129
|
return yield
|
137
130
|
rescue => e
|
138
|
-
Sqreen.log.debug { e.inspect }
|
131
|
+
Sqreen.log.debug { "Caught exception during request: #{e.inspect}" }
|
132
|
+
Sqreen.log.debug { e.backtrace }
|
139
133
|
|
140
134
|
current_retry += 1
|
141
135
|
|
142
136
|
raise e if current_retry >= max_retry || e.is_a?(Sqreen::NotImplementedYet)
|
143
137
|
|
144
138
|
sleep_delay = [MAX_DELAY, retry_request_seconds * current_retry].min
|
145
|
-
Sqreen.log.debug format(
|
139
|
+
Sqreen.log.debug format("Sleeping %ds before retry #{current_retry}/#{max_retry}", sleep_delay)
|
146
140
|
sleep(sleep_delay)
|
147
141
|
|
148
142
|
retry
|
@@ -159,7 +153,6 @@ module Sqreen
|
|
159
153
|
end
|
160
154
|
|
161
155
|
def do_http_request(method, path, data, headers = {}, max_retry = 2)
|
162
|
-
connect unless connected?
|
163
156
|
now = Time.now.utc
|
164
157
|
headers['X-Session-Key'] = @session_id if @session_id
|
165
158
|
headers['X-Sqreen-Time'] = now.to_f.to_s
|
@@ -170,6 +163,7 @@ module Sqreen
|
|
170
163
|
@req_nb,
|
171
164
|
Time.now.utc.to_f)
|
172
165
|
headers['Content-Type'] = 'application/json'
|
166
|
+
headers['Accept'] = 'application/json'
|
173
167
|
if request_compression && !method.casecmp(:GET).zero?
|
174
168
|
headers['Content-Encoding'] = 'gzip'
|
175
169
|
end
|
@@ -198,11 +192,15 @@ module Sqreen
|
|
198
192
|
raise Sqreen::NotImplementedYet
|
199
193
|
end
|
200
194
|
end
|
201
|
-
|
202
195
|
if json && json.body
|
203
|
-
|
204
|
-
|
205
|
-
|
196
|
+
if json['Content-Type'] && json['Content-Type'].start_with?('application/json')
|
197
|
+
res = JSON.parse(json.body)
|
198
|
+
unless res['status']
|
199
|
+
Sqreen.log.debug(format('Cannot %s %s. Parsed response body was: %s', method, path, res.inspect))
|
200
|
+
end
|
201
|
+
else
|
202
|
+
Sqreen.log.debug "Unexpected response Content-Type: #{json['Content-Type']}"
|
203
|
+
Sqreen.log.debug "Unexpected response body: #{json.body.inspect}"
|
206
204
|
end
|
207
205
|
else
|
208
206
|
Sqreen.log.debug 'warning: empty return value'
|
@@ -283,7 +281,7 @@ module Sqreen
|
|
283
281
|
# @param exception [RemoteException] Exception and context to be sent over
|
284
282
|
def post_sqreen_exception(exception)
|
285
283
|
post('sqreen_exception', exception.to_hash, {}, 5)
|
286
|
-
rescue
|
284
|
+
rescue StandardError => e
|
287
285
|
Sqreen.log.warn(format('Could not post exception (network down? %s) %s',
|
288
286
|
e.inspect,
|
289
287
|
exception.to_hash.inspect))
|
data/lib/sqreen/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqreen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sqreen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sq_mini_racer
|