rbtrace 0.4.9 → 0.4.10

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
- SHA1:
3
- metadata.gz: a8cd3dd5d2826625fbf017e93f76f52edbaa0b83
4
- data.tar.gz: 50b49986ffdeab614a9076c5f861738c9d4e4a70
2
+ SHA256:
3
+ metadata.gz: 574f273f971a108d9e994a3f236c3722a649d13093f75a371249dbe6556bc6f0
4
+ data.tar.gz: 2aa00597a8016c8359276314b61d3bc43948f8db343423821b3015dcbe1be60b
5
5
  SHA512:
6
- metadata.gz: ab75bcf6469ae23f80ec62e520e840710ef912e7080ef69474821e38077a9893a1a16d812048d3d47d990ffbe79e4d2dc075ed9367484835e240b35257f22dee
7
- data.tar.gz: 9a2ce4b26b191f1064ba30601a37f4b0f8e6490bb1dec9776720bbcd4935653c823db45f1381d09d0f00b9735a8c0bab31e772985da0524c7f72b7ed17d4ebf1
6
+ metadata.gz: 1c79741a8c653395f4b371caf63f1e1e2c67aa109446ee6365543aad68bd58508808768c5c28ba96eae3db5fa760c2914dc68e66d095bf6806e130ea50511577
7
+ data.tar.gz: 7d4d8f89d2d6c63f635db87801d592a7bfffb2aa48f415e534a1ec3f9c30c55046315dd4394a804b91f7c81599d411ebab8f8168b3cbd8041b547d2b0c04a4ae
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  *.gem
2
2
  .bundle
3
3
  ext/src/msgpack*
4
+ tmp/*
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbtrace (0.4.7)
4
+ rbtrace (0.4.10)
5
5
  ffi (>= 1.0.6)
6
6
  msgpack (>= 0.4.3)
7
7
  trollop (>= 1.16.2)
@@ -9,12 +9,17 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- ffi (1.9.8)
13
- msgpack (0.6.0)
12
+ ffi (1.9.18)
13
+ msgpack (1.2.2)
14
+ rake (10.5.0)
14
15
  trollop (2.1.2)
15
16
 
16
17
  PLATFORMS
17
18
  ruby
18
19
 
19
20
  DEPENDENCIES
21
+ rake (~> 10.0)
20
22
  rbtrace!
23
+
24
+ BUNDLED WITH
25
+ 1.16.1
data/README.md CHANGED
@@ -14,6 +14,11 @@ in production.
14
14
  % gem install rbtrace
15
15
  % rbtrace --help
16
16
 
17
+ ## supported Rubies
18
+
19
+ rbtrace supports all stable versions of Ruby MRI, as of 23-01-2018 this is
20
+ Ruby version 2.2 and later.
21
+
17
22
  ## tracer types
18
23
 
19
24
  rbtrace has several different tracing modes.
@@ -34,6 +39,14 @@ rbtrace has several different tracing modes.
34
39
 
35
40
  % rbtrace -p <PID> --gc
36
41
 
42
+ ### memory: produce a basic memory report regarding process (including GC.stat and ObjectSpace stats)
43
+
44
+ % rbtrace -p <PID> --memory
45
+
46
+ ### backtraces: return backtraces for all active threads in a process
47
+
48
+ % rbtrace -p <PID> --backtraces
49
+
37
50
  ### notes
38
51
 
39
52
  `--firehose` is not reliable on osx.
@@ -193,6 +206,7 @@ for popular ruby libraries and functions.
193
206
 
194
207
  ## todo
195
208
 
209
+ * correct irb implementation so it establishes a dedicated channel
196
210
  * add triggers to start tracing slow methods only inside another method
197
211
  * add watch expressions to fire tracers only when an expression is true
198
212
  * add special expressions for method args (_arg0_, _arguments_)
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc "Compile the c extension"
4
+ task :compile do
5
+ if File.exist?("ext/Makefile")
6
+ system "(cd ext && make clean)"
7
+ end
8
+ system "(cd ext && ruby extconf.rb)"
9
+ system "(cd ext && make)"
10
+ end
11
+
12
+ task :build => :compile
13
+
14
+
@@ -197,6 +197,12 @@ EOS
197
197
  :default => 'irb',
198
198
  :short => '-i'
199
199
 
200
+ opt :backtraces,
201
+ "get backtraces for all threads in current process, -1 denotes all frames",
202
+ :type => String,
203
+ :default => '-1',
204
+ :short => '-b'
205
+
200
206
  opt :backtrace,
201
207
  "get lines from the current backtrace in the process",
202
208
  :type => :int
@@ -209,6 +215,16 @@ EOS
209
215
  opt :timeout,
210
216
  "seconds to wait before giving up on attach/detach/eval",
211
217
  :default => 5
218
+
219
+ opt :memory,
220
+ "report on process memory usage"
221
+
222
+
223
+ opt :heapdump,
224
+ "generate a heap dump for the process in FILENAME",
225
+ :default => "AUTO",
226
+ :short => "-h"
227
+
212
228
  end
213
229
 
214
230
  opts = Trollop.with_standard_exception_handling(parser) do
@@ -224,8 +240,8 @@ EOS
224
240
  ARGV.clear
225
241
  end
226
242
 
227
- unless %w[ fork eval interactive backtrace slow slowcpu firehose methods config gc ].find{ |n| opts[:"#{n}_given"] }
228
- $stderr.puts "Error: --slow, --slowcpu, --gc, --firehose, --methods, --interactive or --config required."
243
+ unless %w[ fork eval interactive backtrace backtraces slow slowcpu firehose methods config gc memory heapdump].find{ |n| opts[:"#{n}_given"] }
244
+ $stderr.puts "Error: --slow, --slowcpu, --gc, --firehose, --methods, --interactive, --backtraces, --backtrace, --memory, --heapdump or --config required."
229
245
  $stderr.puts "Try --help for help."
230
246
  exit(-1)
231
247
  end
@@ -285,18 +301,32 @@ EOS
285
301
  if filtered.size > 0
286
302
  max_len = filtered.size.to_s.size
287
303
 
288
- STDERR.puts "*** found #{filtered.size} processes matching #{opts[:ps].inspect}"
304
+ STDERR.puts "*** found #{filtered.size} process#{filtered.size == 1 ? "" : "es"} matching #{opts[:ps].inspect}"
289
305
  filtered.each_with_index do |line, i|
290
- STDERR.puts " [#{(i+1).to_s.rjust(max_len)}] #{line.strip}"
306
+ prefix = " [#{(i+1).to_s.rjust(max_len)}] "
307
+ if filtered.length == 1
308
+ prefix = ""
309
+ end
310
+ STDERR.puts "#{prefix}#{line.strip}"
311
+ end
312
+
313
+ if filtered.length > 1
314
+ STDERR.puts " [#{'0'.rjust(max_len)}] all #{filtered.size} processes"
291
315
  end
292
- STDERR.puts " [#{'0'.rjust(max_len)}] all #{filtered.size} processes"
293
316
 
294
317
  while true
295
318
  STDERR.sync = true
296
- STDERR.print "*** trace which processes? (0/1,4): "
319
+
320
+ if filtered.length > 1
321
+ STDERR.print "*** trace which processes? (0/1,4): "
322
+ end
297
323
 
298
324
  begin
299
- input = gets
325
+ if filtered.length == 1
326
+ input = "1"
327
+ else
328
+ input = gets
329
+ end
300
330
  rescue Interrupt
301
331
  exit 1
302
332
  end
@@ -372,9 +402,9 @@ EOS
372
402
  end
373
403
  rescue Interrupt, SignalException
374
404
  STDERR.puts "*** waiting on child tracers: #{tracers.inspect}"
375
- tracers.each do |pid|
405
+ tracers.each do |pid1|
376
406
  begin
377
- Process.kill 'INT', pid
407
+ Process.kill 'INT', pid1
378
408
  rescue Errno::ESRCH
379
409
  end
380
410
  end
@@ -413,6 +443,65 @@ EOS
413
443
  tracer.puts res[1..-2].split('|').join("\n ")
414
444
  end
415
445
 
446
+ elsif opts[:backtraces_given]
447
+ num = opts[:backtraces].to_i
448
+ num = -1 if num == 0
449
+
450
+ delim = "146621c9d681409aa"
451
+
452
+ code = "Thread.list.map{|t| t.backtrace[0...#{num}].join(\"#{delim}\")}.join(\"#{delim*2}\")"
453
+
454
+ if res = tracer.eval(code)
455
+ tracer.puts res.split(delim).join("\n")
456
+ end
457
+
458
+ elsif opts[:memory_given]
459
+ memory_report = File.expand_path('../memory_report.rb', __FILE__)
460
+
461
+ require 'tempfile'
462
+ output = Tempfile.new("output")
463
+ output.close
464
+
465
+ begin
466
+ code = "Thread.new do; begin; output = '#{output.path}'; eval(File.read('#{memory_report}')); end; end"
467
+ tracer.eval(code)
468
+
469
+ File.open(output.path, 'r') do |f|
470
+ while true
471
+ begin
472
+ unless line = f.readline
473
+ sleep 0.1
474
+ next
475
+ end
476
+
477
+ if line.strip == "__END__"
478
+ break
479
+ else
480
+ print line
481
+ end
482
+ rescue EOFError
483
+ sleep 0.1
484
+ end
485
+ end
486
+ end
487
+ ensure
488
+ output.unlink
489
+ end
490
+
491
+ elsif opts[:heapdump_given]
492
+ filename = opts[:heapdump]
493
+
494
+ if filename == "AUTO"
495
+ require 'tempfile'
496
+ temp = Tempfile.new("dump")
497
+ filename = temp.path
498
+ temp.close
499
+ temp.unlink
500
+ end
501
+
502
+ tracer.eval("file = File.open('#{filename}', 'w'); ObjectSpace.dump_all(output: file); file.close")
503
+ puts "Heapdump being written to #{filename}"
504
+
416
505
  elsif opts[:eval_given]
417
506
  if res = tracer.eval(code = opts[:eval])
418
507
  tracer.puts ">> #{code}"
@@ -0,0 +1,20 @@
1
+ output
2
+ fork do
3
+ file = File.new(output, 'w')
4
+
5
+ file.puts "GC Stats",""
6
+ GC.stat.each do |k, v|
7
+ file.puts "#{k}: #{v}"
8
+ end
9
+
10
+ file.puts "", "Object Stats", ""
11
+ require 'objspace'
12
+ ObjectSpace.count_objects.sort{|a,b| b[1] <=> a[1]}.each do |k, v|
13
+ file.puts "#{k}: #{v}"
14
+ end
15
+
16
+
17
+ file.puts "__END__"
18
+ file.flush
19
+ file.close
20
+ end
@@ -1,3 +1,3 @@
1
1
  class RBTracer
2
- VERSION = '0.4.9'
2
+ VERSION = '0.4.10'
3
3
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../lib/rbtrace/version', __FILE__)
2
4
 
3
5
  Gem::Specification.new do |s|
@@ -8,16 +10,21 @@ Gem::Specification.new do |s|
8
10
  s.authors = 'Aman Gupta'
9
11
  s.email = 'aman@tmm1.net'
10
12
 
13
+ s.require_paths = ['lib', 'ext']
14
+
11
15
  s.files = `git ls-files`.split("\n")
12
16
  s.extensions = 'ext/extconf.rb'
13
17
 
14
18
  s.bindir = 'bin'
15
19
  s.executables << 'rbtrace'
16
20
 
21
+
17
22
  s.add_dependency 'ffi', '>= 1.0.6'
18
23
  s.add_dependency 'trollop', '>= 1.16.2'
19
24
  s.add_dependency 'msgpack', '>= 0.4.3'
20
25
 
26
+ s.add_development_dependency "rake", "~> 10.0"
27
+
21
28
  s.license = "MIT"
22
29
  s.summary = 'rbtrace: like strace but for ruby code'
23
30
  s.description = 'rbtrace shows you method calls happening inside another ruby process in real time.'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-03 00:00:00.000000000 Z
11
+ date: 2018-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.4.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
55
69
  description: rbtrace shows you method calls happening inside another ruby process
56
70
  in real time.
57
71
  email: aman@tmm1.net
@@ -66,6 +80,7 @@ files:
66
80
  - Gemfile.lock
67
81
  - LICENSE
68
82
  - README.md
83
+ - Rakefile
69
84
  - bin/rbtrace
70
85
  - ext/.gitignore
71
86
  - ext/extconf.rb
@@ -75,6 +90,7 @@ files:
75
90
  - lib/rbtrace/core_ext.rb
76
91
  - lib/rbtrace/interactive/irb.rb
77
92
  - lib/rbtrace/interactive/rib.rb
93
+ - lib/rbtrace/memory_report.rb
78
94
  - lib/rbtrace/msgq.rb
79
95
  - lib/rbtrace/rbtracer.rb
80
96
  - lib/rbtrace/version.rb
@@ -96,6 +112,7 @@ post_install_message:
96
112
  rdoc_options: []
97
113
  require_paths:
98
114
  - lib
115
+ - ext
99
116
  required_ruby_version: !ruby/object:Gem::Requirement
100
117
  requirements:
101
118
  - - ">="
@@ -108,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
125
  version: '0'
109
126
  requirements: []
110
127
  rubyforge_project:
111
- rubygems_version: 2.6.13
128
+ rubygems_version: 2.7.3
112
129
  signing_key:
113
130
  specification_version: 4
114
131
  summary: 'rbtrace: like strace but for ruby code'