perfmonger 0.6.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.
- checksums.yaml +15 -0
- data/.dir-locals.el +2 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +12 -0
- data/COPYING +674 -0
- data/Gemfile +5 -0
- data/HOWTO.md +15 -0
- data/NEWS +115 -0
- data/README.md +61 -0
- data/Rakefile +8 -0
- data/bin/perfmonger +6 -0
- data/data/NOTICE +8 -0
- data/data/Twitter_Bootstrap_LICENSE.txt +176 -0
- data/data/assets/css/bootstrap-responsive.css +1109 -0
- data/data/assets/css/bootstrap.css +6167 -0
- data/data/assets/css/perfmonger.css +17 -0
- data/data/assets/dashboard.erb +319 -0
- data/data/assets/img/glyphicons-halflings-white.png +0 -0
- data/data/assets/img/glyphicons-halflings.png +0 -0
- data/data/assets/js/bootstrap.js +2280 -0
- data/data/assets/js/bootstrap.min.js +6 -0
- data/data/assets/js/canvasjs.js +9042 -0
- data/data/assets/js/canvasjs.min.js +271 -0
- data/data/sysstat.ioconf +268 -0
- data/ext/perfmonger/extconf.rb +19 -0
- data/ext/perfmonger/perfmonger.h +58 -0
- data/ext/perfmonger/perfmonger_record.c +754 -0
- data/ext/perfmonger/sysstat/common.c +627 -0
- data/ext/perfmonger/sysstat/common.h +207 -0
- data/ext/perfmonger/sysstat/ioconf.c +515 -0
- data/ext/perfmonger/sysstat/ioconf.h +84 -0
- data/ext/perfmonger/sysstat/iostat.c +1100 -0
- data/ext/perfmonger/sysstat/iostat.h +121 -0
- data/ext/perfmonger/sysstat/libsysstat.h +19 -0
- data/ext/perfmonger/sysstat/mpstat.c +953 -0
- data/ext/perfmonger/sysstat/mpstat.h +79 -0
- data/ext/perfmonger/sysstat/rd_stats.c +2388 -0
- data/ext/perfmonger/sysstat/rd_stats.h +651 -0
- data/ext/perfmonger/sysstat/sysconfig.h +13 -0
- data/lib/perfmonger/cli.rb +115 -0
- data/lib/perfmonger/command/base_command.rb +39 -0
- data/lib/perfmonger/command/fingerprint.rb +453 -0
- data/lib/perfmonger/command/plot.rb +429 -0
- data/lib/perfmonger/command/record.rb +32 -0
- data/lib/perfmonger/command/record_option.rb +149 -0
- data/lib/perfmonger/command/server.rb +294 -0
- data/lib/perfmonger/command/stat.rb +60 -0
- data/lib/perfmonger/command/stat_option.rb +29 -0
- data/lib/perfmonger/command/summary.rb +402 -0
- data/lib/perfmonger/config.rb +6 -0
- data/lib/perfmonger/version.rb +5 -0
- data/lib/perfmonger.rb +12 -0
- data/misc/release-howto.txt +17 -0
- data/misc/sample-cpu.png +0 -0
- data/misc/sample-read-iops.png +0 -0
- data/perfmonger.gemspec +44 -0
- data/test/run-test.sh +39 -0
- data/test/spec/bin_spec.rb +37 -0
- data/test/spec/data/2devices.expected +42 -0
- data/test/spec/data/2devices.output +42 -0
- data/test/spec/spec_helper.rb +20 -0
- data/test/spec/summary_spec.rb +193 -0
- data/test/test-perfmonger.c +145 -0
- data/test/test.h +9 -0
- metadata +154 -0
| @@ -0,0 +1,294 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            require 'optparse'
         | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
            require 'webrick'
         | 
| 5 | 
            +
            require 'thread'
         | 
| 6 | 
            +
            require 'tmpdir'
         | 
| 7 | 
            +
            require 'fileutils'
         | 
| 8 | 
            +
            require 'erb'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            # monkey patching HTTPResponse for server-sent events
         | 
| 11 | 
            +
            class WEBrick::HTTPResponse
         | 
| 12 | 
            +
              CRLF = "\r\n"
         | 
| 13 | 
            +
              def send_body_io(socket)
         | 
| 14 | 
            +
                begin
         | 
| 15 | 
            +
                  if @request_method == "HEAD"
         | 
| 16 | 
            +
                    # do nothing
         | 
| 17 | 
            +
                  elsif chunked?
         | 
| 18 | 
            +
                    begin
         | 
| 19 | 
            +
                      buf  = ''
         | 
| 20 | 
            +
                      data = ''
         | 
| 21 | 
            +
                      while true
         | 
| 22 | 
            +
                        @body.readpartial( @buffer_size, buf ) # there is no need to clear buf?
         | 
| 23 | 
            +
                        data << format("%x", buf.bytesize) << CRLF
         | 
| 24 | 
            +
                        data << buf << CRLF
         | 
| 25 | 
            +
                        _write_data(socket, data)
         | 
| 26 | 
            +
                        data.clear
         | 
| 27 | 
            +
                        @sent_size += buf.bytesize
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    rescue EOFError # do nothing
         | 
| 30 | 
            +
                    rescue IOError # do nothing
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                    _write_data(socket, "0#{CRLF}#{CRLF}")
         | 
| 33 | 
            +
                  else
         | 
| 34 | 
            +
                    size = @header['content-length'].to_i
         | 
| 35 | 
            +
                    _send_file(socket, @body, 0, size)
         | 
| 36 | 
            +
                    @sent_size = size
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                ensure
         | 
| 39 | 
            +
                  begin; @body.close; rescue IOError; end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
             | 
| 45 | 
            +
            module PerfMonger
         | 
| 46 | 
            +
            module Command
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            class ServerCommand < BaseCommand
         | 
| 49 | 
            +
              register_command 'server', 'Launch self-contained HTML5 realtime graph server'
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              def initialize
         | 
| 52 | 
            +
                @parser = OptionParser.new
         | 
| 53 | 
            +
                @parser.banner = <<EOS
         | 
| 54 | 
            +
            Usage: perfmonger server [options] -- [perfmonger record options]
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            Launch TCP and HTTP server which enables users to get current
         | 
| 57 | 
            +
            perfmonger data record via network.
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            Options:
         | 
| 60 | 
            +
            EOS
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                @hostname = `hostname -f`.strip
         | 
| 63 | 
            +
                @http_hostname = nil
         | 
| 64 | 
            +
                @http_port = 20202
         | 
| 65 | 
            +
                @tcp_port  = 20203
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              def parse_args(argv)
         | 
| 69 | 
            +
                @parser.on('-H', '--hostname NAME', "Host name to display (default: #{@hostname})") do |hostname|
         | 
| 70 | 
            +
                  @hostname = hostname
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                @parser.on('--http-hostname NAME',
         | 
| 74 | 
            +
                           "Host name for HTTP server URL. If not specified, value of '--hostname' option is used.") do |hostname|
         | 
| 75 | 
            +
                  @http_hostname = hostname
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                @parser.on('--http-port PORT', 'HTTP server port to listen.') do |port|
         | 
| 79 | 
            +
                  if ! port =~ /\A\d+\Z/
         | 
| 80 | 
            +
                    puts("ERROR: invalid port number value: #{port}")
         | 
| 81 | 
            +
                    puts(@parser.help)
         | 
| 82 | 
            +
                    exit(false)
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                  @http_port = port.to_i
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                # @parser.on('--tcp-port PORT', 'TCP data server port to listen.') do |port|
         | 
| 88 | 
            +
                #   if ! port =~ /\A\d+\Z/
         | 
| 89 | 
            +
                #     puts("ERROR: invalid port number value: #{port}")
         | 
| 90 | 
            +
                #     puts(@parser.help)
         | 
| 91 | 
            +
                #     exit(false)
         | 
| 92 | 
            +
                #   end
         | 
| 93 | 
            +
                #   @tcp_port = port.to_i
         | 
| 94 | 
            +
                # end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                @parser.parse!(argv)
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                if @http_hostname.nil?
         | 
| 99 | 
            +
                  @http_hostname = @hostname
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                @record_cmd_args = argv
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
              def run(argv)
         | 
| 106 | 
            +
                tmp_rootdir = Dir.mktmpdir
         | 
| 107 | 
            +
                parse_args(argv)
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                _, record_option = PerfMonger::Command::RecordOption.parse(@record_cmd_args)
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                # find perfmonger command
         | 
| 112 | 
            +
                perfmonger_bin = File.expand_path('bin/perfmonger', PerfMonger::ROOTDIR)
         | 
| 113 | 
            +
                if ! File.executable?(perfmonger_bin)
         | 
| 114 | 
            +
                  puts("ERROR: perfmonger not found!")
         | 
| 115 | 
            +
                  exit(false)
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                record_cmd = [perfmonger_bin, 'record',
         | 
| 119 | 
            +
                              *@record_cmd_args]
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                @recorder = Recorder.new(record_cmd).start
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                puts("PerfMonger Realtime Monitor: http://#{@http_hostname}:#{@http_port}/dashboard")
         | 
| 124 | 
            +
                puts("")
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                @http_server =  WEBrick::HTTPServer.new({:DocumentRoot => tmp_rootdir,
         | 
| 127 | 
            +
                                                          :BindAddress => '0.0.0.0',
         | 
| 128 | 
            +
                                                          :Port => @http_port})
         | 
| 129 | 
            +
                setup_webrick(@http_server, record_option)
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                trap(:INT) do
         | 
| 132 | 
            +
                  @http_server.stop
         | 
| 133 | 
            +
                  @recorder.stop
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
                @http_server.start
         | 
| 136 | 
            +
              ensure
         | 
| 137 | 
            +
                FileUtils.rm_rf(tmp_rootdir)
         | 
| 138 | 
            +
              end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
              private
         | 
| 141 | 
            +
              class Recorder
         | 
| 142 | 
            +
                def initialize(record_cmd)
         | 
| 143 | 
            +
                  @current_record = nil
         | 
| 144 | 
            +
                  @mutex = Mutex.new
         | 
| 145 | 
            +
                  @cond = ConditionVariable.new
         | 
| 146 | 
            +
                  @thread = nil
         | 
| 147 | 
            +
                  @record_cmd = record_cmd
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  @working = false
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                def start
         | 
| 153 | 
            +
                  @mutex.synchronize do
         | 
| 154 | 
            +
                    if @thread.nil?
         | 
| 155 | 
            +
                      @thread = true
         | 
| 156 | 
            +
                      @working = true
         | 
| 157 | 
            +
                    else
         | 
| 158 | 
            +
                      return
         | 
| 159 | 
            +
                    end
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                  @thread = Thread.start do
         | 
| 163 | 
            +
                    begin
         | 
| 164 | 
            +
                      IO.popen(@record_cmd, "r") do |io|
         | 
| 165 | 
            +
                        io.each_line do |line|
         | 
| 166 | 
            +
                          @mutex.synchronize do
         | 
| 167 | 
            +
                            @current_perf_data = line.strip
         | 
| 168 | 
            +
                            @cond.broadcast
         | 
| 169 | 
            +
                          end
         | 
| 170 | 
            +
                        end
         | 
| 171 | 
            +
                      end
         | 
| 172 | 
            +
                    rescue Exception => err
         | 
| 173 | 
            +
                      puts("ERROR: Exception in record_thread(#{@record_thread}) in perfmonger-server")
         | 
| 174 | 
            +
                      puts("#{err.class.to_s}: #{err.message}")
         | 
| 175 | 
            +
                      puts(err.backtrace)
         | 
| 176 | 
            +
                    end
         | 
| 177 | 
            +
                  end
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                  self
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                def stop
         | 
| 183 | 
            +
                  @mutex.synchronize do
         | 
| 184 | 
            +
                    @working = false
         | 
| 185 | 
            +
                    @thread.terminate
         | 
| 186 | 
            +
                    @cond.broadcast
         | 
| 187 | 
            +
                  end
         | 
| 188 | 
            +
                end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                def get_current_record
         | 
| 191 | 
            +
                  @mutex.synchronize do
         | 
| 192 | 
            +
                    if @working
         | 
| 193 | 
            +
                      @cond.wait(@mutex)
         | 
| 194 | 
            +
                      current_perf_data = @current_perf_data
         | 
| 195 | 
            +
                    else
         | 
| 196 | 
            +
                      raise EOFError
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
                  end
         | 
| 199 | 
            +
                end
         | 
| 200 | 
            +
              end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
              class DashboardServlet < WEBrick::HTTPServlet::AbstractServlet
         | 
| 203 | 
            +
                def initialize(server, assets_dir, record_option, opt = {})
         | 
| 204 | 
            +
                  @assets_dir = assets_dir
         | 
| 205 | 
            +
                  @record_option = record_option
         | 
| 206 | 
            +
                  @opt = opt
         | 
| 207 | 
            +
                  super
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                def escape_device_name(dev)
         | 
| 211 | 
            +
                  dev.gsub(' ', '_').gsub('-', '_')
         | 
| 212 | 
            +
                end
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                def do_GET(req, res)
         | 
| 215 | 
            +
                  res.content_type = 'text/html'
         | 
| 216 | 
            +
                  res['cache-control'] = 'no-cache'
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                  # Variables for erb template
         | 
| 219 | 
            +
                  devices = @record_option.devices
         | 
| 220 | 
            +
                  report_cpu = @record_option.report_cpu
         | 
| 221 | 
            +
                  hostname = @opt[:hostname]
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                  erb = ERB.new(File.read(File.expand_path('dashboard.erb', @assets_dir)))
         | 
| 224 | 
            +
                  res.body = erb.result(Kernel.binding)
         | 
| 225 | 
            +
                end
         | 
| 226 | 
            +
              end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
              class FaucetServlet < WEBrick::HTTPServlet::AbstractServlet
         | 
| 229 | 
            +
                def initialize(server, recorder)
         | 
| 230 | 
            +
                  super(server)
         | 
| 231 | 
            +
                  @recorder = recorder
         | 
| 232 | 
            +
                end
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                def do_GET(req, res)
         | 
| 235 | 
            +
                  res.chunked = true
         | 
| 236 | 
            +
                  res.content_type = 'text/event-stream'
         | 
| 237 | 
            +
                  res['cache-control'] = 'no-cache'
         | 
| 238 | 
            +
                  r, w = IO.pipe
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                  Thread.start do
         | 
| 241 | 
            +
                    begin
         | 
| 242 | 
            +
                      while record = @recorder.get_current_record
         | 
| 243 | 
            +
                        w << "data: " << record << "\r\n" << "\r\n"
         | 
| 244 | 
            +
                      end
         | 
| 245 | 
            +
                    rescue Errno::EPIPE
         | 
| 246 | 
            +
                      # puts("Connection closed for /faucet")
         | 
| 247 | 
            +
                      # connection closed
         | 
| 248 | 
            +
                    rescue EOFError
         | 
| 249 | 
            +
                      # puts("Recorder has been terminated")
         | 
| 250 | 
            +
                      # connection closed
         | 
| 251 | 
            +
                    rescue Exception => err
         | 
| 252 | 
            +
                      puts("ERROR: Exception in faucet pipe writer")
         | 
| 253 | 
            +
                      puts("#{err.class.to_s}: #{err.message}")
         | 
| 254 | 
            +
                      puts(err.backtrace)
         | 
| 255 | 
            +
                    ensure
         | 
| 256 | 
            +
                      # puts("[FaucetServlet][do_GET] close w,r pipe")
         | 
| 257 | 
            +
                      begin; w.close; rescue IOError; end
         | 
| 258 | 
            +
                      begin; r.close; rescue IOError; end
         | 
| 259 | 
            +
                    end
         | 
| 260 | 
            +
                  end
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                  res.body = r
         | 
| 263 | 
            +
                end
         | 
| 264 | 
            +
              end
         | 
| 265 | 
            +
             | 
| 266 | 
            +
              def setup_webrick(webrick_server, record_option)
         | 
| 267 | 
            +
                # find assets dir
         | 
| 268 | 
            +
                # Search build environment first, then installed dir
         | 
| 269 | 
            +
                assets_dir = [File.expand_path('../../../../../data/assets', __FILE__),
         | 
| 270 | 
            +
                              File.expand_path('assets', PerfMonger::DATAROOTDIR)].find do |dir|
         | 
| 271 | 
            +
                  File.directory?(dir)
         | 
| 272 | 
            +
                end
         | 
| 273 | 
            +
                if assets_dir.nil?
         | 
| 274 | 
            +
                  puts("ERROR: Assets for PerfMonger monitor not found!")
         | 
| 275 | 
            +
                  exit(false)
         | 
| 276 | 
            +
                end
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                webrick_server.mount_proc('/') do |req, res|
         | 
| 279 | 
            +
                  puts("Request Path: " + req.path)
         | 
| 280 | 
            +
                  if req.path == '/favicon.ico'
         | 
| 281 | 
            +
                    res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, '/assets/favicon.ico')
         | 
| 282 | 
            +
                  else
         | 
| 283 | 
            +
                    res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, '/dashboard')
         | 
| 284 | 
            +
                  end
         | 
| 285 | 
            +
                end
         | 
| 286 | 
            +
                webrick_server.mount('/dashboard', DashboardServlet, assets_dir, record_option,
         | 
| 287 | 
            +
                                     :hostname => @hostname)
         | 
| 288 | 
            +
                webrick_server.mount('/assets', WEBrick::HTTPServlet::FileHandler, assets_dir)
         | 
| 289 | 
            +
                webrick_server.mount('/faucet', FaucetServlet, @recorder)
         | 
| 290 | 
            +
              end
         | 
| 291 | 
            +
            end
         | 
| 292 | 
            +
             | 
| 293 | 
            +
            end # module Command
         | 
| 294 | 
            +
            end # module PerfMonger
         | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            require 'optparse'
         | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module PerfMonger
         | 
| 6 | 
            +
            module Command
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            class StatCommand < BaseCommand
         | 
| 9 | 
            +
              register_command 'stat', "Run a command and record system performance during execution"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def initialize
         | 
| 12 | 
            +
                super
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def run(argv)
         | 
| 16 | 
            +
                @argv, @option = PerfMonger::Command::StatOption.parse(argv)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                if @argv.size == 0
         | 
| 19 | 
            +
                  puts("ERROR: No command given.")
         | 
| 20 | 
            +
                  exit(false)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                record_cmd = @option.make_command
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                begin
         | 
| 26 | 
            +
                  if RUBY_VERSION >= '1.9'
         | 
| 27 | 
            +
                    record_pid = Process.spawn(*record_cmd)
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    record_pid = Process.fork do
         | 
| 30 | 
            +
                      Process.exec(*record_cmd)
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  Signal.trap(:INT) do
         | 
| 35 | 
            +
                    Process.kill("INT", record_pid)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  @start_time = Time.now
         | 
| 39 | 
            +
                  if RUBY_VERSION >= '1.9'
         | 
| 40 | 
            +
                    command_pid = Process.spawn(*@argv)
         | 
| 41 | 
            +
                  else
         | 
| 42 | 
            +
                    command_pid = Process.fork do
         | 
| 43 | 
            +
                      system(*@argv)
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                  Process.wait(command_pid)
         | 
| 47 | 
            +
                ensure
         | 
| 48 | 
            +
                  @end_time = Time.now
         | 
| 49 | 
            +
                  Process.kill(:INT, record_pid)
         | 
| 50 | 
            +
                  Process.wait(record_pid)
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                puts("")
         | 
| 54 | 
            +
                printf("Execution time: %.4f\n", @end_time - @start_time)
         | 
| 55 | 
            +
                summary_command = SummaryCommand.new.run([@option.logfile], @argv.join(" "))
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
            end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            end # module Command
         | 
| 60 | 
            +
            end # module PerfMonger
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module PerfMonger
         | 
| 3 | 
            +
            module Command
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class StatOption < RecordOption
         | 
| 6 | 
            +
              attr_reader :json
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              private
         | 
| 9 | 
            +
              def initialize
         | 
| 10 | 
            +
                super()
         | 
| 11 | 
            +
                @parser.banner = <<EOS
         | 
| 12 | 
            +
            Usage: perfmonger stat [options] -- <command>
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            Run a command and gather performance information during its execution.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            Options:
         | 
| 17 | 
            +
            EOS
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                @logfile = './perfmonger.log'
         | 
| 20 | 
            +
                @json = false
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                @parser.on('--json', "Output summary in JSON") do
         | 
| 23 | 
            +
                  @json = true
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            end # module Command
         | 
| 29 | 
            +
            end # module PerfMonger
         |