rails_runner 0.0.1 → 0.0.2

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: 140270f54be56b6eb841de14c8d0b6489c3ad786
4
- data.tar.gz: e93221ca8696a833cad6421d2a30d6ccca1f805f
3
+ metadata.gz: 41d4daada8041fb8cb32f31f1abf2213e2b272b1
4
+ data.tar.gz: 864d7359d31123a2ffdb2014ef7a9490f00870b5
5
5
  SHA512:
6
- metadata.gz: 336638f0a7e7bdde650884ef05d823ea2633a09ba7c2735ec03e8fe2a2f875f95559895130ad6a5d3932f86e78cae38bd10b715ff6527fa1e100b3c669f5ef31
7
- data.tar.gz: 96e042ca7425e45c388de5ffa75f94ae081e7a78c7efbc58495cbc7a8f3945cf16ca3419f8cf5aa978b66a61c914b6fba49c0f6186ec67f30120c6fc57bb545b
6
+ metadata.gz: 6dc7e7f3ae396845b873df5966ca48bcb20735fc3f9280f37c3ccd98475c888f6cd163798715bd4082241a2dc80f3e939adb46ad88a7059b75899407728e95a5
7
+ data.tar.gz: 4e549cc52732cd1903f36393f3507103d8ab979518fb094e967f7005d1b83413000b04da54c821151207aa9a029c6c17fdc852acbe28f4a409756ee446da9e0e
data/lib/rails_runner.rb CHANGED
@@ -2,23 +2,9 @@ require 'beefcake'
2
2
 
3
3
  module RailsRunner
4
4
  require 'rails_runner/util'
5
- require 'rails_runner/messages/action'
6
- require 'rails_runner/messages/endpoint'
7
- require 'rails_runner/messages/request'
8
- require 'rails_runner/messages/minute'
9
- require 'rails_runner/messages/batch'
10
-
11
- require 'rails_runner/notifications/default'
12
- require 'rails_runner/notifications'
13
- require 'rails_runner/notifications/process_action'
14
- require 'rails_runner/notifications/render_partial'
15
- require 'rails_runner/notifications/render_template'
16
- require 'rails_runner/notifications/sql'
17
-
18
5
  require 'rails_runner/instrumenter'
19
6
  require 'rails_runner/middleware'
20
7
  require 'rails_runner/railtie'
21
- require 'rails_runner/subscriber'
22
8
  require 'rails_runner/worker'
23
9
  require 'rails_runner/config'
24
10
 
@@ -3,14 +3,6 @@ module RailsRunner
3
3
  MUTEX = Mutex.new
4
4
 
5
5
  class << self
6
- def current_request
7
- Thread.current[:rails_runner_current_request]
8
- end
9
-
10
- def current_request=(request)
11
- Thread.current[:rails_runner_current_request] = request
12
- end
13
-
14
6
  def start!
15
7
  return @instance if @instance
16
8
 
@@ -27,21 +19,11 @@ module RailsRunner
27
19
 
28
20
  def start
29
21
  @worker = Worker.start!
30
- @subscriber = Subscriber.new.register
31
-
32
22
  self
33
23
  end
34
24
 
35
- def record(*args)
36
- self.class.current_request = Request.new
37
- end
38
-
39
- def reset
40
- self.class.current_request = nil
41
- end
42
-
43
- def publish(request)
44
- @worker.push(request)
25
+ def publish(time)
26
+ @worker.push(time)
45
27
  end
46
28
  end
47
29
  end
@@ -5,19 +5,20 @@ module RailsRunner
5
5
  end
6
6
 
7
7
  def call(env)
8
+ @start = Time.now
8
9
  begin
9
- request = instrumenter.record 'Rack', 'rack.request'
10
- resp = @app.call(env)
11
- request.finish if request
12
- resp
13
- rescue Exception
14
- request.finish(true) if request
15
- raise
10
+ @app.call(env)
16
11
  ensure
17
- instrumenter.reset
12
+ record_time(@start)
18
13
  end
19
14
  end
20
15
 
16
+ def record_time(start)
17
+ milliseconds = ((Time.now - start) * 1000).to_i
18
+ instrumenter.publish(milliseconds)
19
+ end
20
+
21
+ # @return [RailsRunner::Instrumenter]
21
22
  def instrumenter
22
23
  RailsRunner::Instrumenter.instance
23
24
  end
@@ -1,11 +1,16 @@
1
1
  module RailsRunner
2
2
  class Railtie < Rails::Railtie
3
3
  initializer 'rails_runner.configure' do |app|
4
- Instrumenter.start!
5
- app.middleware.insert 0, Middleware
6
4
  RailsRunner.config = RailsRunner::Config.new(app.root.join('config/railsrunner.yml'))
7
5
 
8
- puts "[RAILSRUNNER] started"
6
+ Rails.logger.debug RailsRunner.config.to_yaml
7
+
8
+ if RailsRunner.config.active?
9
+ Instrumenter.start!
10
+ app.middleware.insert 0, Middleware
11
+
12
+ Rails.logger.debug "[RAILSRUNNER] started #{RailsRunner.config.collector_url}"
13
+ end
9
14
  end
10
15
  end
11
16
  end
@@ -9,13 +9,18 @@ module RailsRunner
9
9
  end
10
10
 
11
11
  def post(body)
12
- uri = URI.parse(URI.join("#{RailsRunner.config.collector_url}").to_s)
13
- http = Net::HTTP.new(uri.host, uri.port)
12
+ uri = URI.parse(URI.join("#{RailsRunner.config.collector_url}").to_s)
13
+ http = Net::HTTP.new(uri.host, uri.port)
14
+ http.open_timeout = 3
15
+ http.read_timeout = 3
16
+
14
17
  gzipped = Base64.encode64(gzip(body))
15
18
 
16
- request = Net::HTTP::Post.new(uri.request_uri)
17
- request.body = gzipped
18
- request['Authorization'] = "#{RailsRunner.config.client_id}"
19
+ request = Net::HTTP::Post.new(uri.request_uri)
20
+ request.body = gzipped
21
+ request['Authorization'] = "#{RailsRunner.config.client_id}"
22
+
23
+ Rails.logger.debug "uri: #{uri.host}:#{uri.port} #{uri.request_uri}, header: #{RailsRunner.config.client_id} body length: #{gzipped.length}"
19
24
 
20
25
  http.request(request)
21
26
  end
@@ -1,3 +1,3 @@
1
1
  module RailsRunner
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -2,7 +2,7 @@ module RailsRunner
2
2
  class Worker
3
3
  MUTEX = Mutex.new
4
4
 
5
- attr_accessor :requests, :batch
5
+ attr_accessor :requests
6
6
 
7
7
  class << self
8
8
  def start!
@@ -20,8 +20,16 @@ module RailsRunner
20
20
 
21
21
  def initialize
22
22
  @queue = Queue.new
23
- @requests = 0
24
- @batch = Batch.new
23
+ reset
24
+ end
25
+
26
+ def reset
27
+ @requests = Hash.new { |h,k| h[k] = Hash.new { |h,k| h[k] = 0 } }
28
+ end
29
+
30
+ def current_minute
31
+ time = Time.now.to_i
32
+ time - (time % 60)
25
33
  end
26
34
 
27
35
  def start
@@ -29,17 +37,26 @@ module RailsRunner
29
37
  while (request = @queue.pop)
30
38
  begin
31
39
  case request
32
- when Request
33
- batch.current_minute.add_request(request)
34
- @requests += 1
40
+ when Integer
41
+ @requests[current_minute][request] += 1
35
42
  when :flush
36
43
  send_to_collector
37
44
  end
38
45
  rescue Exception => e
39
46
  puts e.message
47
+ puts e.backtrace.join("\n")
40
48
  end
41
49
  end
42
50
  end
51
+
52
+ Thread.new do
53
+ loop do
54
+ sleep 10.seconds
55
+ Rails.logger.debug "Sending flush message"
56
+ push(:flush)
57
+ end
58
+ end
59
+
43
60
  self
44
61
  end
45
62
 
@@ -48,12 +65,12 @@ module RailsRunner
48
65
  end
49
66
 
50
67
  def send_to_collector
51
- @batch.encode(buffer = '')
68
+ Rails.logger.debug "Sending to collector"
69
+ Rails.logger.flush
52
70
 
53
- Util.post(buffer)
71
+ Util.post(requests.to_json)
54
72
 
55
- @requests = 0
56
- @batch = Batch.new
73
+ reset
57
74
  end
58
75
  end
59
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benoist Claassen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-22 00:00:00.000000000 Z
11
+ date: 2013-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -61,20 +61,8 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - lib/rails_runner/config.rb
63
63
  - lib/rails_runner/instrumenter.rb
64
- - lib/rails_runner/messages/action.rb
65
- - lib/rails_runner/messages/batch.rb
66
- - lib/rails_runner/messages/endpoint.rb
67
- - lib/rails_runner/messages/minute.rb
68
- - lib/rails_runner/messages/request.rb
69
64
  - lib/rails_runner/middleware.rb
70
- - lib/rails_runner/notifications/default.rb
71
- - lib/rails_runner/notifications/process_action.rb
72
- - lib/rails_runner/notifications/render_partial.rb
73
- - lib/rails_runner/notifications/render_template.rb
74
- - lib/rails_runner/notifications/sql.rb
75
- - lib/rails_runner/notifications.rb
76
65
  - lib/rails_runner/railtie.rb
77
- - lib/rails_runner/subscriber.rb
78
66
  - lib/rails_runner/util.rb
79
67
  - lib/rails_runner/version.rb
80
68
  - lib/rails_runner/worker.rb
@@ -1,25 +0,0 @@
1
- module RailsRunner
2
- class Action
3
- include Beefcake::Message
4
-
5
- required :category, :string, 1
6
- required :object, :string, 2
7
- required :start, :int64, 3
8
- required :end, :int64, 4
9
- required :duration, :int64, 5
10
- required :explain, :string, 6
11
- required :level, :int32, 7
12
-
13
- def initialize(category, object, explain = '')
14
- @category = category
15
- @object = object
16
- @explain = explain.to_s
17
- @start = Util.time_in_usec
18
- end
19
-
20
- def finish
21
- @end = Util.time_in_usec
22
- @duration = @end - @start
23
- end
24
- end
25
- end
@@ -1,38 +0,0 @@
1
- module RailsRunner
2
- class Batch
3
- include Beefcake::Message
4
-
5
- required :client_id, :string, 1
6
- required :app_name, :string, 2
7
- required :hostname, :string, 3
8
-
9
- repeated :minutes, Minute, 5
10
-
11
- def initialize
12
- @client_id = RailsRunner.config.client_id
13
- @app_name = RailsRunner.config.app_name
14
- @hostname = RailsRunner.config.hostname
15
-
16
- @_minutes = {}
17
- end
18
-
19
- def current_minute
20
- @_minutes[minute] ||= RailsRunner::Minute.new(minute)
21
- end
22
-
23
- def encode(*)
24
- @minutes = @_minutes.values
25
- super
26
- end
27
-
28
- def minutes
29
- @minutes ||= @_minutes.values
30
- end
31
-
32
- private
33
-
34
- def minute
35
- Time.now.to_i / 60
36
- end
37
- end
38
- end
@@ -1,31 +0,0 @@
1
- module RailsRunner
2
- class Endpoint
3
- include Beefcake::Message
4
- required :name, :string, 1
5
- required :errors, :int64, 2
6
- repeated :times, :int64, 3, packed: true
7
- repeated :counts, :int64, 4, packed: true
8
-
9
- def initialize(*args)
10
- super
11
- @errors = 0
12
- @times = Hash.new { |h, k| h[k] = 0 }
13
- end
14
-
15
- def add_time(time)
16
- @times[time.to_i] += 1
17
- end
18
-
19
- def add_error
20
- @errors += 1
21
- end
22
-
23
- def times
24
- @times.keys
25
- end
26
-
27
- def counts
28
- @times.values
29
- end
30
- end
31
- end
@@ -1,80 +0,0 @@
1
- module RailsRunner
2
- class Minute
3
- include Beefcake::Message
4
-
5
- required :minute, :int64, 1
6
- repeated :endpoints, Endpoint, 2, packed: true
7
- repeated :traces, Request, 3, packed: true
8
-
9
- def initialize(minute = Time.now.to_i)
10
- @minute = minute
11
- @errors = 0
12
- @endpoints = {}
13
- @trace_endpoints = {}
14
- end
15
-
16
- def add_request(request)
17
- add_error(request)
18
-
19
- add_time(request)
20
-
21
- add_trace(request)
22
- end
23
-
24
- def add_trace(request)
25
- return if request.traceable?
26
- return if slower_request_registered?(request)
27
- @trace_endpoints[request.name] = request
28
- end
29
-
30
- def add_time(request)
31
- time = rounded(request.duration)
32
- endpoint(request.name).add_time(time) if request.name.present?
33
- endpoint('total').add_time(time)
34
- end
35
-
36
- def traces
37
- @trace_endpoints.values
38
- end
39
-
40
- def add_error(request)
41
- return unless request.error?
42
- endpoint(request.name || 'total').add_error
43
- end
44
-
45
- def endpoints
46
- @endpoints.values
47
- end
48
-
49
- private
50
-
51
- def endpoint(name)
52
- @endpoints[name] ||= Endpoint.new(name: name)
53
- end
54
-
55
- def rounded(duration)
56
- if duration < 500_000
57
- mod = 10_000
58
- elsif duration < 1000_000
59
- mod = 50_000
60
- elsif duration < 1500_000
61
- mod = 100_000
62
- elsif duration < 2250_000
63
- mod = 150_000
64
- elsif duration < 3000_000
65
- mod = 200_000
66
- else
67
- return 3000_000
68
- end
69
- duration - (duration % mod)
70
- end
71
-
72
- def slower_request_registered?(request)
73
- if @trace_endpoints[request.name]
74
- @trace_endpoints[request.name].duration > request.duration
75
- else
76
- false
77
- end
78
- end
79
- end
80
- end
@@ -1,48 +0,0 @@
1
- module RailsRunner
2
- class Request
3
- include Beefcake::Message
4
-
5
- optional :name, :string, 1
6
- required :start, :int64, 2
7
- required :end, :int64, 3
8
- required :duration, :int64, 4
9
- required :error, :bool, 5
10
- repeated :actions, Action, 6, packed: true
11
-
12
- attr_accessor :notifications
13
-
14
- def initialize
15
- @start = Util.time_in_usec
16
- @current_level = 0
17
- @actions = []
18
- @notifications = []
19
- end
20
-
21
- def finish(error = false)
22
- @end = Util.time_in_usec
23
- @duration = @end - @start
24
- @error = error
25
- Instrumenter.instance.publish(self)
26
- end
27
-
28
- def add_action(action)
29
- action.level = @current_level
30
- @current_level += 1
31
- @actions << action
32
- end
33
-
34
- def finish_action(action)
35
- return unless action
36
- action.finish
37
- @current_level -= 1
38
- end
39
-
40
- def traceable?
41
- name.blank? || error?
42
- end
43
-
44
- def error?
45
- @error
46
- end
47
- end
48
- end
@@ -1,17 +0,0 @@
1
- module RailsRunner
2
- class Notifications
3
- class << self
4
- DEFAULT_NOTIFICATION = Default.new
5
-
6
- def add_notification(name, notification)
7
- @notifications ||= {}
8
- @notifications[name] = notification.new
9
- end
10
-
11
- def to_action(request, name, payload)
12
- notification = @notifications[name] || DEFAULT_NOTIFICATION
13
- notification.to_action(request, payload)
14
- end
15
- end
16
- end
17
- end
@@ -1,42 +0,0 @@
1
- module RailsRunner
2
- class Notifications
3
- class Default
4
- class << self
5
- def notification(name)
6
- RailsRunner::Notifications.add_notification(name, self)
7
- end
8
- end
9
-
10
- def to_action(request, payload)
11
- nil #
12
- end
13
- end
14
-
15
- class RenderDefault < Default
16
- class << self
17
- def mapped_paths
18
- return @mapped_paths if @mapped_paths
19
- @mapped_paths = {
20
- Rails.root.to_s => ''
21
- }
22
- Gem.path.each do |path|
23
- @mapped_paths[File.join(path, 'gems')] = 'gem'
24
- end if defined?(Gem)
25
-
26
- @mapped_paths
27
- end
28
-
29
- def prune_path(raw_path)
30
- mapped_paths.each do |path, replacement|
31
- raw_path = raw_path.gsub(path, replacement)
32
- end
33
- raw_path
34
- end
35
- end
36
-
37
- def prune_path(path)
38
- self.class.prune_path(path)
39
- end
40
- end
41
- end
42
- end
@@ -1,12 +0,0 @@
1
- module RailsRunner
2
- class Notifications
3
- class ProcessAction < Default
4
- notification 'process_action.action_controller'
5
-
6
- def to_action(request, payload)
7
- request.name = "#{payload[:controller]}##{payload[:action]}"
8
- Action.new('Controller', request.name)
9
- end
10
- end
11
- end
12
- end
@@ -1,11 +0,0 @@
1
- module RailsRunner
2
- class Notifications
3
- class RenderPartial < RenderDefault
4
- notification 'render_partial.action_view'
5
-
6
- def to_action(request, payload)
7
- Action.new('View', prune_path(payload[:identifier]))
8
- end
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- module RailsRunner
2
- class Notifications
3
- class RenderTemplate < RenderDefault
4
- notification 'render_template.action_view'
5
-
6
- def to_action(request, payload)
7
- Action.new('View', prune_path(payload[:identifier]))
8
- end
9
- end
10
- end
11
- end
@@ -1,14 +0,0 @@
1
- module RailsRunner
2
- class Notifications
3
- class Sql < Default
4
- IGNORED_NAMES = %w(SCHEMA EXPLAIN CACHE) << nil
5
-
6
- notification 'sql.active_record'
7
-
8
- def to_action(request, payload)
9
- return if IGNORED_NAMES.include? payload[:name]
10
- Action.new('Database', payload[:name], payload[:sql])
11
- end
12
- end
13
- end
14
- end
@@ -1,34 +0,0 @@
1
- module RailsRunner
2
- class Subscriber
3
- Notification = Struct.new(:name, :action)
4
-
5
- def register
6
- unregister if @subscriber
7
- @subscriber = ActiveSupport::Notifications.subscribe nil, self
8
- end
9
-
10
- def start(name, id, payload)
11
- request = Instrumenter.current_request
12
- return unless request
13
-
14
- if (action = Notifications.to_action(request, name, payload))
15
- request.add_action(action)
16
- end
17
-
18
- request.notifications << Notification.new(name, action)
19
- end
20
-
21
- def finish(name, id, payload)
22
- request = Instrumenter.current_request
23
- return unless request
24
-
25
- while (notification = request.notifications.pop)
26
- if notification.name == name
27
- request.finish_action(notification.action)
28
- return
29
- end
30
- end
31
- end
32
-
33
- end
34
- end