corn 0.5.6 → 0.5.7.beta1
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/lib/corn.rb +4 -1
- data/lib/corn/post.rb +40 -7
- data/lib/corn/profiler.rb +3 -2
- data/lib/corn/rack/request_env.rb +3 -3
- data/lib/corn/rack/slow_request_profiler.rb +17 -2
- data/lib/corn/reservoir_sampling.rb +29 -0
- data/lib/generators/corn/config/config_generator.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cd2ed0bc9b102eca18ed7e80ea7a9313702fc02
|
4
|
+
data.tar.gz: 6ce6d074da698b05112110f83635b497f8453735
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07ad76f726b438be79b29f51144c913fd1f413abbd221c2c0beff3c9453db7a439441de4080bc4ebb111c330ef5c6c7f727709f8605b0aeca26925f3920eb22e
|
7
|
+
data.tar.gz: 5d216ec62d5c8d3ccc111d7aee67b3740a3b1c4899023479ed725b27fe3855fd6c27afbaa8322d673d321c28d94471aa2590a65592532d190ad96ce84e6311d6
|
data/lib/corn.rb
CHANGED
@@ -33,9 +33,12 @@ module Corn
|
|
33
33
|
:rack_middleware => Rack::SlowRequestProfiler,
|
34
34
|
:rack_slow_request_profiler => Rack::SlowRequestProfiler,
|
35
35
|
:slow_request_threshold => 5,
|
36
|
+
:fast_request_threshold => lambda { [Corn.sampling_interval * 5, Corn.slow_request_threshold.to_f / 5].max },
|
36
37
|
:profiling => true,
|
37
38
|
:sampling_interval => 0.1,
|
38
|
-
:post_interval => 2
|
39
|
+
:post_interval => 2,
|
40
|
+
:post_fast_request_interval => 60, #seconds
|
41
|
+
:fast_request_sampling_limit => 1024 * 1024 * 2 #2MB
|
39
42
|
})
|
40
43
|
|
41
44
|
module_function
|
data/lib/corn/post.rb
CHANGED
@@ -5,9 +5,12 @@ require 'time'
|
|
5
5
|
|
6
6
|
module Corn
|
7
7
|
class Post
|
8
|
-
def initialize(interval)
|
8
|
+
def initialize(interval, sampling_limit, sampling_time)
|
9
9
|
@queue = Queue.new
|
10
10
|
@thread = start_post_thread(interval)
|
11
|
+
@sampling_limit = sampling_limit
|
12
|
+
@sampling_time = sampling_time
|
13
|
+
reset_sampling
|
11
14
|
end
|
12
15
|
|
13
16
|
def terminate
|
@@ -24,8 +27,21 @@ module Corn
|
|
24
27
|
Thread.start do
|
25
28
|
begin
|
26
29
|
loop do
|
27
|
-
|
28
|
-
|
30
|
+
d = @queue.pop
|
31
|
+
case d[:action]
|
32
|
+
when :post
|
33
|
+
http_post([d])
|
34
|
+
sleep interval
|
35
|
+
when :sampling
|
36
|
+
@sampling << d
|
37
|
+
if Time.now - @sampling_start > @sampling_time
|
38
|
+
http_post(@sampling.items, :sampling)
|
39
|
+
reset_sampling
|
40
|
+
sleep interval
|
41
|
+
end
|
42
|
+
else
|
43
|
+
Corn.logger.info("Corn: Ignore unknown action: #{d[:action]}")
|
44
|
+
end
|
29
45
|
end
|
30
46
|
rescue => e
|
31
47
|
Corn.logger.error("Corn post thread stopped by error #{e.message}\n#{e.backtrace.join("\n")}")
|
@@ -34,14 +50,25 @@ module Corn
|
|
34
50
|
end
|
35
51
|
|
36
52
|
def enqueue(data)
|
37
|
-
return if data.nil?
|
53
|
+
return if data.nil? || data.empty?
|
38
54
|
@queue << data
|
39
55
|
end
|
40
56
|
|
41
|
-
def http_post(
|
57
|
+
def http_post(reports, type=nil)
|
42
58
|
uri = URI.parse(submit_url)
|
43
59
|
req = Net::HTTP::Post.new(uri.path)
|
44
|
-
|
60
|
+
form_data = [['client_id', Corn.client_id]]
|
61
|
+
if type
|
62
|
+
form_data << ['type', type]
|
63
|
+
end
|
64
|
+
reports.each_with_index do |rep, i|
|
65
|
+
[:name, :start_at, :end_at, :data].each do |k|
|
66
|
+
if v = rep[k]
|
67
|
+
form_data << ["reports[][#{k}]", v]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
req.set_form_data(form_data)
|
45
72
|
|
46
73
|
http = Net::HTTP.new(uri.host, uri.port)
|
47
74
|
if uri.scheme == 'https'
|
@@ -55,7 +82,7 @@ module Corn
|
|
55
82
|
end
|
56
83
|
end
|
57
84
|
res = http.request(req)
|
58
|
-
Corn.logger.info("Corn
|
85
|
+
Corn.logger.info("Corn reports(#{reports.size}) submitted to #{submit_url}")
|
59
86
|
unless res.is_a?(Net::HTTPSuccess)
|
60
87
|
Corn.logger.error("Post failed: #{res.message}(#{res.code}), response body: \n#{res.body}")
|
61
88
|
end
|
@@ -66,5 +93,11 @@ module Corn
|
|
66
93
|
def submit_url
|
67
94
|
Corn.submit_url
|
68
95
|
end
|
96
|
+
|
97
|
+
private
|
98
|
+
def reset_sampling
|
99
|
+
@sampling = ReservoirSampling.new(@sampling_limit)
|
100
|
+
@sampling_start = Time.now
|
101
|
+
end
|
69
102
|
end
|
70
103
|
end
|
data/lib/corn/profiler.rb
CHANGED
@@ -3,8 +3,9 @@ require 'sampling_prof'
|
|
3
3
|
|
4
4
|
module Corn
|
5
5
|
class Profiler
|
6
|
-
def initialize(post_interval,
|
7
|
-
|
6
|
+
def initialize(post_interval, post_sampling_limit, post_sampling_time,
|
7
|
+
sampling_interval)
|
8
|
+
@post = Post.new(post_interval, post_sampling_limit, post_sampling_time)
|
8
9
|
@prof = SamplingProf.new(sampling_interval)
|
9
10
|
at_exit { terminate }
|
10
11
|
end
|
@@ -31,9 +31,9 @@ module Corn
|
|
31
31
|
name = "#{name}?#{@env[:query_string]}"
|
32
32
|
end
|
33
33
|
{
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
:name => name,
|
35
|
+
:start_at => @env[:start_time].iso8601,
|
36
|
+
:end_at => end_at.iso8601
|
37
37
|
}
|
38
38
|
end
|
39
39
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
+
require 'thread'
|
1
2
|
require 'corn/profiler'
|
3
|
+
require 'corn/reservoir_sampling'
|
2
4
|
require 'corn/rack/request_env'
|
3
5
|
|
4
6
|
module Corn
|
@@ -7,8 +9,11 @@ module Corn
|
|
7
9
|
class ProfilingApp
|
8
10
|
def initialize(app)
|
9
11
|
@@prof ||= Profiler.new(Corn.post_interval,
|
12
|
+
Corn.fast_request_sampling_limit,
|
13
|
+
Corn.post_fast_request_interval,
|
10
14
|
Corn.sampling_interval)
|
11
15
|
@app = app
|
16
|
+
|
12
17
|
Corn.logger.info("Corn sampling interval: #{Corn.sampling_interval}")
|
13
18
|
Corn.logger.info("Corn slow request threshold: #{Corn.slow_request_threshold}")
|
14
19
|
end
|
@@ -29,11 +34,20 @@ module Corn
|
|
29
34
|
def output_handler(env)
|
30
35
|
request_env = RequestEnv.new(env)
|
31
36
|
lambda do |data|
|
32
|
-
|
33
|
-
|
37
|
+
t = request_env.time
|
38
|
+
if t < fast_request_threshold || t > slow_request_threshold
|
39
|
+
action = t > Corn.slow_request_threshold ? :post : :sampling
|
40
|
+
request_env.to_report.merge(:data => data, :action => action)
|
34
41
|
end
|
35
42
|
end
|
36
43
|
end
|
44
|
+
|
45
|
+
def fast_request_threshold
|
46
|
+
@frt ||= Corn.fast_request_threshold
|
47
|
+
end
|
48
|
+
def slow_request_threshold
|
49
|
+
@srt ||= Corn.slow_request_threshold
|
50
|
+
end
|
37
51
|
end
|
38
52
|
|
39
53
|
def initialize(app)
|
@@ -44,6 +58,7 @@ module Corn
|
|
44
58
|
@app.call(env)
|
45
59
|
end
|
46
60
|
|
61
|
+
# for test
|
47
62
|
def terminate
|
48
63
|
@app.terminate if @app.respond_to?(:terminate)
|
49
64
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Corn
|
2
|
+
class ReservoirSampling
|
3
|
+
attr_reader :items
|
4
|
+
def initialize(limit)
|
5
|
+
@limit = limit
|
6
|
+
@items = []
|
7
|
+
@size = -1
|
8
|
+
@count = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(item)
|
12
|
+
@count += 1
|
13
|
+
if @size < 0 && bytesize < @limit
|
14
|
+
items << item
|
15
|
+
else
|
16
|
+
@size = items.size
|
17
|
+
j = rand(@count).to_i
|
18
|
+
if j < @size
|
19
|
+
items[j] = item
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def bytesize
|
26
|
+
items.map{|d|d[:data].bytesize}.reduce(:+) || 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -56,7 +56,7 @@ Corn.config({
|
|
56
56
|
# called. So you can also use it to turn on profiling by a request parameter.
|
57
57
|
# For example: Corn.config(:profiling => lambda {|env| env["QUERY_STRING"] =~ /corn_profiling=true/ })
|
58
58
|
# This configuration will be checked for every request, so don't do anything
|
59
|
-
#
|
59
|
+
# expensive here.
|
60
60
|
# :profiling => true,
|
61
61
|
})
|
62
62
|
# Install corn rack middleware for profiling slow requests
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: corn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.7.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xiao Li
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sampling_prof
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/corn/post.rb
|
39
39
|
- lib/corn/profiler.rb
|
40
40
|
- lib/corn/rack.rb
|
41
|
+
- lib/corn/reservoir_sampling.rb
|
41
42
|
- lib/corn/rack/request_env.rb
|
42
43
|
- lib/corn/rack/slow_request_profiler.rb
|
43
44
|
- lib/generators/corn/config/config_generator.rb
|
@@ -56,9 +57,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
57
|
version: '0'
|
57
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
59
|
requirements:
|
59
|
-
- - '
|
60
|
+
- - '>'
|
60
61
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
62
|
+
version: 1.3.1
|
62
63
|
requirements: []
|
63
64
|
rubyforge_project:
|
64
65
|
rubygems_version: 2.1.9
|