dead_view_catcher 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ 0.1 (January 12, 2011)
2
+
3
+ * Initial release: tested against mongrel and unicorn on nix system
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Guillaume Luccisano - g-mai|: guillaume.luccisano
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,45 @@
1
+ = DeadViewCatcher
2
+
3
+ DeadViewCatcher is a gem for Ruby on Rails giving you an easy way to find which views you are not using anymore in your app.
4
+ This might be really useful for big Rails app maintained by a large team.
5
+
6
+ Works with Rails 2.3 (Will be tested against Rails3 soon)
7
+
8
+ == Usage
9
+
10
+ Simply load the gem in your rails app.
11
+
12
+ Then instantiate DeadViewCatcher during the boot:
13
+
14
+ DeadViewCatcher.watch!
15
+
16
+ Now, at any time, you can send a TRAP signal to your rails instance in order to generate a dump of your views status:
17
+
18
+ kill -s TRAP pid_of_your_instance
19
+
20
+ If you want to generate a consolidated dump gathering data from all your Rails instances, just choose one instance and send it the URG signal:
21
+
22
+ kill -s URG pid_of_one_of_your_instances
23
+
24
+ == Options
25
+
26
+ The watch! method accepts some options :
27
+
28
+ # The correct grep string in order to select instances of your app for consolidated dumps
29
+ # This option is mandatory if you plan to use the consolidated dump feature
30
+ DeadViewCatcher.watch!(:grep => 'unicorn_rails worker')
31
+
32
+ # Change the default signal
33
+ DeadViewCatcher.watch!(:signal => 'USR1')
34
+
35
+ # Change the consolidated default signal
36
+ DeadViewCatcher.watch!(:all_instances_signal => 'USR2')
37
+
38
+ # Change the default file for the dump
39
+ DeadViewCatcher.watch!(:file => '/tmp/somewhere.txt')
40
+
41
+
42
+ When customizing the signal you want to catch, be careful when picking one, as your server might already catch some (like Unicorn does for USR1 and USR2).
43
+
44
+
45
+ Copyright (c) 2011 Guillaume Luccisano - g-mai|: guillaume.luccisano, released under the MIT license
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'dead_view_catcher'
@@ -0,0 +1,169 @@
1
+ module DeadViewCatcher
2
+
3
+ # DeadViewCatcher help you find easily not used views in your Rails app.
4
+ # It's not really Thread safe and using globals, but it's on purpose.
5
+
6
+ # Usage:
7
+ #
8
+ # Send a signal (TRAP by default) to one of your rails instance in order to create a dump of the dead views in tmp/dead_views.txt
9
+ # kill -s TRAP pid
10
+ #
11
+ # If you want a more globalized stats, you can use the all instances signal (URG by default)
12
+ # This signal will agregate the results of all instances by sending to all instances the TRAP signal.
13
+ # Then it will dump the consolidated stats in tmp/dead_views.txt (the default file)
14
+ #
15
+ # Note: SIGUSR1 and SIGUSR2 is not used as it's used by unicorn :/
16
+
17
+ DefaultOptions = {:signal => 'TRAP', :file => 'tmp/dead_views.txt', :all_instances_signal => 'URG'}
18
+
19
+ def self.watch!(opts = {})
20
+ options = DefaultOptions.merge(opts)
21
+
22
+ $dead_view_catcher_started_on = Time.now
23
+ $dead_view_catcher_nb_render = 0
24
+ $dead_view_catcher_views = build_views_hash
25
+ $dead_view_last_exception = nil
26
+
27
+ watch_signal!(options)
28
+ watch_all_instances_signal!(options) if !options[:grep].blank?
29
+
30
+ ActionView::Template.send :include, DeadViewCatcher::Extensions::ActionView
31
+ end
32
+
33
+ # Building the views hash (Only using app/views folders)
34
+ def self.build_views_hash
35
+ views = ActiveSupport::OrderedHash.new
36
+
37
+ Dir.glob(File.join(Rails.root, 'app', 'views', '**', '*')).each do |v|
38
+ if File.stat(v).file?
39
+ views[v.gsub(Rails.root, '').gsub(/^\//, '')] = 0
40
+ end
41
+ end
42
+
43
+ return views
44
+ end
45
+
46
+ def self.watch_signal!(options)
47
+ Signal.trap(options[:signal]) do
48
+ begin
49
+ puts ">> Dumping dead views..."
50
+ open(File.join(Rails.root, options[:file]), 'w+') do |fd|
51
+ fd.write(dump_hash($dead_view_catcher_views).to_yaml)
52
+ end
53
+ puts ">> Dead views dumped to #{options[:file]}"
54
+ rescue Exception => e
55
+ puts e.to_s + "\n" + e.backtrace.join("\n")
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.watch_all_instances_signal!(options)
61
+ Signal.trap(options[:all_instances_signal]) do
62
+ begin
63
+ puts ">> Starting gathering consolidated dead views..."
64
+ # Getting all process pids :
65
+ ps = `ps aux | grep -i "#{options[:grep]}"`.split("\n").select { |l| !l.index('grep') }
66
+ pids = ps.collect { |l| (l.split(/ +/, 2)[1].to_i rescue nil) }.compact - [Process.pid]
67
+
68
+ last_pid = Process.pid
69
+ total_hash = dump_hash
70
+ total_hash[:pids] = [last_pid]
71
+ total_hash[:nb_instances] = 1
72
+
73
+ pids.each do |p|
74
+ # Sending the signal to other instances
75
+ `kill -s #{options[:signal]} #{p}`
76
+
77
+ # Now waiting for the output
78
+ i = 0; l = nil
79
+ while (!(l = YAML.load_file(options[:file]) rescue nil) or l[:pid] != p) and i < 15
80
+ sleep 0.1
81
+ i += 1
82
+ end
83
+
84
+ if l and l[:pid] and l[:pid] != last_pid
85
+ puts " >> Agregating data from pid #{l[:pid]}"
86
+
87
+ # Agregating datas...
88
+ total_hash[:running_hours] += l[:running_hours]
89
+ total_hash[:views_rendered] += l[:views_rendered]
90
+ total_hash[:exception_caught] += l[:exception_caught]
91
+ total_hash[:pids] << l[:pid]
92
+ total_hash[:nb_instances] = total_hash[:pids].size
93
+ l[:complete_stats].each do |k, v|
94
+ total_hash[:complete_stats][k] += v
95
+ end
96
+
97
+ last_pid = l[:pid]
98
+ else
99
+ puts " >> pid #{l[:pid]} skiped.."
100
+ end
101
+ end
102
+
103
+ total_hash[:dead_views] = dead_views(total_hash[:complete_stats])
104
+
105
+ open(File.join(Rails.root, options[:file]), 'w+') do |fd|
106
+ fd.write(total_hash.to_yaml)
107
+ end
108
+ puts ">> Consolidated Dead views dumped to #{options[:file]}"
109
+ rescue Exception => e
110
+ puts e.to_s + "\n" + e.backtrace.join("\n")
111
+ end
112
+ end
113
+ end
114
+
115
+ def self.dead_views(h = nil)
116
+ h ||= $dead_view_catcher_views
117
+ deads = ActiveSupport::OrderedHash.new
118
+ h.keys.sort.each do |k|
119
+ if h[k] == 0
120
+ deads[k] = h[k]
121
+ end
122
+ end
123
+ deads
124
+ end
125
+
126
+ def self.dump_hash(dead_views_hash = nil)
127
+ dump = ActiveSupport::OrderedHash.new
128
+
129
+ dump[:running_hours] = ((Time.now - $dead_view_catcher_started_on) / 3600).round(2)
130
+ dump[:views_rendered] = $dead_view_catcher_nb_render
131
+ dump[:time] = Time.now
132
+ dump[:pid] = Process.pid
133
+ dump[:exception_caught] = [$dead_view_last_exception].compact
134
+ dump[:dead_views] = dead_views(dead_views_hash)
135
+ dump[:complete_stats] = $dead_view_catcher_views
136
+ dump
137
+ end
138
+
139
+ module Extensions
140
+ module ActionView
141
+
142
+ def self.included(mod)
143
+ mod.send :alias_method, :dead_view_catcher_render, :render
144
+ mod.send :define_method, :render do |*opts|
145
+ view_catcher_rendered
146
+ dead_view_catcher_render(*opts)
147
+ end
148
+ end
149
+
150
+ def view_catcher_rendered
151
+ begin
152
+ rp = relative_path
153
+ if rp and rp.index('app/views') == 0
154
+ $dead_view_catcher_nb_render += 1
155
+ #Rails.logger.info "Rendering and counting: #{rp}"
156
+ begin
157
+ $dead_view_catcher_views[rp] += 1
158
+ rescue
159
+ raise "Index: #{rp} doesn't exist in dead_view_catcher_views Hash"
160
+ end
161
+ end
162
+ rescue Exception => e
163
+ $dead_view_last_exception = e.to_s + "\n" + e.backtrace.join("\n")
164
+ end
165
+ end
166
+
167
+ end
168
+ end
169
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dead_view_catcher
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Guillaume Luccisano
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-12 00:00:00 -08:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: DeadViewCatcher is a gem for Ruby on Rails giving you an easy way to find which views you are not using anymore in your app. Might be really useful for big Rails app.
22
+ email: guillaume.luccisano@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/dead_view_catcher.rb
31
+ - CHANGELOG.rdoc
32
+ - MIT-LICENSE
33
+ - README.rdoc
34
+ - init.rb
35
+ has_rdoc: true
36
+ homepage: http://github.com/kwi/dead_view_catcher
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 3
50
+ segments:
51
+ - 0
52
+ version: "0"
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 19
59
+ segments:
60
+ - 1
61
+ - 3
62
+ - 4
63
+ version: 1.3.4
64
+ requirements: []
65
+
66
+ rubyforge_project: dead_view_catcher
67
+ rubygems_version: 1.4.1
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Find easily wich views you are not using anymore in your Rails app.
71
+ test_files: []
72
+