dike 0.0.1

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.
Files changed (7) hide show
  1. data/README +175 -0
  2. data/bin/dike +66 -0
  3. data/dike-0.0.1.gem +0 -0
  4. data/gemspec.rb +28 -0
  5. data/install.rb +210 -0
  6. data/lib/dike.rb +264 -0
  7. metadata +53 -0
data/README ADDED
@@ -0,0 +1,175 @@
1
+ NAME
2
+
3
+ dike
4
+
5
+ SYNOPSIS
6
+
7
+ a simple memory leak detector for ruby with preconfigured rails' hooks.
8
+
9
+ INSTALL
10
+
11
+ gem install dike
12
+
13
+ URIS
14
+
15
+ http://www.codeforpeople.com/lib/ruby/
16
+ http://rubyforge.org/projects/codeforpeople/
17
+
18
+ DESCRIPTION
19
+
20
+ the concept behind is simple: Object is extended in order that the location
21
+ of each objects' creation is tracked. a summarizer command is given to walk
22
+ ObjectSpace using each objects class and the location if it's creation to
23
+ detect memory leaks. not all leaks can be detected and some that are may
24
+ not really be leaks, but dike provided a simple way to see the hotspots in
25
+ your code that may potentially be leaking.
26
+
27
+ EXAMPLES
28
+
29
+ PURE RUBY
30
+
31
+ require 'dike'
32
+
33
+ Dike.log STDERR # the default
34
+
35
+ Thread.new do
36
+ sleep 4.2 and Dike.finger
37
+ end
38
+
39
+ Main.start
40
+
41
+
42
+ RAILS
43
+
44
+ file:RAILS_ROOT/config/environment.rb
45
+ ...
46
+ require 'dike'
47
+
48
+ shell: ./script/server
49
+
50
+ shell: curl --silent http://localhost:3000
51
+
52
+ shell: cat ./log/dike/0
53
+ ---
54
+ - class: String
55
+ count: 90769
56
+ trace: []
57
+ - class: Array
58
+ count: 18931
59
+ trace: []
60
+ - class: Class
61
+ count: 2
62
+ trace:
63
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:222:in `class_factory'
64
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `each'
65
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `class_factory'
66
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:248:in `Widget'
67
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets/page/base.rb:1
68
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `require'
69
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `load'
70
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:16:in `for_controller'
71
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:243:in `widget'
72
+ - /Users/ahoward/site/votelink.com/public/../config/../app/controllers/application.rb:150
73
+ ...
74
+
75
+ shell: curl --silent http://localhost:3000
76
+
77
+ shell: cat ./log/dike/1
78
+ ---
79
+ - class: String
80
+ count: 100769
81
+ trace: []
82
+ - class: Array
83
+ count: 19931
84
+ trace: []
85
+ - class: Class
86
+ count: 5
87
+ trace:
88
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:222:in `class_factory'
89
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `each'
90
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:220:in `class_factory'
91
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:248:in `Widget'
92
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets/page/base.rb:1
93
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `require'
94
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:31:in `load'
95
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:16:in `for_controller'
96
+ - /Users/ahoward/site/votelink.com/public/../config/../lib/widgets.rb:243:in `widget'
97
+ - /Users/ahoward/site/votelink.com/public/../config/../app/controllers/application.rb:150
98
+ ...
99
+
100
+ shell: dike ./log/dike
101
+ ---
102
+ - class: Proc
103
+ count: 65
104
+ trace:
105
+ - /opt/local/lib/ruby/1.8/cgi/session.rb:165:in `new'
106
+ - /opt/local/lib/ruby/1.8/cgi/session.rb:165:in `callback'
107
+ - /opt/local/lib/ruby/1.8/cgi/session.rb:299:in `initialize'
108
+ - /Users/ahoward/src/ruby/dike/dike-0.0.1/lib/dike.rb:233:in `new'
109
+ - /Users/ahoward/src/ruby/dike/dike-0.0.1/lib/dike.rb:233:in `call'
110
+ - /Users/ahoward/src/ruby/dike/dike-0.0.1/lib/dike.rb:233:in `new'
111
+ - /Users/ahoward/site/votelink.com/public/../config/../vendor/rails/actionpack/lib/action_contr oller/cgi_process.rb:123:in `session'
112
+ ...
113
+
114
+ SUMMARY
115
+
116
+ * the 'Dike.finger' method dumps it's log in a format showing
117
+
118
+ class : the class of object being leaked/allocated
119
+ count : the number instances leaked from the trace location
120
+ trace : the trace location of object birth
121
+
122
+ * loading into a rails environment causes snapshots of the above format to
123
+ be dumped into RAILS_ROOT/log/dike/ after each request. each snapshot is
124
+ incrementally numbered 0, 1, ...
125
+
126
+ * the 'dike' command line tool can be used in two ways
127
+
128
+ dike directory/with/logs/dike/
129
+
130
+ dike old_dump new_dump
131
+
132
+ if given a directory 'old_dump' and 'new_dump' are auto-calculated by
133
+ scanning the directory. in either case the tool dups a delta running old
134
+ -->> new. the delta shows only changes from old to new, so a line like
135
+
136
+ - class: Proc
137
+ count: 3
138
+ ...
139
+
140
+ means that 3 Proc objects were created between the two dumps. note that,
141
+ when given a directory, the default old and new dumps are the oldest and
142
+ newest dumps respectively, to get fine grained information sumarizing the
143
+ changes between two requests give the files manually, for example
144
+
145
+ dike ./log/dike/41 ./log/dike/42
146
+
147
+ * options that affect logging
148
+
149
+ - Dike.filter pattern
150
+
151
+ pattern must respond to '===' and each object in ObjectSpace will be
152
+ compared against it. for example
153
+
154
+ Dile.filter Array
155
+
156
+ would cause logging to restrict itself to Array, or sublcasses of
157
+ Array, only
158
+
159
+ - Dike.log io
160
+
161
+ set the dike logging object. the object should respond to 'puts'.
162
+
163
+ - Dike.logfactory directory
164
+
165
+ cause logging to occur into a new log for each call the 'Dike.finger'.
166
+ the logs will be auto numbered 0, 1, ...
167
+
168
+ LIMITATIONS
169
+
170
+ not all object creation can be tracked and not all leaks are reported.
171
+
172
+ AUTHOR
173
+
174
+ ara [dot] t [dot] howard [at] gmail [dot] com
175
+
data/bin/dike ADDED
@@ -0,0 +1,66 @@
1
+ #! /usr/bin/env ruby
2
+ require "yaml"
3
+ require "orderedhash"
4
+
5
+ ### TODO objectify - this is crap
6
+
7
+ ### parse argv
8
+ help = ARGV.delete("-h") || ARGV.delete("--help") || ARGV.delete("help")
9
+
10
+ a, b, *ignored = ARGV
11
+
12
+ if help or a.nil?
13
+ puts "dike (directory || old_dump new_dump)"
14
+ exit 42
15
+ end
16
+
17
+ ### load/determine files
18
+ if b
19
+ old_dump = a
20
+ new_dump = b
21
+ else
22
+ directory = a
23
+ Dir.chdir directory do
24
+ list = Dir.glob "*"
25
+ list = list.grep(%r/^[0-9]+$/).map{|entry| entry.to_i}
26
+ a, b = list.min, list.max
27
+ abort "not enough dumps" unless((a and b) and (a != b))
28
+ old_dump = File.join directory, a.to_s
29
+ new_dump = File.join directory, b.to_s
30
+ end
31
+ end
32
+
33
+ ### compute stats
34
+ a = open(old_dump){|fd| YAML.load fd}
35
+ a_index = {}
36
+ a.each{|record| a_index[record["trace"]] = record}
37
+
38
+ b = open(new_dump){|fd| YAML.load fd}
39
+ b_index = {}
40
+ b.each{|record| b_index[record["trace"]] = record}
41
+
42
+ ### generate report
43
+ report = []
44
+
45
+ (a_index.keys + b_index.keys).uniq.each do |trace|
46
+ record = OrderedHash.new
47
+
48
+ a_record = a_index[trace] || {}
49
+ b_record = b_index[trace] || {}
50
+
51
+ klass = a_record["class"] || b_record["class"]
52
+ count = b_record["count"].to_i - a_record["count"].to_i
53
+
54
+ next unless count > 0
55
+
56
+ record["class"] = klass
57
+ record["count"] = count
58
+ record["trace"] = trace.clone
59
+
60
+ report << record
61
+ end
62
+
63
+ report =
64
+ report.sort_by{|record| [-record["count"], record["class"]]}
65
+
66
+ y report
data/dike-0.0.1.gem ADDED
File without changes
data/gemspec.rb ADDED
@@ -0,0 +1,28 @@
1
+
2
+ lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
3
+
4
+ require 'rubygems'
5
+
6
+ Gem::Specification::new do |spec|
7
+ $VERBOSE = nil
8
+ spec.name = lib
9
+ spec.version = version
10
+ spec.platform = Gem::Platform::RUBY
11
+ spec.summary = lib
12
+
13
+ spec.files = Dir::glob "**/**"
14
+ spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
15
+
16
+ spec.require_path = "lib"
17
+ spec.autorequire = lib
18
+
19
+ spec.has_rdoc = File::exist? "doc"
20
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
21
+ #spec.add_dependency 'lib', '>= version'
22
+
23
+ spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
24
+
25
+ spec.author = "Ara T. Howard"
26
+ spec.email = "ara.t.howard@gmail.com"
27
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
28
+ end
data/install.rb ADDED
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if f =~ %r/\.lnk/
40
+ path.push f
41
+ dir |= [File.dirname(f)]
42
+ end
43
+ for f in dir
44
+ next if f == "."
45
+ next if f == "CVS"
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ for f in path
49
+ next if (/\~$/ =~ f)
50
+ next if (/^\./ =~ File.basename(f))
51
+ unless bin
52
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
+ else
54
+ from = File.join(srcdir, f)
55
+ to = File.join(destdir, f)
56
+ shebangify(from) do |sf|
57
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
58
+ $deferr.printf "chmod %04o %s\n", mode, to
59
+ File::install(sf, to, mode, false)
60
+ end
61
+ end
62
+ end
63
+ #}}}
64
+ end
65
+ def shebangify f
66
+ #{{{
67
+ open(f) do |fd|
68
+ buf = fd.read 42
69
+ if buf =~ %r/^\s*#\s*!.*ruby/o
70
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
+ begin
72
+ fd.rewind
73
+ ftmp.puts "#!#{ $ruby }"
74
+ while((buf = fd.read(8192)))
75
+ ftmp.write buf
76
+ end
77
+ ftmp.close
78
+ yield ftmp.path
79
+ ensure
80
+ ftmp.close!
81
+ end
82
+ else
83
+ yield f
84
+ end
85
+ end
86
+ #}}}
87
+ end
88
+ def ARGV.switch
89
+ #{{{
90
+ return nil if self.empty?
91
+ arg = self.shift
92
+ return nil if arg == '--'
93
+ if arg =~ /^-(.)(.*)/
94
+ return arg if $1 == '-'
95
+ raise 'unknown switch "-"' if $2.index('-')
96
+ self.unshift "-#{$2}" if $2.size > 0
97
+ "-#{$1}"
98
+ else
99
+ self.unshift arg
100
+ nil
101
+ end
102
+ #}}}
103
+ end
104
+ def ARGV.req_arg
105
+ #{{{
106
+ self.shift || raise('missing argument')
107
+ #}}}
108
+ end
109
+ def linkify d, linked = []
110
+ #--{{{
111
+ if test ?d, d
112
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
+ versioned.each do |v|
114
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
+ lnk = nil
116
+ begin
117
+ if test ?l, dst
118
+ lnk = "#{ dst }.lnk"
119
+ puts "#{ dst } -> #{ lnk }"
120
+ File::rename dst, lnk
121
+ end
122
+ unless test ?e, dst
123
+ puts "#{ src } -> #{ dst }"
124
+ File::copy src, dst
125
+ linked << dst
126
+ end
127
+ ensure
128
+ if lnk
129
+ at_exit do
130
+ puts "#{ lnk } -> #{ dst }"
131
+ File::rename lnk, dst
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ linked
138
+ #--}}}
139
+ end
140
+
141
+
142
+ #
143
+ # main program
144
+ #
145
+
146
+ libdir = $site_libdir
147
+ bindir = $bindir
148
+ no_linkify = false
149
+ linked = nil
150
+ help = false
151
+
152
+ usage = <<-usage
153
+ #{ File::basename $0 }
154
+ -d, --destdir <destdir>
155
+ -l, --libdir <libdir>
156
+ -b, --bindir <bindir>
157
+ -r, --ruby <ruby>
158
+ -n, --no_linkify
159
+ -s, --sudo
160
+ -h, --help
161
+ usage
162
+
163
+ begin
164
+ while switch = ARGV.switch
165
+ case switch
166
+ when '-d', '--destdir'
167
+ libdir = ARGV.req_arg
168
+ when '-l', '--libdir'
169
+ libdir = ARGV.req_arg
170
+ when '-b', '--bindir'
171
+ bindir = ARGV.req_arg
172
+ when '-r', '--ruby'
173
+ $ruby = ARGV.req_arg
174
+ when '-n', '--no_linkify'
175
+ no_linkify = true
176
+ when '-s', '--sudo'
177
+ sudo = 'sudo'
178
+ when '-h', '--help'
179
+ help = true
180
+ else
181
+ raise "unknown switch #{switch.dump}"
182
+ end
183
+ end
184
+ rescue
185
+ STDERR.puts $!.to_s
186
+ STDERR.puts usage
187
+ exit 1
188
+ end
189
+
190
+ if help
191
+ STDOUT.puts usage
192
+ exit
193
+ end
194
+
195
+ system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
196
+
197
+ unless no_linkify
198
+ linked = linkify('lib') + linkify('bin')
199
+ end
200
+
201
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
202
+
203
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
204
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
205
+
206
+ if linked
207
+ linked.each{|path| File::rm_f path}
208
+ end
209
+
210
+ system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
data/lib/dike.rb ADDED
@@ -0,0 +1,264 @@
1
+ require "yaml"
2
+ require "attributes"
3
+ require "orderedhash"
4
+
5
+ module Dike
6
+ class LogFactory
7
+ attribute "directory"
8
+ attribute "current"
9
+
10
+ def initialize directory = "dike"
11
+ require "fileutils"
12
+ FileUtils.mkdir_p directory
13
+ @directory = directory
14
+ list = Dir.glob(File.join(@directory, "*"))
15
+ list = list.grep(%r/^[0-9]+$/).map{|entry| entry.to_i}
16
+ @current = list.max || -1
17
+ end
18
+
19
+ def next &block
20
+ if block
21
+ open File.join(@directory, self.next.to_s), "w", &block
22
+ else
23
+ @current += 1
24
+ end
25
+ end
26
+ end
27
+
28
+ class << self
29
+ Objects = Hash.new
30
+
31
+ def mark_birth object, stacktrace
32
+ return if Objects[object_id]
33
+ object_id = Object::Methods["object_id"].bind(object).call
34
+ Objects[object_id] = stacktrace
35
+ ObjectSpace.define_finalizer object, &mark_birth_finalizer(object_id)
36
+ end
37
+
38
+ def mark_birth_finalizer object_id
39
+ lambda{ Objects.delete object_id }
40
+ end
41
+
42
+ Ignore = Hash.new
43
+
44
+ Ignore[Ignore.object_id] = true
45
+
46
+ class << Ignore
47
+ def transaction
48
+ state = clone
49
+ Ignore[state.object_id] = true
50
+ yield
51
+ ensure
52
+ clear
53
+ update state
54
+ Ignore.delete state.object_id
55
+ state = nil
56
+ end
57
+ end
58
+
59
+ def ignore *list
60
+ list.flatten.each do |object|
61
+ object_id = ::Object::Methods["object_id"].bind(object).call
62
+ Ignore[object_id] = true
63
+ #ObjectSpace.define_finalizer object, &ignore_finalizer(object_id)
64
+ end
65
+ end
66
+
67
+ def ignored &block
68
+ object = block.call
69
+ ignore object
70
+ object
71
+ end
72
+
73
+ def ignore_finalizer object_id
74
+ lambda{ Ignore.delete object_id }
75
+ end
76
+
77
+ attribute("filter"){ Object }
78
+ attribute("threshold"){ Struct.new(:class, :code, :object)[42, 42, 1] }
79
+ attribute("log"){ STDERR }
80
+ attribute("logfactory"){ nil }
81
+
82
+ def finger options = {}
83
+ Thread.critical = true
84
+
85
+ begin
86
+ GC.start
87
+
88
+ count, code = :remembered
89
+
90
+ Ignore.transaction do
91
+ count = Hash.new 0
92
+ ignore count
93
+
94
+ code = Hash.new do |h,k|
95
+ sh = Hash.new 0
96
+ ignore sh
97
+ h[k] = sh
98
+ end
99
+ ignore code
100
+
101
+ ObjectSpace.each_object(filter) do |object|
102
+ m = Object::Methods["object_id"].bind object
103
+ ignore m
104
+ object_id = m.call
105
+
106
+ next if Ignore[object_id]
107
+
108
+ m = Object::Methods["class"].bind object
109
+ ignore m
110
+ klass = m.call
111
+
112
+ defined_at = Objects[object_id]
113
+ count[klass] += 1
114
+ code[klass][defined_at] += 1
115
+ end
116
+ end
117
+
118
+ GC.start
119
+
120
+ worst_klasses =
121
+ count.to_a.sort_by{|pair| pair.last}.last(threshold.class).reverse
122
+
123
+ count.clear
124
+ count = nil
125
+
126
+ =begin
127
+ report = []
128
+ =end
129
+ total = 0
130
+
131
+ logging do |log|
132
+ log.puts "---"
133
+
134
+ worst_klasses.each do |klass, count|
135
+ worst_code = code[klass].to_a.sort_by{|pair| pair.last}.last(threshold.code).reverse
136
+
137
+ name = Class::Methods["name"].bind(klass).call.to_s
138
+ name = Class::Methods["inspect"].bind(klass).call.to_s if name.empty?
139
+ name = 'UNKNOWN' if name.empty?
140
+
141
+ worst_code.each do |stacktrace, count|
142
+ next unless count > threshold.object
143
+ =begin
144
+
145
+ TODO - figure out why the hell yaml leaks so bad!
146
+
147
+ report << OrderedHash[
148
+ 'class', name,
149
+ 'count', count,
150
+ 'stacktrace', (stacktrace ? stacktrace.clone : []),
151
+ ]
152
+ =end
153
+ trace = stacktrace ? stacktrace.clone : []
154
+
155
+ ### roll our own because yaml leaks!
156
+ log.puts "- class: #{ name }"
157
+ log.puts " count: #{ count }"
158
+ if trace.empty?
159
+ log.puts " trace: []"
160
+ else
161
+ log.puts " trace:"
162
+ trace.each do |line|
163
+ log.puts " - #{ line }"
164
+ end
165
+ end
166
+ end
167
+
168
+ worst_code.clear
169
+ worst_code = nil
170
+
171
+ total += count
172
+ end
173
+ end
174
+
175
+ =begin
176
+ logging do |log|
177
+ log.puts report.to_yaml
178
+ log.flush
179
+ end
180
+
181
+ report.clear
182
+ report = nil
183
+ GC.start
184
+ =end
185
+
186
+ worst_klasses.clear
187
+ worst_klasses = nil
188
+
189
+ code.clear
190
+ code = nil
191
+
192
+ GC.start
193
+
194
+ total
195
+ ensure
196
+ Thread.critical = false
197
+ end
198
+ end
199
+
200
+ def logging &block
201
+ logfactory ? logfactory.next(&block) : block.call(log)
202
+ end
203
+ end
204
+
205
+ class ::Object
206
+ Methods = instance_methods.inject(Hash.new){|h, m| h.update m => instance_method(m)}
207
+ Methods["initialize"] = instance_method "initialize"
208
+ Dike.ignore Methods
209
+ Methods.each{|k,v| Dike.ignore k, v}
210
+
211
+ verbose = $VERBOSE
212
+ begin
213
+ $VERBOSE = nil
214
+ def initialize *a, &b
215
+ Methods["initialize"].bind(self).call *a, &b
216
+ ensure
217
+ Dike.mark_birth self, caller rescue nil
218
+ end
219
+ ensure
220
+ $VERBOSE = verbose
221
+ end
222
+ end
223
+
224
+ class ::Class
225
+ Methods = instance_methods.inject(Hash.new){|h, m| h.update m => instance_method(m)}
226
+ Dike.ignore Methods
227
+ Methods.each{|k,v| Dike.ignore k, v}
228
+
229
+ verbose = $VERBOSE
230
+ begin
231
+ $VERBOSE = nil
232
+ def new *a, &b
233
+ object = Methods["new"].bind(self).call *a, &b
234
+ ensure
235
+ Dike.mark_birth object, caller rescue nil
236
+ end
237
+ def allocate *a, &b
238
+ object = Methods["allocate"].bind(self).call *a, &b
239
+ ensure
240
+ Dike.mark_birth object, caller rescue nil
241
+ end
242
+ ensure
243
+ $VERBOSE = verbose
244
+ end
245
+ end
246
+
247
+ class ::Module
248
+ Methods = instance_methods.inject(Hash.new){|h, m| h.update m => instance_method(m)}
249
+ Dike.ignore Methods
250
+ Methods.each{|k,v| Dike.ignore k, v}
251
+ end
252
+ end
253
+
254
+
255
+ if defined? Rails
256
+ Dike.logfactory Dike::LogFactory.new(File.join(RAILS_ROOT, "log", "dike"))
257
+
258
+ ActionController::Base.module_eval do
259
+ after_filter do |controller|
260
+ Dike.finger
261
+ true
262
+ end
263
+ end
264
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: dike
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-09-27 00:00:00 -06:00
8
+ summary: dike
9
+ require_paths:
10
+ - lib
11
+ email: ara.t.howard@gmail.com
12
+ homepage: http://codeforpeople.com/lib/ruby/dike/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: dike
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Ara T. Howard
31
+ files:
32
+ - bin
33
+ - bin/dike
34
+ - dike-0.0.1.gem
35
+ - gemspec.rb
36
+ - install.rb
37
+ - lib
38
+ - lib/dike.rb
39
+ - README
40
+ test_files: []
41
+
42
+ rdoc_options: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ executables:
47
+ - dike
48
+ extensions: []
49
+
50
+ requirements: []
51
+
52
+ dependencies: []
53
+