lib/arborist/command/start.rb in arborist-0.0.1.pre20160128152542 vs lib/arborist/command/start.rb in arborist-0.0.1.pre20160606141735
- old
+ new
@@ -20,15 +20,19 @@
command :start do |cmd|
cmd.flag :loader, desc: "Specify a loader type to use.",
default_value: 'file'
+ cmd.desc "Run under the profiler in the given MODE (one of wall, cpu, or object; defaults to wall)."
+ cmd.arg_name :MODE
+ cmd.flag [:p, 'profiler'], must_match: ['wall', 'cpu', 'object']
+
cmd.action do |globals, options, args|
appname = args.shift
source = args.shift
- loader = Arborist::Loader.create( options.loader, source )
+ loader = Arborist::Loader.create( options[:loader], source )
runner = case appname
when 'manager'
Arborist.manager_for( loader )
when 'monitors'
Arborist.monitor_runner_for( loader )
@@ -37,11 +41,11 @@
else
raise "Don't know how to start %p" % [ appname ]
end
unless_dryrun( "starting #{appname}" ) do
- start( runner )
+ start( runner, options[:p] )
end
end
end
@@ -49,12 +53,54 @@
module_function
###############
### Start the specified +runner+ instance after setting up the environment for
### it.
- def start( runner )
- $0 = runner.class.name
- runner.run
+ def start( runner, profile_mode=nil )
+ Process.setproctitle( runner.class.name )
+
+ if profile_mode
+ self.with_profiling_enabled( profile_mode, runner ) do
+ runner.run
+ end
+ else
+ runner.run
+ end
end
+
+
+ ### Wrap the profiler around the specified +callable+.
+ def self::with_profiling_enabled( profile_arg, runner, &block )
+ require 'stackprof'
+ mode, outfile = self.parse_profile_args( profile_arg, runner )
+
+ self.log.info "Profiling in %s mode, outputting to %s" % [ mode, outfile ]
+ StackProf.run( mode: mode.to_sym, out: outfile, &block )
+ rescue LoadError => err
+ self.log.debug "%p while loading the StackProf profiler: %s"
+ exit_now!( "Couldn't load the profiler; you probably need to `gem install stackprof`", 254 )
+ end
+
+
+ ### Set up the StackProf profiler to run in the given +mode+.
+ def self::parse_profile_args( arg, runner )
+ profile_mode, profile_filename = arg.split( ':', 2 )
+ profile_filename ||= self.default_profile_filename( profile_mode, runner )
+
+ return profile_mode, profile_filename
+ end
+
+
+ ### Return a filename for a StackProf profile run over the given +runner+.
+ def self::default_profile_filename( mode, runner )
+ basename = runner.class.name.gsub( /.*::/, '' )
+ return "%s-%s-%s.%d.dump" % [
+ basename,
+ mode,
+ Time.now.strftime('%Y%m%d%H%M%S'),
+ Process.pid,
+ ]
+ end
+
end # module Arborist::CLI::Start