sqreen 1.19.1 → 1.20.2
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/CHANGELOG.md +22 -0
- data/lib/sqreen/agent_message.rb +20 -0
- data/lib/sqreen/aggregated_metric.rb +25 -0
- data/lib/sqreen/attack_detected.html +1 -2
- data/lib/sqreen/ca.crt +24 -0
- data/lib/sqreen/configuration.rb +10 -4
- data/lib/sqreen/deferred_logger.rb +4 -0
- data/lib/sqreen/deliveries/batch.rb +4 -1
- data/lib/sqreen/deliveries/simple.rb +4 -0
- data/lib/sqreen/endpoint_testing.rb +184 -0
- data/lib/sqreen/event.rb +7 -5
- data/lib/sqreen/events/attack.rb +23 -18
- data/lib/sqreen/events/remote_exception.rb +0 -22
- data/lib/sqreen/events/request_record.rb +15 -70
- data/lib/sqreen/frameworks/request_recorder.rb +13 -2
- data/lib/sqreen/graft/call.rb +32 -19
- data/lib/sqreen/graft/callback.rb +1 -1
- data/lib/sqreen/graft/hook.rb +97 -116
- data/lib/sqreen/graft/hook_point.rb +1 -1
- data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
- data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
- data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
- data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
- data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
- data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
- data/lib/sqreen/legacy/instrumentation.rb +10 -10
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +221 -0
- data/lib/sqreen/legacy/waf_redactions.rb +49 -0
- data/lib/sqreen/log/loggable.rb +2 -1
- data/lib/sqreen/logger.rb +4 -0
- data/lib/sqreen/metrics/base.rb +3 -0
- data/lib/sqreen/metrics_store.rb +22 -12
- data/lib/sqreen/performance_notifications/binned_metrics.rb +8 -2
- data/lib/sqreen/rules.rb +4 -2
- data/lib/sqreen/rules/not_found_cb.rb +2 -0
- data/lib/sqreen/rules/rule_cb.rb +2 -0
- data/lib/sqreen/rules/waf_cb.rb +13 -10
- data/lib/sqreen/runner.rb +75 -8
- data/lib/sqreen/sensitive_data_redactor.rb +19 -31
- data/lib/sqreen/session.rb +51 -43
- data/lib/sqreen/signals/conversions.rb +283 -0
- data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
- data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/weave/legacy/instrumentation.rb +56 -53
- metadata +45 -7
- data/lib/sqreen/backport.rb +0 -9
- data/lib/sqreen/backport/clock_gettime.rb +0 -74
- data/lib/sqreen/backport/original_name.rb +0 -88
| @@ -30,27 +30,5 @@ module Sqreen | |
| 30 30 | 
             
                def klass
         | 
| 31 31 | 
             
                  payload['exception'].class.name
         | 
| 32 32 | 
             
                end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                def to_hash
         | 
| 35 | 
            -
                  exception = payload['exception']
         | 
| 36 | 
            -
                  ev = {
         | 
| 37 | 
            -
                    :klass => exception.class.name,
         | 
| 38 | 
            -
                    :message => exception.message,
         | 
| 39 | 
            -
                    :params => payload['request_params'],
         | 
| 40 | 
            -
                    :time => payload['time'],
         | 
| 41 | 
            -
                    :infos => {
         | 
| 42 | 
            -
                      :client_ip => payload['client_ip'],
         | 
| 43 | 
            -
                    },
         | 
| 44 | 
            -
                    :request => payload['request_infos'],
         | 
| 45 | 
            -
                    :headers => payload['headers'],
         | 
| 46 | 
            -
                    :rule_name => payload['rule_name'],
         | 
| 47 | 
            -
                    :rulespack_id => payload['rulespack_id'],
         | 
| 48 | 
            -
                  }
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  ev[:infos].merge!(payload['infos']) if payload['infos']
         | 
| 51 | 
            -
                  return ev unless exception.backtrace
         | 
| 52 | 
            -
                  ev[:context] = { :backtrace => exception.backtrace.map(&:to_s) }
         | 
| 53 | 
            -
                  ev
         | 
| 54 | 
            -
                end
         | 
| 55 33 | 
             
              end
         | 
| 56 34 | 
             
            end
         | 
| @@ -14,6 +14,10 @@ require 'sqreen/sensitive_data_redactor' | |
| 14 14 | 
             
            module Sqreen
         | 
| 15 15 | 
             
              # When a request is deeemed worthy of being sent to the backend
         | 
| 16 16 | 
             
              class RequestRecord < Sqreen::Event
         | 
| 17 | 
            +
                attr_reader :redactor
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                # @param [Hash] payload
         | 
| 20 | 
            +
                # @param [Sqreen::SensitiveDataRedactor] redactor
         | 
| 17 21 | 
             
                def initialize(payload, redactor = nil)
         | 
| 18 22 | 
             
                  @redactor = redactor
         | 
| 19 23 | 
             
                  super(payload)
         | 
| @@ -23,74 +27,18 @@ module Sqreen | |
| 23 27 | 
             
                  (payload && payload[:observed]) || {}
         | 
| 24 28 | 
             
                end
         | 
| 25 29 |  | 
| 26 | 
            -
                def  | 
| 27 | 
            -
                   | 
| 28 | 
            -
                  if payload[:observed]
         | 
| 29 | 
            -
                    res[:observed] = payload[:observed].dup
         | 
| 30 | 
            -
                    rulespack = nil
         | 
| 31 | 
            -
                    if observed[:attacks]
         | 
| 32 | 
            -
                      res[:observed][:attacks] = observed[:attacks].map do |att|
         | 
| 33 | 
            -
                        natt = att.dup
         | 
| 34 | 
            -
                        rulespack = natt.delete(:rulespack_id) || rulespack
         | 
| 35 | 
            -
                        natt
         | 
| 36 | 
            -
                      end
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
                    if observed[:sqreen_exceptions]
         | 
| 39 | 
            -
                      res[:observed][:sqreen_exceptions] = observed[:sqreen_exceptions].map do |exc|
         | 
| 40 | 
            -
                        nex = exc.dup
         | 
| 41 | 
            -
                        excp = nex.delete(:exception)
         | 
| 42 | 
            -
                        if excp
         | 
| 43 | 
            -
                          nex[:message] = excp.message
         | 
| 44 | 
            -
                          nex[:klass] = excp.class.name
         | 
| 45 | 
            -
                        end
         | 
| 46 | 
            -
                        rulespack = nex.delete(:rulespack_id) || rulespack
         | 
| 47 | 
            -
                        nex
         | 
| 48 | 
            -
                      end
         | 
| 49 | 
            -
                    end
         | 
| 50 | 
            -
                    res[:rulespack_id] = rulespack unless rulespack.nil?
         | 
| 51 | 
            -
                    if observed[:observations]
         | 
| 52 | 
            -
                      res[:observed][:observations] = observed[:observations].map do |cat, key, value, time|
         | 
| 53 | 
            -
                        { :category => cat, :key => key, :value => value, :time => time }
         | 
| 54 | 
            -
                      end
         | 
| 55 | 
            -
                    end
         | 
| 56 | 
            -
                    if observed[:sdk]
         | 
| 57 | 
            -
                      res[:observed][:sdk] = processed_sdk_calls
         | 
| 58 | 
            -
                    end
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
                  res[:local] = payload['local'] if payload['local']
         | 
| 61 | 
            -
                  if payload['request']
         | 
| 62 | 
            -
                    res[:request] = payload['request'].dup
         | 
| 63 | 
            -
                    res[:client_ip] = res[:request].delete(:client_ip) if res[:request][:client_ip]
         | 
| 64 | 
            -
                  else
         | 
| 65 | 
            -
                    res[:request] = {}
         | 
| 66 | 
            -
                  end
         | 
| 67 | 
            -
                  if payload['response']
         | 
| 68 | 
            -
                    res[:response] = payload['response'].dup
         | 
| 69 | 
            -
                  else
         | 
| 70 | 
            -
                    res[:response] = {}
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  res[:request][:parameters] = payload['params'] if payload['params']
         | 
| 74 | 
            -
                  res[:request][:headers] = payload['headers'] if payload['headers']
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  res = Sqreen::EncodingSanitizer.sanitize(res)
         | 
| 30 | 
            +
                def last_identify_args
         | 
| 31 | 
            +
                  return nil unless observed[:sdk]
         | 
| 77 32 |  | 
| 78 | 
            -
                   | 
| 79 | 
            -
                     | 
| 80 | 
            -
                     | 
| 81 | 
            -
                      res[:observed][:attacks] = @redactor.redact_attacks!(res[:observed][:attacks], redacted)
         | 
| 82 | 
            -
                    end
         | 
| 83 | 
            -
                    if redacted.any? && res[:observed] && res[:observed][:sqreen_exceptions]
         | 
| 84 | 
            -
                      res[:observed][:sqreen_exceptions] = @redactor.redact_exceptions!(res[:observed][:sqreen_exceptions], redacted)
         | 
| 85 | 
            -
                    end
         | 
| 33 | 
            +
                  observed[:sdk].reverse_each do |meth, _time, *args|
         | 
| 34 | 
            +
                    next unless meth == :identify
         | 
| 35 | 
            +
                    return args
         | 
| 86 36 | 
             
                  end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                  res
         | 
| 37 | 
            +
                  nil
         | 
| 89 38 | 
             
                end
         | 
| 90 39 |  | 
| 91 | 
            -
                private
         | 
| 92 | 
            -
             | 
| 93 40 | 
             
                def processed_sdk_calls
         | 
| 41 | 
            +
                  return [] unless observed[:sdk]
         | 
| 94 42 | 
             
                  auth_keys = last_identify_id
         | 
| 95 43 |  | 
| 96 44 | 
             
                  observed[:sdk].map do |meth, time, *args|
         | 
| @@ -102,6 +50,8 @@ module Sqreen | |
| 102 50 | 
             
                  end
         | 
| 103 51 | 
             
                end
         | 
| 104 52 |  | 
| 53 | 
            +
                private
         | 
| 54 | 
            +
             | 
| 105 55 | 
             
                def inject_identifiers(args, meth, auth_keys)
         | 
| 106 56 | 
             
                  return args unless meth == :track && auth_keys
         | 
| 107 57 |  | 
| @@ -118,13 +68,8 @@ module Sqreen | |
| 118 68 | 
             
                end
         | 
| 119 69 |  | 
| 120 70 | 
             
                def last_identify_id
         | 
| 121 | 
            -
                   | 
| 122 | 
            -
             | 
| 123 | 
            -
                  observed[:sdk].reverse_each do |meth, _time, *args|
         | 
| 124 | 
            -
                    next unless meth == :identify
         | 
| 125 | 
            -
                    return args.first if args.respond_to? :first
         | 
| 126 | 
            -
                  end
         | 
| 127 | 
            -
                  nil
         | 
| 71 | 
            +
                  args = last_identify_args
         | 
| 72 | 
            +
                  args.first if args.respond_to? :first
         | 
| 128 73 | 
             
                end
         | 
| 129 74 | 
             
              end
         | 
| 130 75 | 
             
            end
         | 
| @@ -58,12 +58,20 @@ module Sqreen | |
| 58 58 | 
             
                  Sqreen.log.debug { "close_request_record called. observed_items: #{observed_items}" }
         | 
| 59 59 |  | 
| 60 60 | 
             
                  clean_request_record if observed_items.nil?
         | 
| 61 | 
            -
                  if only_metric_observation
         | 
| 61 | 
            +
                  if Sqreen.features['use_signals'] || only_metric_observation
         | 
| 62 62 | 
             
                    push_metrics(observations_queue, queue)
         | 
| 63 | 
            -
                    return clean_request_record
         | 
| 64 63 | 
             
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  if only_metric_observation
         | 
| 66 | 
            +
                    clean_request_record
         | 
| 67 | 
            +
                    return
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  # signals require request section to be present
         | 
| 71 | 
            +
                  payload_requests << 'request'
         | 
| 65 72 | 
             
                  payload = payload_creator.payload(payload_requests)
         | 
| 66 73 | 
             
                  payload[:observed] = observed_items
         | 
| 74 | 
            +
             | 
| 67 75 | 
             
                  queue.push create_request_record(payload)
         | 
| 68 76 | 
             
                  clean_request_record
         | 
| 69 77 | 
             
                end
         | 
| @@ -79,10 +87,13 @@ module Sqreen | |
| 79 87 | 
             
                  @redactor ||= SensitiveDataRedactor.from_config
         | 
| 80 88 | 
             
                end
         | 
| 81 89 |  | 
| 90 | 
            +
                # pushes metric observations to the observations queue
         | 
| 91 | 
            +
                # and clears the list for the request record
         | 
| 82 92 | 
             
                def push_metrics(observations_queue, event_queue)
         | 
| 83 93 | 
             
                  observed_items[:observations].each do |obs|
         | 
| 84 94 | 
             
                    observations_queue.push obs
         | 
| 85 95 | 
             
                  end
         | 
| 96 | 
            +
                  observed_items[:observations] = []
         | 
| 86 97 | 
             
                  return unless observations_queue.size > MAX_OBS_QUEUE_LENGTH / 2
         | 
| 87 98 | 
             
                  event_queue.push Sqreen::METRICS_EVENT
         | 
| 88 99 | 
             
                end
         | 
    
        data/lib/sqreen/graft/call.rb
    CHANGED
    
    | @@ -98,53 +98,66 @@ module Sqreen | |
| 98 98 | 
             
                    Process.clock_gettime(Process::CLOCK_MONOTONIC)
         | 
| 99 99 | 
             
                  end
         | 
| 100 100 |  | 
| 101 | 
            -
                  attr_reader :tag
         | 
| 101 | 
            +
                  attr_reader :tag, :size, :duration
         | 
| 102 102 |  | 
| 103 103 | 
             
                  def initialize(tag, &block)
         | 
| 104 104 | 
             
                    @tag = tag
         | 
| 105 | 
            -
                    @blips = []
         | 
| 106 105 | 
             
                    @block = block
         | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
                  def duration
         | 
| 110 | 
            -
                    @blips.each_with_index.reduce(0) { |a, (e, i)| i.even? ? a - e : a + e }
         | 
| 106 | 
            +
                    @duration = 0
         | 
| 107 | 
            +
                    @size = 0
         | 
| 111 108 | 
             
                  end
         | 
| 112 109 |  | 
| 113 110 | 
             
                  def elapsed
         | 
| 114 | 
            -
                    @ | 
| 111 | 
            +
                    @duration + Timer.read
         | 
| 115 112 | 
             
                  end
         | 
| 116 113 |  | 
| 117 114 | 
             
                  def ignore
         | 
| 118 | 
            -
                    @ | 
| 115 | 
            +
                    @size += 1
         | 
| 116 | 
            +
                    @duration += Timer.read
         | 
| 119 117 | 
             
                    yield(self)
         | 
| 120 118 | 
             
                  ensure
         | 
| 121 | 
            -
                    @ | 
| 119 | 
            +
                    @size += 1
         | 
| 120 | 
            +
                    @duration -= Timer.read
         | 
| 122 121 | 
             
                  end
         | 
| 123 122 |  | 
| 124 | 
            -
                  def measure
         | 
| 125 | 
            -
                     | 
| 123 | 
            +
                  def measure(opts = nil)
         | 
| 124 | 
            +
                    now = Timer.read
         | 
| 125 | 
            +
                    ignore = opts[:ignore] if opts
         | 
| 126 | 
            +
                    if ignore
         | 
| 127 | 
            +
                      ignore.size += 1
         | 
| 128 | 
            +
                      ignore.duration += now
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
                    @size += 1
         | 
| 131 | 
            +
                    @duration -= now
         | 
| 126 132 | 
             
                    yield(self)
         | 
| 127 133 | 
             
                  ensure
         | 
| 128 | 
            -
                     | 
| 134 | 
            +
                    now = Timer.read
         | 
| 135 | 
            +
                    if ignore
         | 
| 136 | 
            +
                      ignore.size += 1
         | 
| 137 | 
            +
                      ignore.duration -= now
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                    @size += 1
         | 
| 140 | 
            +
                    @duration += now
         | 
| 129 141 | 
             
                    @block.call(self) if @block
         | 
| 130 | 
            -
                    Sqreen::Graft.logger.debug { "#{@tag}: time=%.03fus" % (duration * 1_000_000) }
         | 
| 131 142 | 
             
                  end
         | 
| 132 143 |  | 
| 133 144 | 
             
                  def start
         | 
| 134 | 
            -
                    @ | 
| 145 | 
            +
                    @size += 1
         | 
| 146 | 
            +
                    @duration -= Timer.read
         | 
| 135 147 | 
             
                  end
         | 
| 136 148 |  | 
| 137 149 | 
             
                  def stop
         | 
| 138 | 
            -
                    @ | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
                  def size
         | 
| 142 | 
            -
                    @blips.size
         | 
| 150 | 
            +
                    @size += 1
         | 
| 151 | 
            +
                    @duration += Timer.read
         | 
| 143 152 | 
             
                  end
         | 
| 144 153 |  | 
| 145 154 | 
             
                  def to_s
         | 
| 146 155 | 
             
                    "#{@tag}: time=%.03fus" % (duration * 1_000_000)
         | 
| 147 156 | 
             
                  end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  protected
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                  attr_writer :size, :duration
         | 
| 148 161 | 
             
                end
         | 
| 149 162 | 
             
              end
         | 
| 150 163 | 
             
            end
         | 
| @@ -21,7 +21,7 @@ module Sqreen | |
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 23 | 
             
                  def call(*args, &block)
         | 
| 24 | 
            -
                    Sqreen::Graft.logger.debug { "[#{Process.pid}] Callback #{@name} disabled:#{disabled?}" }
         | 
| 24 | 
            +
                    # Sqreen::Graft.logger.debug { "[#{Process.pid}] Callback #{@name} disabled:#{disabled?}" } if Sqreen::Graft.logger.debug?
         | 
| 25 25 | 
             
                    return if @disabled
         | 
| 26 26 | 
             
                    @block.call(*args, &block)
         | 
| 27 27 | 
             
                  end
         | 
    
        data/lib/sqreen/graft/hook.rb
    CHANGED
    
    | @@ -46,27 +46,31 @@ module Sqreen | |
| 46 46 | 
             
                  end
         | 
| 47 47 |  | 
| 48 48 | 
             
                  def before(tag = nil, opts = {}, &block)
         | 
| 49 | 
            -
                    return @before | 
| 49 | 
            +
                    return @before if block.nil?
         | 
| 50 50 |  | 
| 51 51 | 
             
                    @before << Callback.new(callback_name(:before, tag), opts, &block)
         | 
| 52 | 
            +
                    @before.sort_by!(&:rank)
         | 
| 52 53 | 
             
                  end
         | 
| 53 54 |  | 
| 54 55 | 
             
                  def after(tag = nil, opts = {}, &block)
         | 
| 55 | 
            -
                    return @after | 
| 56 | 
            +
                    return @after if block.nil?
         | 
| 56 57 |  | 
| 57 58 | 
             
                    @after << Callback.new(callback_name(:after, tag), opts, &block)
         | 
| 59 | 
            +
                    @after.sort_by!(&:rank)
         | 
| 58 60 | 
             
                  end
         | 
| 59 61 |  | 
| 60 62 | 
             
                  def raised(tag = nil, opts = {}, &block)
         | 
| 61 | 
            -
                    return @raised | 
| 63 | 
            +
                    return @raised if block.nil?
         | 
| 62 64 |  | 
| 63 65 | 
             
                    @raised << Callback.new(callback_name(:raised, tag), opts, &block)
         | 
| 66 | 
            +
                    @raised.sort_by!(&:rank)
         | 
| 64 67 | 
             
                  end
         | 
| 65 68 |  | 
| 66 69 | 
             
                  def ensured(tag = nil, opts = {}, &block)
         | 
| 67 | 
            -
                    return @ensured | 
| 70 | 
            +
                    return @ensured if block.nil?
         | 
| 68 71 |  | 
| 69 72 | 
             
                    @ensured << Callback.new(callback_name(:ensured, tag), opts, &block)
         | 
| 73 | 
            +
                    @ensured.sort_by!(&:rank)
         | 
| 70 74 | 
             
                  end
         | 
| 71 75 |  | 
| 72 76 | 
             
                  def depends_on(&block)
         | 
| @@ -112,6 +116,13 @@ module Sqreen | |
| 112 116 | 
             
                  end
         | 
| 113 117 |  | 
| 114 118 | 
             
                  def self.wrapper(hook)
         | 
| 119 | 
            +
                    timed_hooks_proc = proc do |t|
         | 
| 120 | 
            +
                      Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_hooks] << t
         | 
| 121 | 
            +
                    end
         | 
| 122 | 
            +
                    timed_callbacks_proc = proc do |t|
         | 
| 123 | 
            +
                      Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timed_callbacks] << t
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 115 126 | 
             
                    Proc.new do |*args, &block|
         | 
| 116 127 | 
             
                      if Thread.current[:sqreen_hook_entered] || Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:time_budget_expended]
         | 
| 117 128 | 
             
                        if hook.point.super?
         | 
| @@ -121,10 +132,12 @@ module Sqreen | |
| 121 132 | 
             
                        end
         | 
| 122 133 | 
             
                      end
         | 
| 123 134 |  | 
| 124 | 
            -
                       | 
| 125 | 
            -
             | 
| 126 | 
            -
                       | 
| 127 | 
            -
             | 
| 135 | 
            +
                      hook_point_super = hook.point.super?
         | 
| 136 | 
            +
                      logger = Sqreen::Graft.logger
         | 
| 137 | 
            +
                      logger_debug = Sqreen::Graft.logger.debug?
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                      Timer.new(hook.point, &timed_hooks_proc).measure do |chrono|
         | 
| 140 | 
            +
                        logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} caller:#{Kernel.caller[2].inspect}" } if logger_debug
         | 
| 128 141 |  | 
| 129 142 | 
             
                        budget = Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:time_budget]
         | 
| 130 143 | 
             
                        timer = Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:timer] if budget
         | 
| @@ -143,37 +156,29 @@ module Sqreen | |
| 143 156 | 
             
                          # TODO: TimedHookCall TimedCallbackCall
         | 
| 144 157 | 
             
                          # TODO: TimeBoundHookCall TimeBoundCallbackCall TimeBoundFlow?
         | 
| 145 158 |  | 
| 146 | 
            -
                           | 
| 147 | 
            -
                             | 
| 148 | 
            -
             | 
| 149 | 
            -
                             | 
| 150 | 
            -
                               | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
                                 | 
| 154 | 
            -
                                unless remaining > 0
         | 
| 155 | 
            -
                                  Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 156 | 
            -
                                  next
         | 
| 157 | 
            -
                                end
         | 
| 159 | 
            +
                          hook.before.each do |c|
         | 
| 160 | 
            +
                            next if c.ignore && c.ignore.call
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                            if timer && !c.mandatory
         | 
| 163 | 
            +
                              remaining = budget - timer.elapsed
         | 
| 164 | 
            +
                              unless remaining > 0
         | 
| 165 | 
            +
                                Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 166 | 
            +
                                next
         | 
| 158 167 | 
             
                              end
         | 
| 168 | 
            +
                            end
         | 
| 159 169 |  | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 163 | 
            -
                                end.measure do
         | 
| 164 | 
            -
                                  before_chrono.ignore do
         | 
| 165 | 
            -
                                    c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passed), ball)
         | 
| 166 | 
            -
                                  end
         | 
| 167 | 
            -
                                end
         | 
| 170 | 
            +
                            flow = catch(Ball.new) do |ball|
         | 
| 171 | 
            +
                              Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
         | 
| 172 | 
            +
                                c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passed), ball)
         | 
| 168 173 | 
             
                              end
         | 
| 174 | 
            +
                            end
         | 
| 169 175 |  | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
                          end
         | 
| 176 | 
            +
                            next unless c.flow && flow.is_a?(Flow)
         | 
| 177 | 
            +
                            hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
         | 
| 178 | 
            +
                            hooked_call.args_pass = flow.args and hooked_call.args_passing = true if flow.args?
         | 
| 179 | 
            +
                            hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
         | 
| 180 | 
            +
                            break if flow.break?
         | 
| 181 | 
            +
                          end unless hook.disabled?
         | 
| 177 182 |  | 
| 178 183 | 
             
                          raise hooked_call.raise if hooked_call.raising
         | 
| 179 184 | 
             
                          return hooked_call.return if hooked_call.returning
         | 
| @@ -184,7 +189,7 @@ module Sqreen | |
| 184 189 |  | 
| 185 190 | 
             
                        begin
         | 
| 186 191 | 
             
                          chrono.ignore do
         | 
| 187 | 
            -
                            if  | 
| 192 | 
            +
                            if hook_point_super
         | 
| 188 193 | 
             
                              hooked_call.returned = super(*(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
         | 
| 189 194 | 
             
                            else
         | 
| 190 195 | 
             
                              hooked_call.returned = hook.point.apply(hooked_call.instance, 'sqreen_hook', *(hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed), &block)
         | 
| @@ -195,40 +200,32 @@ module Sqreen | |
| 195 200 | 
             
                          Thread.current[:sqreen_hook_entered] = true
         | 
| 196 201 | 
             
                          hooked_call.raised = e
         | 
| 197 202 |  | 
| 198 | 
            -
                           | 
| 203 | 
            +
                          logger.debug { "[#{Process.pid}] Hook #{hook.point} disabled:#{hook.disabled?} exception:#{e}" } if logger_debug
         | 
| 199 204 | 
             
                          raise if hook.raised.empty?
         | 
| 200 205 |  | 
| 201 | 
            -
                           | 
| 202 | 
            -
                             | 
| 203 | 
            -
             | 
| 204 | 
            -
                             | 
| 205 | 
            -
                               | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
                                 | 
| 209 | 
            -
                                unless remaining > 0
         | 
| 210 | 
            -
                                  Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 211 | 
            -
                                  next
         | 
| 212 | 
            -
                                end
         | 
| 206 | 
            +
                          hook.raised.each do |c|
         | 
| 207 | 
            +
                            next if c.ignore && c.ignore.call
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                            if timer && !c.mandatory
         | 
| 210 | 
            +
                              remaining = budget - timer.elapsed
         | 
| 211 | 
            +
                              unless remaining > 0
         | 
| 212 | 
            +
                                Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 213 | 
            +
                                next
         | 
| 213 214 | 
             
                              end
         | 
| 215 | 
            +
                            end
         | 
| 214 216 |  | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
                                end.measure do
         | 
| 219 | 
            -
                                  raised_chrono.ignore do
         | 
| 220 | 
            -
                                    c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, hooked_call.raised), ball)
         | 
| 221 | 
            -
                                  end
         | 
| 222 | 
            -
                                end
         | 
| 217 | 
            +
                            flow = catch(Ball.new) do |ball|
         | 
| 218 | 
            +
                              Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
         | 
| 219 | 
            +
                                c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, hooked_call.raised), ball)
         | 
| 223 220 | 
             
                              end
         | 
| 221 | 
            +
                            end
         | 
| 224 222 |  | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 231 | 
            -
                          end
         | 
| 223 | 
            +
                            next unless c.flow && flow.is_a?(Flow)
         | 
| 224 | 
            +
                            hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
         | 
| 225 | 
            +
                            hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
         | 
| 226 | 
            +
                            hooked_call.retrying = true if flow.retry?
         | 
| 227 | 
            +
                            break if flow.break?
         | 
| 228 | 
            +
                          end unless hook.disabled?
         | 
| 232 229 |  | 
| 233 230 | 
             
                          retry if hooked_call.retrying
         | 
| 234 231 | 
             
                          raise hooked_call.raise if hooked_call.raising
         | 
| @@ -238,72 +235,56 @@ module Sqreen | |
| 238 235 | 
             
                          timer.start if timer
         | 
| 239 236 | 
             
                          Thread.current[:sqreen_hook_entered] = true
         | 
| 240 237 |  | 
| 241 | 
            -
                           | 
| 242 | 
            -
                             | 
| 243 | 
            -
             | 
| 244 | 
            -
                             | 
| 245 | 
            -
                               | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
                                 | 
| 249 | 
            -
                                unless remaining > 0
         | 
| 250 | 
            -
                                  Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 251 | 
            -
                                  next
         | 
| 252 | 
            -
                                end
         | 
| 238 | 
            +
                          hook.after.each do |c|
         | 
| 239 | 
            +
                            next if c.ignore && c.ignore.call
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                            if timer && !c.mandatory
         | 
| 242 | 
            +
                              remaining = budget - timer.elapsed
         | 
| 243 | 
            +
                              unless remaining > 0
         | 
| 244 | 
            +
                                Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 245 | 
            +
                                next
         | 
| 253 246 | 
             
                              end
         | 
| 247 | 
            +
                            end
         | 
| 254 248 |  | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
                                end.measure do
         | 
| 259 | 
            -
                                  after_chrono.ignore do
         | 
| 260 | 
            -
                                    c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, nil, hooked_call.returned), ball)
         | 
| 261 | 
            -
                                  end
         | 
| 262 | 
            -
                                end
         | 
| 249 | 
            +
                            flow = catch(Ball.new) do |ball|
         | 
| 250 | 
            +
                              Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
         | 
| 251 | 
            +
                                c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, nil, hooked_call.returned), ball)
         | 
| 263 252 | 
             
                              end
         | 
| 253 | 
            +
                            end
         | 
| 264 254 |  | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 270 | 
            -
                          end
         | 
| 255 | 
            +
                            next unless c.flow && flow.is_a?(Flow)
         | 
| 256 | 
            +
                            hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
         | 
| 257 | 
            +
                            hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
         | 
| 258 | 
            +
                            break if flow.break?
         | 
| 259 | 
            +
                          end unless hook.disabled?
         | 
| 271 260 |  | 
| 272 261 | 
             
                          raise hooked_call.raise if hooked_call.raising
         | 
| 273 262 | 
             
                          return hooked_call.returning ? hooked_call.return : hooked_call.returned
         | 
| 274 263 | 
             
                        ensure
         | 
| 275 264 | 
             
                          # TODO: timer.start if someone has thrown?
         | 
| 276 265 |  | 
| 277 | 
            -
                           | 
| 278 | 
            -
                             | 
| 279 | 
            -
             | 
| 280 | 
            -
                             | 
| 281 | 
            -
                               | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 284 | 
            -
                                 | 
| 285 | 
            -
                                unless remaining > 0
         | 
| 286 | 
            -
                                  Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 287 | 
            -
                                  next
         | 
| 288 | 
            -
                                end
         | 
| 266 | 
            +
                          hook.ensured.each do |c|
         | 
| 267 | 
            +
                            next if c.ignore && c.ignore.call
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                            if timer && !c.mandatory
         | 
| 270 | 
            +
                              remaining = budget - timer.elapsed
         | 
| 271 | 
            +
                              unless remaining > 0
         | 
| 272 | 
            +
                                Thread.current[:sqreen_http_request] && Thread.current[:sqreen_http_request][:skipped_callbacks] << c && Thread.current[:sqreen_http_request][:time_budget_expended] = true
         | 
| 273 | 
            +
                                next
         | 
| 289 274 | 
             
                              end
         | 
| 275 | 
            +
                            end
         | 
| 290 276 |  | 
| 291 | 
            -
             | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
                                end.measure do
         | 
| 295 | 
            -
                                  ensured_chrono.ignore do
         | 
| 296 | 
            -
                                    c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, nil, hooked_call.returned), ball)
         | 
| 297 | 
            -
                                  end
         | 
| 298 | 
            -
                                end
         | 
| 277 | 
            +
                            flow = catch(Ball.new) do |ball|
         | 
| 278 | 
            +
                              Timer.new(c.name, &timed_callbacks_proc).measure(ignore: chrono) do
         | 
| 279 | 
            +
                                c.call(CallbackCall.new(c, remaining, hooked_call.instance, hooked_call.args_passing ? hooked_call.args_pass : hooked_call.args_passed, nil, hooked_call.returned), ball)
         | 
| 299 280 | 
             
                              end
         | 
| 281 | 
            +
                            end
         | 
| 300 282 |  | 
| 301 | 
            -
             | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 304 | 
            -
             | 
| 305 | 
            -
             | 
| 306 | 
            -
                          end
         | 
| 283 | 
            +
                            next unless c.flow && flow.is_a?(Flow)
         | 
| 284 | 
            +
                            hooked_call.raise = flow.raise and hooked_call.raising = true if flow.raise?
         | 
| 285 | 
            +
                            hooked_call.return = flow.return and hooked_call.returning = true if flow.return?
         | 
| 286 | 
            +
                            break if flow.break?
         | 
| 287 | 
            +
                          end unless hook.disabled?
         | 
| 307 288 |  | 
| 308 289 | 
             
                          Thread.current[:sqreen_hook_entered] = false
         | 
| 309 290 | 
             
                          timer.stop if timer
         |