rails_runner 0.0.1 → 0.0.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 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