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 +5 -5
- data/.gitignore +1 -0
- data/Gemfile.lock +8 -3
- data/README.md +14 -0
- data/Rakefile +14 -0
- data/lib/rbtrace/cli.rb +98 -9
- data/lib/rbtrace/memory_report.rb +20 -0
- data/lib/rbtrace/version.rb +1 -1
- data/rbtrace.gemspec +7 -0
- metadata +20 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: 574f273f971a108d9e994a3f236c3722a649d13093f75a371249dbe6556bc6f0
         | 
| 4 | 
            +
              data.tar.gz: 2aa00597a8016c8359276314b61d3bc43948f8db343423821b3015dcbe1be60b
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1c79741a8c653395f4b371caf63f1e1e2c67aa109446ee6365543aad68bd58508808768c5c28ba96eae3db5fa760c2914dc68e66d095bf6806e130ea50511577
         | 
| 7 | 
            +
              data.tar.gz: 7d4d8f89d2d6c63f635db87801d592a7bfffb2aa48f415e534a1ec3f9c30c55046315dd4394a804b91f7c81599d411ebab8f8168b3cbd8041b547d2b0c04a4ae
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                rbtrace (0.4. | 
| 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. | 
| 13 | 
            -
                msgpack ( | 
| 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_)
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -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 | 
            +
             | 
    
        data/lib/rbtrace/cli.rb
    CHANGED
    
    | @@ -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}  | 
| 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 | 
            -
                       | 
| 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 | 
            -
             | 
| 319 | 
            +
             | 
| 320 | 
            +
                      if filtered.length > 1
         | 
| 321 | 
            +
                        STDERR.print "*** trace which processes? (0/1,4): "
         | 
| 322 | 
            +
                      end
         | 
| 297 323 |  | 
| 298 324 | 
             
                      begin
         | 
| 299 | 
            -
                         | 
| 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 | | 
| 405 | 
            +
                        tracers.each do |pid1|
         | 
| 376 406 | 
             
                          begin
         | 
| 377 | 
            -
                            Process.kill 'INT',  | 
| 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
         | 
    
        data/lib/rbtrace/version.rb
    CHANGED
    
    
    
        data/rbtrace.gemspec
    CHANGED
    
    | @@ -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. | 
| 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- | 
| 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. | 
| 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'
         |