rails-idle 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f58b55e40ca14d9ba36db82d076cc50dc3ccba46
4
+ data.tar.gz: 8bde64f72b2e5dbd54d034132abe534ba2553d1f
5
+ SHA512:
6
+ metadata.gz: ddffde060b6413844c73918b96440a479096c8e53212c2e93f8a7b3d1233148b8c341673ad5d80e9a56793b0b462c091095435d38848f4b975697cb275fb3f84
7
+ data.tar.gz: c5aae1b3eb90f11b0fbf95f8409a3d8efd6ad11529c2123ccdfba2f0a25d47ff71bcfbb16f043d8cb7da08bac3d77bdb422537bd7a74bb00c1d7a4066f3ee9ba
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ tmp
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Vitalik Danchenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,68 @@
1
+ require 'pathname'
2
+ require 'active_support/core_ext/hash'
3
+ require 'active_support/core_ext/string'
4
+
5
+ module RailsIdle
6
+ autoload :Storage, 'rails-idle/storage'
7
+ autoload :Collector, 'rails-idle/collector'
8
+ autoload :TreeBuilder, 'rails-idle/tree_builder'
9
+ autoload :Report, 'rails-idle/report'
10
+ autoload :Web, 'rails-idle/web'
11
+
12
+ DEFAULTS = {
13
+ collectors: RailsIdle::Collector.list,
14
+ reset: false,
15
+ cache: {
16
+ :views => Pathname.new('/tmp/cache/rails-idle/views.cache'),
17
+ },
18
+ }
19
+
20
+ class << self
21
+
22
+ def options
23
+ @options ||= DEFAULTS.dup
24
+ end
25
+
26
+ def options=(opts)
27
+ @options = opts
28
+ end
29
+
30
+ def configure
31
+ yield self
32
+ end
33
+
34
+ def collectors
35
+ options[:collectors]
36
+ end
37
+
38
+ def collectors=(list)
39
+ options[:collectors] = list.map(&:to_sym).select{|c| DEFAULTS[:collectors].include? c}
40
+ end
41
+
42
+ def cache=(hash)
43
+ hash.select{|key, _| DEFAULTS[:collectors].include? key}
44
+ _cache = hash.symbolize_keys.select{|c, _| DEFAULTS[:collectors].include? c}
45
+ options[:cache].merge!(_cache)
46
+ end
47
+
48
+ def reset?
49
+ options[:reset]
50
+ end
51
+
52
+ def reset=(value)
53
+ options[:reset] = value
54
+ end
55
+
56
+ def stylesheets
57
+ @stylesheets ||= []
58
+ end
59
+
60
+ def stylesheets=(sheets = [])
61
+ @stylesheets = sheets
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ require 'rails-idle/railtie' if defined?(::Rails)
@@ -0,0 +1,21 @@
1
+ module RailsIdle
2
+ module Collector
3
+ autoload :Base, 'rails-idle/collector/base'
4
+ #autoload :Actions, 'rails-idle/collector/actions'
5
+ autoload :Views, 'rails-idle/collector/views'
6
+ # autoload :Stylesheets, 'rails-idle/collector/stylesheets'
7
+
8
+ class << self
9
+
10
+ def list
11
+ [:views]
12
+ end
13
+
14
+ def instance(key)
15
+ return RailsIdle::Collector::Views.instance if key == :views
16
+ # return RailsIdle::Collector::Stylesheets.instance if key == :stylesheets
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ require 'singleton'
2
+
3
+ module RailsIdle
4
+ module Collector
5
+ class Base
6
+ include Singleton
7
+
8
+ def collect
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def subscribe
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def push(item, execution_time = 1)
17
+ storage.add(item, execution_time)
18
+ end
19
+
20
+ def storage
21
+ @starage ||= RailsIdle::Storage::RailsCache.new
22
+ end
23
+
24
+ protected
25
+
26
+ def collector_key
27
+ self.class.to_s.demodulize.downcase.to_sym
28
+ end
29
+
30
+ private
31
+
32
+ def _collect(path)
33
+ storage.reset(path) if RailsIdle.reset?
34
+ storage.add(path)
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,92 @@
1
+ module RailsIdle
2
+ module Collector
3
+ class Views < Base
4
+ def collect
5
+ view_paths.each do |path|
6
+ views = Dir[path + '/**/*.*']
7
+ views.each do |view|
8
+ view = modify_prefix(view)
9
+ next unless view
10
+ if view =~ extensions_regexp
11
+ _collect view
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def subscribe
18
+ %w{render_template render_partial render_collection}.each do |event|
19
+ ActiveSupport::Notifications.subscribe("#{event}.action_view") do |name, started, finished, unique_id, payload|
20
+ orig_prefix = ''
21
+ view = modify_prefix payload[:identifier], orig_prefix
22
+ next unless view
23
+ execution_time = finished.to_f - started.to_f
24
+ push(view, execution_time)
25
+ if payload[:layout] && view =~ /\.\w+\.\w+$/
26
+ # just_view = extract_view payload[:identifier], view
27
+ # prefix = payload[:identifier].gsub(just_view, '')
28
+ extension = view.match(/\.\w+\.\w+$/)[0]
29
+ layout = orig_prefix + '/' + payload[:layout] + extension
30
+ layout = modify_prefix layout
31
+ push(layout, execution_time) if layout
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def view_paths
40
+ ActionController::Base.new.view_paths.map(&:to_path)
41
+ end
42
+
43
+ def extensions_regexp
44
+ @extensions_regexp ||= build_extensions_regexp
45
+ end
46
+
47
+ def build_extensions_regexp
48
+ formats = %w(html text)
49
+ handlers = ActionView::Template.template_handler_extensions
50
+ exts = view_extentions.join('|').gsub(/\./, '\.')
51
+ Regexp.new "(#{exts})$"
52
+ end
53
+
54
+ def view_extentions
55
+ @view_extentions ||= build_view_extentions
56
+ end
57
+
58
+ def build_view_extentions
59
+ extentions = []
60
+ format_extensions = %w(html text)
61
+ handler_extensions = ActionView::Template.template_handler_extensions
62
+ handler_extensions.each do |handler_ext|
63
+ extentions << ".#{handler_ext}"
64
+ format_extensions.each do |format_ext|
65
+ extentions << ".#{format_ext}.#{handler_ext}"
66
+ end
67
+ end
68
+ extentions
69
+ end
70
+
71
+ def modify_prefix(identifier, orig_prefix = '')
72
+ view_paths.each do |path|
73
+ orig_prefix.replace path
74
+ return identifier.gsub(path, path.gsub('/', '&#47;')) if identifier.start_with?(path)
75
+ end
76
+ orig_prefix.replace ''
77
+ nil
78
+ end
79
+
80
+ # def extract_view(orig_prefix, modified_prefix)
81
+ # idx = 1
82
+ # view = ''
83
+ # while (idx <= orig_prefix.size && idx <= modified_prefix.size && orig_prefix[-idx] == modified_prefix[-idx])
84
+ # view = modified_prefix[-idx] + view
85
+ # idx += 1
86
+ # end
87
+ # view
88
+ # end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,22 @@
1
+ module RailsIdle
2
+ class << self
3
+ def init!
4
+ collect
5
+ subscribe
6
+ end
7
+
8
+ private
9
+
10
+ def _collectors
11
+ Hash[*(RailsIdle::Collector.list.map{|c| [c, RailsIdle::Collector.instance(c)]}.flatten)]
12
+ end
13
+
14
+ def collect
15
+ _collectors.select{|k, _| options[:collectors].include? k}.each_value(&:collect)
16
+ end
17
+
18
+ def subscribe
19
+ _collectors.select{|k, _| options[:collectors].include? k}.each_value(&:subscribe)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ require 'rails-idle/init'
2
+
3
+ module RailsIdle
4
+ class Railtie < ::Rails::Railtie
5
+ config.to_prepare do
6
+ RailsIdle.init!
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ module RailsIdle
2
+ class Report
3
+ CALCULATED_KEY = :calculated
4
+ COUNTER_KEY = RailsIdle::Storage::COUNTER_KEY
5
+
6
+ def initialize(collector)
7
+ @tree = TreeBuilder.new(collector).tree
8
+ end
9
+
10
+ def prepare
11
+ calc_counter!(@tree)
12
+ #sort!(@obj)
13
+ @tree
14
+ end
15
+
16
+ private
17
+
18
+ def calc_counter!(obj)
19
+ return obj[COUNTER_KEY] if obj[COUNTER_KEY].is_a?(Fixnum)
20
+ return obj[CALCULATED_KEY] if obj[CALCULATED_KEY].is_a?(Fixnum)
21
+ obj[CALCULATED_KEY] = obj.inject(0) do |sum, (key, nested_obj)|
22
+ sum + (key.is_a?(Symbol) ? 0 : calc_counter!(nested_obj))
23
+ end
24
+ obj[CALCULATED_KEY]
25
+ end
26
+
27
+ def sort!(obj)
28
+ obj.each do |k, v|
29
+ obj[k] = sort!(v) if v.is_a?(Hash)
30
+ end
31
+ obj.sort_by do |k, v|
32
+ if v.is_a?(Hash)
33
+ v[CALCULATED_KEY] || v[COUNTER_KEY] || 0
34
+ else
35
+ Float::INFINITY
36
+ end
37
+ end.to_h
38
+ end
39
+
40
+
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module RailsIdle
2
+ module Storage
3
+ COUNTER_KEY = :counter
4
+ EXECUTION_KEY = :execution
5
+
6
+ autoload :Base, 'rails-idle/storage/base'
7
+ autoload :RailsCache, 'rails-idle/storage/rails_cache'
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ module RailsIdle
2
+ module Storage
3
+ class Base
4
+
5
+ def add(path, execution_time = nil)
6
+ add_to_list path
7
+ end
8
+
9
+ def get(path, key)
10
+ raise NotImplementedError
11
+ end
12
+
13
+ def reset(path)
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def objects_list
18
+ @objects_list ||= empty_list
19
+ end
20
+
21
+ private
22
+
23
+ def empty_list
24
+ []
25
+ end
26
+
27
+ def add_to_list(path)
28
+ objects_list << path
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ module RailsIdle
2
+ module Storage
3
+ class RailsCache < Base
4
+
5
+ def add(path, execution_time = nil)
6
+ super
7
+ if execution_time
8
+ increment(path, COUNTER_KEY)
9
+ increment(path, EXECUTION_KEY, (execution_time * 1000).round)
10
+ end
11
+ end
12
+
13
+ def get(path, key)
14
+ begin
15
+ Rails.cache.read build_name(path, key)
16
+ rescue Exception => e # Redis workaround
17
+ (Rails.cache.read build_name(path, key), raw: true).to_i
18
+ end
19
+ end
20
+
21
+ def reset(path)
22
+ [COUNTER_KEY, EXECUTION_KEY].each do |key|
23
+ Rails.cache.delete build_name(path, key)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def increment(path, key, amount = 1)
30
+ Rails.cache.increment build_name(path, key), amount
31
+ end
32
+
33
+ def build_name(path, key)
34
+ "#{RailsIdle}.#{path}.#{key}"
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ module RailsIdle
2
+ class TreeBuilder
3
+ def initialize(collector)
4
+ @storage = collector.storage
5
+ end
6
+
7
+ def tree
8
+ @tree ||= build_tree
9
+ end
10
+
11
+ private
12
+
13
+ def build_tree
14
+ root = {}
15
+ @storage.objects_list.each do |path|
16
+ items = parse_path(path)
17
+ tree = root
18
+ items.each do |item|
19
+ tree[item] = {} unless tree[item]
20
+ tree = tree[item]
21
+ end
22
+ tree[RailsIdle::Storage::COUNTER_KEY] = @storage.get(path, RailsIdle::Storage::COUNTER_KEY)
23
+ tree[RailsIdle::Storage::EXECUTION_KEY] = @storage.get(path, RailsIdle::Storage::EXECUTION_KEY)
24
+ end
25
+ root
26
+ end
27
+
28
+ def parse_path(path)
29
+ path.split(/,|\/|::/)
30
+ end
31
+
32
+ end
33
+ end