sqreen 0.8.11465220943 → 1.0.0.pre1480953244

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
  SHA1:
3
- metadata.gz: 39dacf780c2f8a4e5a3c80ed2295f31bbaa6185a
4
- data.tar.gz: 0ed786d7f9437a8daff74d03112b699a0ede8aab
3
+ metadata.gz: 9c8f5f54c0af763465089699d22bef3c53346dc9
4
+ data.tar.gz: e0015e87e9c6e62f9859224e7eb47bb193ea04c4
5
5
  SHA512:
6
- metadata.gz: 8c74afdd056d0c52b3d524454cb0fb25cda1cb55ec5f5696eeab53095df3673b3043535da5b1937a86f8d918094504d7cc6ff24b660a2369e481ca263a045c5a
7
- data.tar.gz: 0a5fc6dd89edf3fbcbd45743b1b82f42adc3e96929f5f52df59ed9f54f4c8aff6434d1ed08046f41d99ad79a85e07d668373185d07c2a2577dc4b75f40b06b58
6
+ metadata.gz: 71533d2617f9a4b06d491a87b394f3da3ec0dd1c6019179d92155433799ddd19d32c3f82249c032ee208239bb252c7ca78aa1fde03bbf6b28f422cbc363400d8
7
+ data.tar.gz: 607a0981e332784768e172e25721c7edc6f11632f570da2cd955d18e2c5a6059037b14c959fa9a9a3a92100c85751d3325bddaf858027d133cda9aa2aeb1506d
@@ -26,7 +26,6 @@ Sqreen.framework.on_start do |framework|
26
26
  prevent_startup = Sqreen.framework.prevent_startup
27
27
  if !prevent_startup
28
28
  runner = Sqreen::Runner.new(configuration, framework)
29
- runner.do_heartbeat
30
29
  runner.run_watcher
31
30
  else
32
31
  Sqreen.log.debug("#{prevent_startup} prevented Sqreen startup")
@@ -5,7 +5,8 @@ require 'strscan'
5
5
 
6
6
  # the value located at the given binding
7
7
  class BindingAccessor
8
- attr_reader :path, :expression, :convert
8
+ PathElem = Struct.new(:kind, :value)
9
+ attr_reader :path, :expression
9
10
 
10
11
  # Expression to be accessed
11
12
  # @param expression [String] expression to read
@@ -30,6 +31,18 @@ class BindingAccessor
30
31
 
31
32
  protected
32
33
 
34
+ STRING_KIND = 'string'.freeze
35
+ SYMBOL_KIND = 'symbol'.freeze
36
+ INTEGER_KIND = 'integer'.freeze
37
+ LOCAL_VAR_KIND = 'local-variable'.freeze
38
+ INSTANCE_VAR_KIND = 'instance-variable'.freeze
39
+ CLASS_VAR_KIND = 'class-variable'.freeze
40
+ GLOBAL_VAR_KIND = 'global-variable'.freeze
41
+ CONSTANT_KIND = 'constant'.freeze
42
+ METHOD_KIND = 'method'.freeze
43
+ INDEX_KIND = 'index'.freeze
44
+ SQREEN_VAR_KIND = 'sqreen-variable'.freeze
45
+
33
46
  if binding.respond_to?(:local_variable_get)
34
47
  def get_local(name, bind)
35
48
  bind.local_variable_get(name)
@@ -42,28 +55,28 @@ class BindingAccessor
42
55
 
43
56
  def resolve_component(current_value, component, binding, env)
44
57
  case component[:kind]
45
- when 'string', 'symbol', 'integer'
58
+ when STRING_KIND, SYMBOL_KIND, INTEGER_KIND
46
59
  component[:value]
47
- when 'local-variable'
48
- get_local(component[:name], binding)
49
- when 'instance-variable'
50
- current_value.instance_variable_get("@#{component[:name]}")
51
- when 'class-variable'
52
- current_value.class.class_variable_get("@@#{component[:name]}")
53
- when 'global-variable'
54
- instance_eval("$#{component[:name]}")
55
- when 'constant'
60
+ when LOCAL_VAR_KIND
61
+ get_local(component[:value], binding)
62
+ when INSTANCE_VAR_KIND
63
+ current_value.instance_variable_get("@#{component[:value]}")
64
+ when CLASS_VAR_KIND
65
+ current_value.class.class_variable_get("@@#{component[:value]}")
66
+ when GLOBAL_VAR_KIND
67
+ instance_eval("$#{component[:value]}")
68
+ when CONSTANT_KIND
56
69
  if current_value
57
- current_value.const_get(component[:name].to_s)
70
+ current_value.const_get(component[:value].to_s)
58
71
  else
59
- Object.const_get(component[:name].to_s)
72
+ Object.const_get(component[:value].to_s)
60
73
  end
61
- when 'method'
62
- current_value.send(component[:name])
63
- when 'index'
64
- current_value[component[:index]]
65
- when 'sqreen-variable'
66
- resolve_sqreen_variable(component[:name], *env)
74
+ when METHOD_KIND
75
+ current_value.send(component[:value])
76
+ when INDEX_KIND
77
+ current_value[component[:value]]
78
+ when SQREEN_VAR_KIND
79
+ resolve_sqreen_variable(component[:value], *env)
67
80
  else
68
81
  raise "Do not know how to handle this component #{component.inspect}"
69
82
  end
@@ -93,7 +106,7 @@ class BindingAccessor
93
106
  @path.push scalar
94
107
  return
95
108
  end
96
- if @path.size == 0
109
+ if @path.empty?
97
110
  scan_push_variable
98
111
  else
99
112
  scan_push_method
@@ -102,16 +115,17 @@ class BindingAccessor
102
115
  scan_push_more_constant if @scan.scan(/\./).nil?
103
116
  raise error_state('Scan stuck') if @scan.pos == pos
104
117
  end
118
+ ensure
119
+ @scan = nil
105
120
  end
106
121
 
107
122
  def scan_scalar
108
- case
109
- when @scan.scan(/\d+/)
110
- return { :value => @scan[0].to_i, :kind => 'integer' }
111
- when @scan.scan(/:(\w+)/)
112
- return { :value => @scan[1].to_sym, :kind => 'symbol' }
113
- when @scan.scan(/'((?:\\.|[^\\'])*)'/)
114
- return { :value => @scan[1], :kind => 'string' }
123
+ if @scan.scan(/\d+/)
124
+ return PathElem.new(INTEGER_KIND, @scan[0].to_i)
125
+ elsif @scan.scan(/:(\w+)/)
126
+ return PathElem.new(SYMBOL_KIND, @scan[1].to_sym)
127
+ elsif @scan.scan(/'((?:\\.|[^\\'])*)'/)
128
+ return PathElem.new(STRING_KIND, @scan[1])
115
129
  end
116
130
  end
117
131
 
@@ -119,11 +133,11 @@ class BindingAccessor
119
133
  '[\w\u0080-\u{10ffff}]'
120
134
  else
121
135
  '[\w\x80-\xFF]'
122
- end
136
+ end
123
137
 
124
138
  def scan_push_constant
125
139
  return unless @scan.scan(/([A-Z]#{RUBY_IDENTIFIER_CHAR}+)/)
126
- @path << { :name => @scan[1], :kind => 'constant' }
140
+ @path << PathElem.new(CONSTANT_KIND, @scan[1])
127
141
  end
128
142
 
129
143
  def scan_push_more_constant
@@ -133,30 +147,28 @@ class BindingAccessor
133
147
  end
134
148
 
135
149
  def scan_push_variable
136
- case
137
- when @scan.scan(/\$(#{RUBY_IDENTIFIER_CHAR}+)/)
138
- return @path << { :name => @scan[1], :kind => 'global-variable' }
139
- when @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/)
140
- return @path << { :name => @scan[1], :kind => 'class-variable' }
141
- when @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/)
142
- return @path << { :name => @scan[1], :kind => 'instance-variable' }
143
- when @scan.scan(/#\.(\w+)/)
144
- return @path << { :name => @scan[1], :kind => 'sqreen-variable' }
145
- when scan_push_constant
150
+ if @scan.scan(/\$(#{RUBY_IDENTIFIER_CHAR}+)/)
151
+ return @path << PathElem.new(GLOBAL_VAR_KIND, @scan[1])
152
+ elsif @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/)
153
+ return @path << PathElem.new(CLASS_VAR_KIND, @scan[1])
154
+ elsif @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/)
155
+ return @path << PathElem.new(INSTANCE_VAR_KIND, @scan[1])
156
+ elsif @scan.scan(/#\.(\w+)/)
157
+ return @path << PathElem.new(SQREEN_VAR_KIND, @scan[1])
158
+ elsif scan_push_constant
146
159
  return
147
- when @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/u)
148
- return @path << { :name => @scan[1], :kind => 'local-variable' }
160
+ elsif @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/u)
161
+ return @path << PathElem.new(LOCAL_VAR_KIND, @scan[1])
149
162
  end
150
163
  end
151
164
 
152
165
  def scan_push_method
153
- case
154
- when @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/)
155
- return @path << { :name => @scan[1], :kind => 'class-variable' }
156
- when @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/)
157
- return @path << { :name => @scan[1], :kind => 'instance-variable' }
158
- when @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/)
159
- return @path << { :name => @scan[1], :kind => 'method' }
166
+ if @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/)
167
+ return @path << PathElem.new(CLASS_VAR_KIND, @scan[1])
168
+ elsif @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/)
169
+ return @path << PathElem.new(INSTANCE_VAR_KIND, @scan[1])
170
+ elsif @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/)
171
+ return @path << PathElem.new(METHOD_KIND, @scan[1])
160
172
  end
161
173
  end
162
174
 
@@ -165,7 +177,7 @@ class BindingAccessor
165
177
  scalar = scan_scalar
166
178
  raise error_state('Invalid index') unless scalar
167
179
  raise error_state('Unfinished index') unless @scan.scan(/\]/)
168
- @path << { :kind => 'index', :index => scalar[:value] }
180
+ @path << PathElem.new(INDEX_KIND, scalar[:value])
169
181
  end
170
182
  end
171
183
 
@@ -30,11 +30,15 @@ class ConditionEvaluator
30
30
  # @params hash [Hash] Hash to search into
31
31
  # @params min_value_size [Fixnum] to compare against
32
32
  def self.hash_val_include?(value, hash, min_value_size, rem = 10)
33
- return false if rem <= 0
34
- hash.any? do |_k, hval|
33
+ return true if rem <= 0
34
+ vals = hash
35
+ vals = hash.values if hash.is_a?(Hash)
36
+
37
+ vals.any? do |hval|
35
38
  case hval
36
- when Hash
37
- ConditionEvaluator.hash_val_include?(value, hval, min_value_size, rem - 1)
39
+ when Hash, Array
40
+ ConditionEvaluator.hash_val_include?(value, hval,
41
+ min_value_size, rem - 1)
38
42
  when NilClass
39
43
  false
40
44
  else
@@ -42,11 +46,11 @@ class ConditionEvaluator
42
46
  false
43
47
  else
44
48
  v = hval.to_s
45
- if v.size < min_value_size
46
- false
47
- else
48
- ConditionEvaluator.str_include?(value.to_s, v)
49
- end
49
+ if v.size < min_value_size
50
+ false
51
+ else
52
+ ConditionEvaluator.str_include?(value.to_s, v)
53
+ end
50
54
  end
51
55
  end
52
56
  end
@@ -91,6 +95,7 @@ class ConditionEvaluator
91
95
 
92
96
  def compile_expr(exp, rem)
93
97
  return exp if exp == true || exp == false
98
+ return true if exp.empty?
94
99
  raise(Sqreen::Exception, 'too deep call detected') if rem <= 0
95
100
  h = {}
96
101
  exp.each do |op, values|
@@ -140,9 +145,9 @@ class ConditionEvaluator
140
145
 
141
146
  def evaluate_expr(exp, rem, *args)
142
147
  return exp if exp == true || exp == false
148
+ return true if exp.empty?
143
149
  raise(Sqreen::Exception, 'too deep call detected') if rem <= 0
144
- bool = nil
145
- exp.each do |op, values|
150
+ exp.all? do |op, values|
146
151
  res = values.map do |v|
147
152
  case v
148
153
  when Hash
@@ -190,7 +195,7 @@ class ConditionEvaluator
190
195
  # FIXME: this should be check in compile
191
196
  raise(Sqreen::Exception, "unknown op #{op})")
192
197
  end
198
+ bool
193
199
  end
194
- bool
195
200
  end
196
201
  end
@@ -18,7 +18,8 @@ module Sqreen
18
18
  next if conds.respond_to?(:empty?) && conds.empty?
19
19
  next unless base.method_defined?(cb)
20
20
  send("#{cb}_conditions=", ConditionEvaluator.new(conds))
21
- next if base.instance_variable_get("@conditional_hooked_#{cb}")
21
+ defd = base.instance_variable_defined?("@conditional_hooked_#{cb}")
22
+ next if defd && base.instance_variable_get("@conditional_hooked_#{cb}")
22
23
  base.send(:alias_method, "#{cb}_without_conditions", cb)
23
24
  base.send(:alias_method, cb, "#{cb}_with_conditions")
24
25
  base.instance_variable_set("@conditional_hooked_#{cb}", true)
@@ -42,6 +42,8 @@ module Sqreen
42
42
  :default => nil },
43
43
  { :env => :SQREEN_REPORT_PERF_NR, :name => :report_perf_newrelic,
44
44
  :default => false },
45
+ { :env => :SQREEN_INITIAL_FEATURES, :name => :initial_features,
46
+ :default => nil },
45
47
 
46
48
  ].freeze
47
49
 
@@ -29,11 +29,11 @@ module Sqreen
29
29
  end
30
30
 
31
31
  def drain
32
- post_batch
32
+ post_batch unless current_batch.empty?
33
33
  end
34
34
 
35
35
  def tick
36
- post_batch if current_batch.size > 0 && stale?
36
+ post_batch if !current_batch.empty? && stale?
37
37
  end
38
38
 
39
39
  protected
@@ -29,7 +29,7 @@ module Sqreen
29
29
 
30
30
  def time
31
31
  return nil unless payload['local']
32
- payload['local']['time'].to_s
32
+ payload['local']['time']
33
33
  end
34
34
 
35
35
  def backtrace
@@ -9,6 +9,15 @@ module Sqreen
9
9
  class GenericFramework
10
10
  attr_accessor :sqreen_configuration
11
11
 
12
+ def initialize
13
+ if defined?(Rack::Builder)
14
+ hook_rack_builder
15
+ else
16
+ to_app_done(Process.pid)
17
+ end
18
+ end
19
+
20
+
12
21
  # What kind of database is this
13
22
  def db_settings(_options = {})
14
23
  raise Sqreen::NotImplementedYet
@@ -97,21 +106,23 @@ module Sqreen
97
106
 
98
107
  # Instrument with our rules when the framework as finished loading
99
108
  def instrument_when_ready!(instrumentor, rules)
100
- done = false
101
- # FIXME: why is this called twice
102
- unless defined?(Rack::Builder)
103
- done = true
104
- return
109
+ wait_for_to_app do
110
+ instrumentor.instrument!(rules, self)
105
111
  end
106
- cb = Sqreen::RunWhenCalledCB.new(Rack::Builder, :to_app) do
107
- if done
108
- Sqreen.log.debug('Already instrumented to_app')
109
- else
110
- instrumentor.instrument!(rules, self)
111
- done = true
112
- end
113
- end
114
- instrumentor.add_callback(cb)
112
+ end
113
+
114
+ def to_app_done(val)
115
+ return if @to_app_done
116
+ @to_app_done = val
117
+ return unless @wait
118
+ @wait.each(&:call)
119
+ @wait.clear
120
+ end
121
+
122
+ def wait_for_to_app(&block)
123
+ yield && return if @to_app_done
124
+ @wait ||= []
125
+ @wait << block
115
126
  end
116
127
 
117
128
  # Does the parameters include this value
@@ -217,6 +228,33 @@ module Sqreen
217
228
 
218
229
  protected
219
230
 
231
+ def hook_rack_request(klass)
232
+ @calling_pid = Process.pid
233
+ klass.class_eval do
234
+ define_method(:call_with_sqreen) do |*args, &block|
235
+ rv = call_without_sqreen(*args, &block)
236
+ if Sqreen.framework.instance_variable_get('@calling_pid') != Process.pid
237
+ Sqreen.framework.instance_variable_set('@calling_pid', Process.pid)
238
+ yield Sqreen.framework
239
+ end
240
+ rv
241
+ end
242
+ alias_method :call_without_sqreen, :call
243
+ alias_method :call, :call_with_sqreen
244
+ end
245
+ end
246
+
247
+ def hook_rack_builder
248
+ Rack::Builder.class_eval do
249
+ define_method(:to_app_with_sqreen) do |*args, &block|
250
+ Sqreen.framework.to_app_done(Process.pid)
251
+ to_app_without_sqreen(*args, &block)
252
+ end
253
+ alias_method :to_app_without_sqreen, :to_app
254
+ alias_method :to_app, :to_app_with_sqreen
255
+ end
256
+ end
257
+
220
258
  # FIXME: Extract to another object (utils?)
221
259
  # FIXME: protect against cycles ?
222
260
  def each_value_for_hash(params, &block)
@@ -229,11 +267,12 @@ module Sqreen
229
267
  end
230
268
 
231
269
  def ensure_rack_loaded
270
+ @cannot_load_rack ||= false
232
271
  return false if @cannot_load_rack
233
272
  require 'rack' unless defined?(Rack)
234
273
  true
235
274
  rescue LoadError => e
236
- # FIXME find a nice way to test this branch
275
+ # FIXME: find a nice way to test this branch
237
276
  Sqreen::RemoteException.record(e)
238
277
  @cannot_load_rack = true
239
278
  false
@@ -73,30 +73,10 @@ module Sqreen
73
73
  end
74
74
  end
75
75
 
76
- def hook_rack_request(app)
77
- saved_meth_name = :call_without_sqreen_hooked
78
- new_method = :call_with_sqreen_hooked
79
-
80
- app.class.class_eval do
81
- alias_method saved_meth_name, :call
82
-
83
- define_method(new_method) do |*args, &cblock|
84
- rv = send(saved_meth_name, *args, &cblock)
85
- if Sqreen.framework.instance_variable_get('@calling_pid') != Process.pid
86
- Sqreen.framework.instance_variable_set('@calling_pid', Process.pid)
87
- yield Sqreen.framework
88
- end
89
- rv
90
- end
91
-
92
- alias_method :call, new_method
93
- end
94
- end
95
-
96
76
  def on_start(&block)
97
77
  @calling_pid = Process.pid
98
78
  Init.startup do |app|
99
- hook_rack_request(app, &block)
79
+ hook_rack_request(app.class, &block)
100
80
  app.config.after_initialize do
101
81
  yield self
102
82
  end
@@ -14,6 +14,11 @@ module Sqreen
14
14
  h
15
15
  end
16
16
 
17
+ def on_start(&block)
18
+ hook_rack_request(Sinatra::Application, &block)
19
+ yield self
20
+ end
21
+
17
22
  def db_settings(options = {})
18
23
  adapter = options[:connection_adapter]
19
24
  return nil unless adapter