sqreen 1.12.0 → 1.13.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: 867b430d86c473c22fcad2e5531c5ee70078ffa45201e8e4e906127e854eaf84
4
- data.tar.gz: e8ba868e3b21824963da46dde7abbf171f17cb83732af65599fb84eaa4181245
3
+ metadata.gz: fb4ef79ad2d573f02250c303800c9d4c8b64a3f1e0318fbf2f7e198508826b7b
4
+ data.tar.gz: 991f85b77cb27f9387fb027e74538aded1a7f0e4dd0c1a78a8a89041154d790a
5
5
  SHA512:
6
- metadata.gz: 98d5d2879397613f82ead509e0dc352ab7c139c8e045f0e64d4f2f8938b3c992264e4053e6b1d001af7f2131593bf319d45882235388b417d48c9cf88a337093
7
- data.tar.gz: c0ee0912af909dd7fa94db71a5480215dc36e4e2c3cd6471dae61b0ee888763c63e10fa385027957d0d7c17e34c47aa96968225be3a4ebe8f04fbe044b2ad0ab
6
+ metadata.gz: a575ae38cbccc9381e8dea3fedc7c7ac24ce0a7174b0ba799f264cfbd8bf0a346c4c60fc6518172f6bff09d692193d469cb31fe4513781f67468d52c7db14419
7
+ data.tar.gz: 8dffc28661b0e8fd608cae0917326519abf7c6d8f4b36d96ffead33e6df3059f0de05187a03d425d21068e36a04f8b6f0b42c9375bce9a9a7515c1fe6f847ff4
@@ -6,6 +6,7 @@ require 'sqreen/log'
6
6
  require 'sqreen/exception'
7
7
  require 'sqreen/sdk'
8
8
  require 'sqreen/frameworks'
9
+ require 'singleton'
9
10
 
10
11
  module Sqreen
11
12
  # Implements actions (behavior taken in response to agent signals)
@@ -58,25 +59,39 @@ module Sqreen
58
59
  return nil
59
60
  end
60
61
 
61
- subclass.new(id, duration, hash['parameters'] || {})
62
+ opts = {
63
+ :duration => duration,
64
+ :send_response => hash['send_response'],
65
+ }
66
+
67
+ subclass.new(id, opts, hash['parameters'] || {})
62
68
  end
63
69
 
70
+ # Base class for actions
64
71
  class Base
65
- attr_reader :id, :expiry
72
+ attr_reader :id, :expiry, :send_response
66
73
 
67
- def initialize(id, duration)
74
+ def initialize(id, opts)
68
75
  @id = id
76
+ duration = opts[:duration]
69
77
  @expiry = Time.new + duration unless duration.nil?
78
+ @send_response = if opts[:send_response].nil?
79
+ true
80
+ else
81
+ !!opts[:send_response]
82
+ end
70
83
  end
71
84
 
72
85
  # See Sqreen::CB for return values
73
86
  def run(*args)
74
87
  return if expiry && Time.new > expiry
75
88
  ret = do_run *args
76
- unless ret.nil?
89
+ unless ret.nil? || !@send_response
77
90
  Sqreen.internal_track(event_name,
78
- 'properties' => event_properties(*args).
79
- merge('action_id' => id))
91
+ 'properties' => {
92
+ 'output' => event_properties(*args),
93
+ 'action_id' => id,
94
+ })
80
95
  end
81
96
  ret
82
97
  end
@@ -155,8 +170,8 @@ module Sqreen
155
170
  include IpRanges
156
171
  self.type_name = 'block_ip'
157
172
 
158
- def initialize(id, duration, params = {})
159
- super(id, duration)
173
+ def initialize(id, opts, params = {})
174
+ super(id, opts)
160
175
  parse_ip_ranges params
161
176
  end
162
177
 
@@ -179,8 +194,8 @@ module Sqreen
179
194
 
180
195
  attr_reader :redirect_url
181
196
 
182
- def initialize(id, duration, params = {})
183
- super(id, duration)
197
+ def initialize(id, opts, params = {})
198
+ super(id, opts)
184
199
  @redirect_url = params['url']
185
200
  raise "no url provided for action #{id}" unless @redirect_url
186
201
  parse_ip_ranges params
@@ -199,5 +214,48 @@ module Sqreen
199
214
  { 'ip_address' => client_ip, 'url' => @redirect_url }
200
215
  end
201
216
  end
217
+
218
+ # Blocks a user at the point Sqreen::identify()
219
+ # or Sqreen::auth_track() are called
220
+ class BlockUser < Base
221
+ self.type_name = 'block_user'
222
+
223
+ def initialize(id, opts, params = {})
224
+ super(id, opts)
225
+ @users = params['users']
226
+ raise ::Sqreen::Exception, 'nil "users" param for block_user action' if @users.nil?
227
+ raise ::Sqreen::Exception, '"users" param must be an array' unless @users.is_a? Array
228
+ end
229
+
230
+ def do_run(identity_params)
231
+ return unless @users.include? stringify_keys(identity_params)
232
+ Sqreen.log.info(
233
+ "Will raise due to user being blocked by action #{id}. " \
234
+ "Blocked user identity: #{identity_params}"
235
+ )
236
+
237
+ e = Sqreen::AttackBlocked.new(
238
+ "Blocked user with identity #{identity_params} " \
239
+ 'due to automatic security response. No action is required'
240
+ )
241
+
242
+ {
243
+ :status => :raise,
244
+ :exception => e,
245
+ }
246
+ end
247
+
248
+ def event_properties(identity_params)
249
+ { 'user' => identity_params }
250
+ end
251
+
252
+ private
253
+
254
+ def stringify_keys(hash)
255
+ Hash[
256
+ hash.map { |k, v| [k.to_s, v] }
257
+ ]
258
+ end
259
+ end
202
260
  end
203
261
  end
@@ -49,6 +49,8 @@ module Sqreen
49
49
  :default => false, :convert => :to_bool },
50
50
  { :env => :SQREEN_INITIAL_FEATURES, :name => :initial_features,
51
51
  :default => nil },
52
+ { :env => :SQREEN_IP_HEADER, :name => :ip_header,
53
+ :default => nil },
52
54
 
53
55
  ].freeze
54
56
 
@@ -42,9 +42,7 @@ module Sqreen
42
42
  end
43
43
  end
44
44
  if observed[:sdk]
45
- res[:observed][:sdk] = observed[:sdk].map do |meth, time, *args|
46
- { :name => meth, :time => time, :args => args }
47
- end
45
+ res[:observed][:sdk] = processed_sdk_calls
48
46
  end
49
47
  end
50
48
  res[:local] = payload['local'] if payload['local']
@@ -58,5 +56,44 @@ module Sqreen
58
56
  res[:request][:headers] = payload['headers'] if payload['headers']
59
57
  res
60
58
  end
59
+
60
+ private
61
+
62
+ def processed_sdk_calls
63
+ auth_keys = last_identify_id
64
+
65
+ observed[:sdk].map do |meth, time, *args|
66
+ {
67
+ :name => meth,
68
+ :time => time,
69
+ :args => inject_identifiers(args, meth, auth_keys),
70
+ }
71
+ end
72
+ end
73
+
74
+ def inject_identifiers(args, meth, auth_keys)
75
+ return args unless meth == :track && auth_keys
76
+
77
+ track_opts = args[1] || {}
78
+ if track_opts[:user_identifiers].nil?
79
+ args[1] = track_opts.dup
80
+ args[1][:user_identifiers] = auth_keys
81
+ elsif track_opts[:user_identifiers] != auth_keys
82
+ Sqreen.log.warn 'Sqreen.identify and Sqreen.track have been called ' \
83
+ 'with different user_identifiers values'
84
+ end
85
+
86
+ args
87
+ end
88
+
89
+ def last_identify_id
90
+ return nil unless observed[:sdk]
91
+
92
+ observed[:sdk].reverse_each do |meth, _time, *args|
93
+ next unless meth == :identify
94
+ return args.first if args.respond_to? :first
95
+ end
96
+ nil
97
+ end
61
98
  end
62
99
  end
@@ -44,16 +44,30 @@ module Sqreen
44
44
  ENV['RACK_ENV'] == 'development'
45
45
  end
46
46
 
47
- PREFFERED_IP_HEADERS = %w(HTTP_X_FORWARDED_FOR HTTP_X_REAL_IP
47
+ PREFERRED_IP_HEADERS = %w[HTTP_X_FORWARDED_FOR HTTP_X_REAL_IP
48
48
  HTTP_CLIENT_IP HTTP_X_FORWARDED
49
49
  HTTP_X_CLUSTER_CLIENT_IP HTTP_FORWARDED_FOR
50
- HTTP_FORWARDED HTTP_VIA).freeze
50
+ HTTP_FORWARDED HTTP_VIA].freeze
51
+
52
+ def preferred_ip_headers
53
+ @preferred_ip_headers ||=
54
+ begin
55
+ header_name = Sqreen.config_get(:ip_header)
56
+ if header_name
57
+ env_var = 'HTTP_' + header_name.tr('-', '_').upcase
58
+ [env_var] + (PREFERRED_IP_HEADERS - [env_var])
59
+ else
60
+ PREFERRED_IP_HEADERS
61
+ end
62
+ end
63
+ end
64
+ private :preferred_ip_headers
51
65
 
52
66
  def ip_headers
53
67
  req = request
54
68
  return [] unless req
55
69
  ips = []
56
- (PREFFERED_IP_HEADERS + ['REMOTE_ADDR']).each do |header|
70
+ (preferred_ip_headers + ['REMOTE_ADDR']).each do |header|
57
71
  v = req.env[header]
58
72
  ips << [header, v] unless v.nil?
59
73
  end
@@ -79,7 +93,7 @@ module Sqreen
79
93
  return nil unless req
80
94
  # Look for an external address being forwarded
81
95
  split_ips = []
82
- PREFFERED_IP_HEADERS.each do |header_name|
96
+ preferred_ip_headers.each do |header_name|
83
97
  forwarded = req.env[header_name]
84
98
  ips = split_ip_addresses(forwarded)
85
99
  lip = ips.find { |ip| (ip !~ TRUSTED_PROXIES) && valid_ip?(ip) }
@@ -11,6 +11,7 @@ require 'sqreen/rules_signature'
11
11
  require 'sqreen/shared_storage'
12
12
  require 'sqreen/rules_callbacks/record_request_context'
13
13
  require 'sqreen/rules_callbacks/run_req_start_actions'
14
+ require 'sqreen/rules_callbacks/run_block_user_actions'
14
15
  require 'set'
15
16
 
16
17
  # How to override a class method:
@@ -245,6 +246,10 @@ module Sqreen
245
246
  def self.define_callback_method(meth, original_meth, klass_name)
246
247
  @sqreen_multi_instr ||= nil
247
248
  proc do |*args, &block|
249
+ record_req_hp = @@record_request_hookpoints.include?([klass_name, meth]) &&
250
+ Sqreen::PerformanceNotifications.listen_for?
251
+ Sqreen::PerformanceNotifications::BinnedMetrics.start_request if record_req_hp
252
+
248
253
  budget = nil
249
254
  skip_call = Thread.current[:sqreen_in_use]
250
255
  begin
@@ -370,6 +375,7 @@ module Sqreen
370
375
  next unless ret.is_a? Hash
371
376
  case ret[:status]
372
377
  when :raise, 'raise'
378
+ raise ret[:exception] if ret.key?(:exception)
373
379
  raise Sqreen::AttackBlocked, "Sqreen blocked a security threat (type: #{ret[:rule_name]}). No action is required."
374
380
  when :override, 'override'
375
381
  result = ret[:new_return_value]
@@ -379,10 +385,11 @@ module Sqreen
379
385
  end
380
386
  result
381
387
  ensure
382
- if @@record_request_hookpoints.include?([klass_name, meth]) && Sqreen::PerformanceNotifications.listen_for?
388
+ if record_req_hp
383
389
  Sqreen::PerformanceNotifications.instrument('Callbacks/hooks_reporting/pre') do
384
390
  Sqreen::PerformanceNotifications::LogPerformance.next_request
385
391
  Sqreen::PerformanceNotifications::NewRelic.next_request
392
+ Sqreen::PerformanceNotifications::BinnedMetrics.finish_request
386
393
  end
387
394
  end
388
395
  Thread.current[:sqreen_in_use] = false
@@ -439,6 +446,8 @@ module Sqreen
439
446
  end
440
447
  alias_method meth, saved_meth_name
441
448
  send(method_kind, meth)
449
+
450
+ remove_method saved_meth_name
442
451
  end
443
452
  end
444
453
 
@@ -450,6 +459,15 @@ module Sqreen
450
459
  saved_meth_name = get_saved_method_name(meth)
451
460
  new_method = "#{meth}_modified".to_sym
452
461
 
462
+ # do not include ancestors o/wise we might get a saved method from a
463
+ # superclass which is never called because the original name
464
+ # (instrumented) method of the superclass has been overridden
465
+ private_meths = klass_name.private_instance_methods(false)
466
+ if private_meths.include?(saved_meth_name)
467
+ Sqreen.log.debug { "#{saved_meth_name} found #{klass_name}##{meth} already instrumented" }
468
+ return saved_meth_name
469
+ end
470
+
453
471
  p = Instrumentation.define_callback_method(meth, saved_meth_name,
454
472
  klass_name)
455
473
  method_kind = nil
@@ -664,7 +682,9 @@ module Sqreen
664
682
  # @return [Array<Sqreen::CB>]
665
683
  def hardcoded_callbacks(framework)
666
684
  [
667
- Sqreen::Rules::RunReqStartActions.new(framework)
685
+ Sqreen::Rules::RunReqStartActions.new(framework),
686
+ Sqreen::Rules::RunBlockUserActions.new(Sqreen, :identify, 0),
687
+ Sqreen::Rules::RunBlockUserActions.new(Sqreen, :auth_track, 1),
668
688
  ]
669
689
  end
670
690
 
@@ -4,3 +4,4 @@
4
4
  require 'sqreen/metrics/collect'
5
5
  require 'sqreen/metrics/average'
6
6
  require 'sqreen/metrics/sum'
7
+ require 'sqreen/metrics/binning'
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2018 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/metrics/base'
5
+
6
+ module Sqreen
7
+ module Metric
8
+ # Takes numbers as samples and bins them (effectively, rounds them).
9
+ class Binning < Base
10
+ # upper bound of i-th bin is factor * base^(i-1)
11
+ def initialize(base, factor)
12
+ super()
13
+ @base = base
14
+ @factor = factor
15
+ log_base = Math.log(base)
16
+ log_factor = Math.log(factor)
17
+ @inv_log_base = 1 / log_base
18
+ @add_parcel = - log_factor / log_base
19
+ new_sample(Time.now.utc)
20
+ end
21
+
22
+ def update(_at, _key, x)
23
+ h = @sample[OBSERVATION_KEY]
24
+ bin = bin_no(x)
25
+ h[bin] += 1
26
+ end
27
+
28
+ def next_sample(time)
29
+ return nil if @sample[OBSERVATION_KEY].empty?
30
+ super(time)
31
+ end
32
+
33
+ protected
34
+
35
+ # these two are called by next_sample
36
+
37
+ def finalize_sample(time)
38
+ @sample[FINISH_KEY] = time
39
+ h = @sample[OBSERVATION_KEY]
40
+ @sample[OBSERVATION_KEY] = { 'u' => @factor, 'b' => @base, 'v' => h }
41
+ end
42
+
43
+ def new_sample(time)
44
+ @sample = {
45
+ OBSERVATION_KEY => Hash.new { |hash, key| hash[key] = 0 },
46
+ START_KEY => time,
47
+ }
48
+ end
49
+
50
+ private
51
+
52
+ def bin_no(x)
53
+ res = 2 + (@inv_log_base * Math.log(x) + @add_parcel).floor
54
+ res < 1 ? 1 : res
55
+ end
56
+ end
57
+
58
+ # overrides the constructor
59
+ class ParameterizedBinning < Binning
60
+ def initialize
61
+ raise 'Not configured' unless self.class.base && self.class.factor
62
+ super(self.class.base, self.class.factor)
63
+ end
64
+
65
+ class << self
66
+ attr_reader :base, :factor
67
+ def parameters(opts)
68
+ @base = opts[:base]
69
+ @factor = opts[:factor]
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -33,7 +33,7 @@ module Sqreen
33
33
 
34
34
  # Definition contains a name,period and aggregate at least
35
35
  # @param definition [Hash] a metric definition
36
- # @param klass [Object] Override metric class (used in testing)
36
+ # @param mklass [Object] Override metric object (used in testing)
37
37
  def create_metric(definition, mklass = nil)
38
38
  name = definition[NAME_KEY]
39
39
  kind = definition[KIND_KEY]
@@ -47,6 +47,10 @@ module Sqreen
47
47
  metric
48
48
  end
49
49
 
50
+ def metric?(name)
51
+ @metrics.key?(name)
52
+ end
53
+
50
54
  def update(name, at, key, value)
51
55
  at = at.utc
52
56
  metric, period, start = @metrics[name]
@@ -71,7 +75,7 @@ module Sqreen
71
75
  def next_sample(name, at)
72
76
  metric = @metrics[name][0]
73
77
  r = metric.next_sample(at)
74
- @metrics[name][2] = at
78
+ @metrics[name][2] = at # start
75
79
  if r
76
80
  r[NAME_KEY] = name
77
81
  obs = r[Metric::OBSERVATION_KEY]
@@ -0,0 +1,119 @@
1
+ # Copyright (c) 2018 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/performance_notifications'
5
+
6
+ module Sqreen
7
+ #
8
+ module PerformanceNotifications
9
+ # Logs callback performance
10
+ class BinnedMetrics
11
+ EVENT_REQ = 'req'.freeze # request total time
12
+ EVENT_TOTAL_TIME = 'sq'.freeze # sqreen total overhead callback time
13
+
14
+ EVT_NAME_REGEXP = %r{\ACallbacks/([^/]+)/([^/]+)\z}
15
+
16
+ # @param metrics_store [Sqreen::MetricsStore]
17
+ def initialize(metrics_store, period)
18
+ @metrics_store = metrics_store
19
+ @period = period
20
+ @subid = nil
21
+ end
22
+
23
+ def enable
24
+ return unless @subid.nil?
25
+
26
+ metrics_store.create_metric(
27
+ 'name' => EVENT_REQ, 'period' => period, 'kind' => 'ParameterizedBinning'
28
+ )
29
+ metrics_store.create_metric(
30
+ 'name' => EVENT_TOTAL_TIME, 'period' => period, 'kind' => 'ParameterizedBinning'
31
+ )
32
+
33
+ @subid = Sqreen::PerformanceNotifications.subscribe(&method(:log))
34
+ end
35
+
36
+ def disable
37
+ return if @subid.nil?
38
+ Sqreen::PerformanceNotifications.unsubscribe(@subid)
39
+ @subid = nil
40
+ end
41
+
42
+ def log(event, start, finish, _meta)
43
+ return unless event =~ EVT_NAME_REGEXP
44
+ rule, cb = Regexp.last_match.captures
45
+
46
+ metric_name = "sq.#{rule}.#{cb}"
47
+ ensure_metric(metric_name)
48
+
49
+ finish_time = SQREEN_MONO_TIME ? Time.now.utc : finish
50
+ time_millis = (finish - start) * 1000
51
+ SharedStorage[:sqreen_request_time] += time_millis
52
+ metrics_store.update(metric_name, finish_time, nil, time_millis)
53
+ end
54
+
55
+ def start_request
56
+ SharedStorage[:request_start_time] = PerformanceNotifications.time
57
+ SharedStorage[:sqreen_request_time] = 0.0
58
+ end
59
+
60
+ def finish_request
61
+ start_time = SharedStorage[:request_start_time]
62
+ finish_time = PerformanceNotifications.time
63
+ duration_millis = (finish_time - start_time) * 1000
64
+
65
+ finish_time_obj = SQREEN_MONO_TIME ? Time.now.utc : finish_time
66
+ # format of evt is [cat, key, value, timestamp]
67
+ Sqreen.observations_queue.push(
68
+ [EVENT_REQ, nil, duration_millis, finish_time_obj]
69
+ )
70
+ Sqreen.observations_queue.push(
71
+ [EVENT_TOTAL_TIME, nil,
72
+ SharedStorage[:sqreen_request_time], finish_time_obj]
73
+ )
74
+ end
75
+
76
+ private
77
+
78
+ # @return [Sqreen::MetricsStore]
79
+ attr_reader :metrics_store
80
+ attr_reader :period
81
+
82
+ def ensure_metric(metric_name)
83
+ return if metrics_store.metric?(metric_name)
84
+ metrics_store.create_metric(
85
+ 'name' => metric_name, 'period' => period, 'kind' => 'ParameterizedBinning'
86
+ )
87
+ end
88
+
89
+ @instance = nil
90
+ class << self
91
+ # @return [Sqreen::PerformanceNotifications::BinnedMetrics]
92
+ attr_reader :instance
93
+ def enable(metrics_store, period = 60, base = 2.0, factor = 0.1)
94
+ disable
95
+ Sqreen::Metric::ParameterizedBinning.parameters(
96
+ :base => base, :factor => factor
97
+ )
98
+ @instance = new(metrics_store, period).tap(&:enable)
99
+ end
100
+
101
+ def disable
102
+ return unless instance
103
+ instance.disable
104
+ @instance = nil
105
+ end
106
+
107
+ def start_request
108
+ return unless instance
109
+ instance.start_request
110
+ end
111
+
112
+ def finish_request
113
+ return unless instance
114
+ instance.finish_request
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2018 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/rule_callback'
5
+ require 'sqreen/actions'
6
+
7
+ module Sqreen
8
+ module Rules
9
+ # Runs the block_user actions (for hooking Sqreen.{identify,auth_user})
10
+ class RunBlockUserActions < CB
11
+ def initialize(klass, method, auth_keys_idx)
12
+ super(klass, method)
13
+ @auth_keys_idx = auth_keys_idx
14
+ end
15
+
16
+ def post(_retval, _inst, args, _budget = nil)
17
+ actions = actions_repo[Sqreen::Actions::BlockUser]
18
+
19
+ actions.each do |action|
20
+ res = action.run args[@auth_keys_idx]
21
+ return res unless res.nil?
22
+ end
23
+ nil
24
+ end
25
+
26
+ private
27
+
28
+ # @return [Sqreen::Actions::Repository]
29
+ def actions_repo
30
+ Sqreen::Actions::Repository.instance
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/sqreen/runner.rb CHANGED
@@ -17,6 +17,7 @@ require 'sqreen/metrics_store'
17
17
  require 'sqreen/deliveries/simple'
18
18
  require 'sqreen/deliveries/batch'
19
19
  require 'sqreen/performance_notifications/metrics'
20
+ require 'sqreen/performance_notifications/binned_metrics'
20
21
  require 'sqreen/instrumentation'
21
22
  require 'sqreen/call_countable'
22
23
 
@@ -30,6 +31,11 @@ module Sqreen
30
31
 
31
32
  METRICS_EVENT = 'metrics'.freeze
32
33
 
34
+ PERF_METRICS_PERIOD = 60 # 1 min
35
+ DEFAULT_PERF_LEVEL = 0 # disabled
36
+ DEFAULT_PERF_UNIT = 0.1 # ms
37
+ DEFAULT_PERF_BASE = 2.0
38
+
33
39
  class << self
34
40
  attr_reader :features
35
41
  def update_features(features)
@@ -204,6 +210,20 @@ module Sqreen
204
210
  end
205
211
  end
206
212
 
213
+ def config_binned_metrics(level, base, factor)
214
+ level = level.to_i
215
+ if level <= 0
216
+ Sqreen.log.debug('Disabling binned metrics')
217
+ PerformanceNotifications::BinnedMetrics.disable
218
+ else
219
+ Sqreen.log.warn("Unknown value for perf_level: #{level}. Treating as 1") unless level == 1
220
+ PerformanceNotifications::BinnedMetrics.enable(
221
+ metrics_engine, PERF_METRICS_PERIOD, base.to_f, factor.to_f
222
+ )
223
+ end
224
+ end
225
+
226
+
207
227
  def setup_instrumentation(context_infos = {})
208
228
  Sqreen.log.info 'setup instrumentation'
209
229
  rulespack_id, rules = load_rules(context_infos)
@@ -282,6 +302,9 @@ module Sqreen
282
302
  Sqreen.update_features(features)
283
303
  session.request_compression = features['request_compression'] if session
284
304
  self.performance_metrics_period = features['performance_metrics_period']
305
+ config_binned_metrics(features['perf_level'] || DEFAULT_PERF_LEVEL,
306
+ features['perf_base'] || DEFAULT_PERF_BASE,
307
+ features['perf_unit'] || DEFAULT_PERF_UNIT)
285
308
  self.call_counts_metrics_period = features['call_counts_metrics_period']
286
309
  hd = features['heartbeat_delay'].to_i
287
310
  self.heartbeat_delay = hd if hd > 0
data/lib/sqreen/sdk.rb CHANGED
@@ -36,13 +36,13 @@ module Sqreen
36
36
  # For internal usage. Users are to call track() instead.
37
37
  def internal_track(event_name, options = {})
38
38
  properties = options[:properties]
39
- authentication_keys = options[:user_identifiers]
39
+ user_identifiers = options[:user_identifiers]
40
40
  timestamp = options[:timestamp] || Time.now.utc
41
41
  # Not in SDK v0
42
42
  # request = options[:request]
43
43
 
44
44
  args = {}
45
- args[:authentication_keys] = authentication_keys if authentication_keys
45
+ args[:user_identifiers] = user_identifiers if user_identifiers
46
46
  args[:properties] = properties if properties
47
47
 
48
48
  Sqreen.framework.observe(
@@ -33,3 +33,8 @@ end
33
33
 
34
34
  # Change SharedStorage.get if ruby is actually newer
35
35
  require 'sqreen/shared_storage23' if RUBY_VERSION >= '2.3.0'
36
+
37
+ class << Sqreen::SharedStorage
38
+ alias [] get
39
+ alias []= set
40
+ end
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
2
  # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
3
  module Sqreen
4
- VERSION = '1.12.0'.freeze
4
+ VERSION = '1.13.0'.freeze
5
5
  end
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.12.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sqreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-31 00:00:00.000000000 Z
11
+ date: 2018-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: execjs
@@ -81,12 +81,14 @@ files:
81
81
  - lib/sqreen/metrics.rb
82
82
  - lib/sqreen/metrics/average.rb
83
83
  - lib/sqreen/metrics/base.rb
84
+ - lib/sqreen/metrics/binning.rb
84
85
  - lib/sqreen/metrics/collect.rb
85
86
  - lib/sqreen/metrics/sum.rb
86
87
  - lib/sqreen/metrics_store.rb
87
88
  - lib/sqreen/middleware.rb
88
89
  - lib/sqreen/payload_creator.rb
89
90
  - lib/sqreen/performance_notifications.rb
91
+ - lib/sqreen/performance_notifications/binned_metrics.rb
90
92
  - lib/sqreen/performance_notifications/log.rb
91
93
  - lib/sqreen/performance_notifications/log_performance.rb
92
94
  - lib/sqreen/performance_notifications/metrics.rb
@@ -111,6 +113,7 @@ files:
111
113
  - lib/sqreen/rules_callbacks/record_request_context.rb
112
114
  - lib/sqreen/rules_callbacks/reflected_xss.rb
113
115
  - lib/sqreen/rules_callbacks/regexp_rule.rb
116
+ - lib/sqreen/rules_callbacks/run_block_user_actions.rb
114
117
  - lib/sqreen/rules_callbacks/run_req_start_actions.rb
115
118
  - lib/sqreen/rules_callbacks/shell_env.rb
116
119
  - lib/sqreen/rules_callbacks/url_matches.rb