rbtrace 0.4.9 → 0.4.10

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
- 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'