Skip to content

Commit

Permalink
Merge pull request #4034 from chef/lcg/ruby-profiling
Browse files Browse the repository at this point in the history
add optional ruby-profiling with --profile-ruby
  • Loading branch information
lamont-granquist committed Oct 13, 2015
2 parents 6d7adf9 + 51c6ba8 commit 92ba97d
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ group(:maintenance) do
end

group(:development, :test) do
# for profiling
gem "ruby-prof"

gem "simplecov"
gem 'rack', "~> 1.5.1"
Expand Down
6 changes: 6 additions & 0 deletions lib/chef/application/apply.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ class Chef::Application::Apply < Chef::Application
:description => 'Enable whyrun mode',
:boolean => true

option :profile_ruby,
:long => "--[no-]profile-ruby",
:description => "Dump complete Ruby call graph stack of entire Chef run (expert only)",
:boolean => true,
:default => false

option :color,
:long => '--[no-]color',
:boolean => true,
Expand Down
8 changes: 7 additions & 1 deletion lib/chef/application/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Author:: AJ Christensen (<aj@opscode.com)
# Author:: Christopher Brown (<cb@opscode.com>)
# Author:: Mark Mzyk (mmzyk@opscode.com)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -55,6 +55,12 @@ class Chef::Application::Client < Chef::Application
:boolean => true,
:default => false

option :profile_ruby,
:long => "--[no-]profile-ruby",
:description => "Dump complete Ruby call graph stack of entire Chef run (expert only)",
:boolean => true,
:default => false

option :color,
:long => '--[no-]color',
:boolean => true,
Expand Down
8 changes: 7 additions & 1 deletion lib/chef/application/solo.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# Author:: AJ Christensen (<aj@opscode.com>)
# Author:: Mark Mzyk (mmzyk@opscode.com)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
# Copyright:: Copyright (c) 2008-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -52,6 +52,12 @@ class Chef::Application::Solo < Chef::Application
:boolean => true,
:default => false

option :profile_ruby,
:long => "--[no-]profile-ruby",
:description => "Dump complete Ruby call graph stack of entire Chef run (expert only)",
:boolean => true,
:default => false

option :color,
:long => '--[no-]color',
:boolean => true,
Expand Down
27 changes: 27 additions & 0 deletions lib/chef/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ def initialize(json_attribs=nil, args={})
# @return Always returns true.
#
def run
start_profiling

run_error = nil

runlock = RunLock.new(Chef::Config.lockfile)
Expand Down Expand Up @@ -284,6 +286,9 @@ def run
run_completed_successfully
events.run_completed(node)

# keep this inside the main loop to get exception backtraces
end_profiling

# rebooting has to be the last thing we do, no exceptions.
Chef::Platform::Rebooter.reboot_if_needed!(node)
rescue Exception => run_error
Expand Down Expand Up @@ -891,6 +896,28 @@ def run_failed_notifications
attr_reader :override_runlist
attr_reader :specific_recipes

def profiling_prereqs!
require 'ruby-prof'
rescue LoadError
raise "You must have the ruby-prof gem installed in order to use --profile-ruby"
end

def start_profiling
return unless Chef::Config[:profile_ruby]
profiling_prereqs!
RubyProf.start
end

def end_profiling
return unless Chef::Config[:profile_ruby]
profiling_prereqs!
path = Chef::FileCache.create_cache_path("graph_profile.out", false)
File.open(path, "w+") do |file|
RubyProf::GraphPrinter.new(RubyProf.stop).print(file, {})
end
Chef::Log.warn("Ruby execution profile dumped to #{path}")
end

def empty_directory?(path)
!File.exists?(path) || (Dir.entries(path).size <= 2)
end
Expand Down
17 changes: 17 additions & 0 deletions spec/integration/client/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,23 @@ class ::Blah
result.error!
end

it "should complete with success when using --profile-ruby and output a profile file" do
file 'config/client.rb', <<EOM
local_mode true
cookbook_path "#{path_to('cookbooks')}"
EOM
result = shell_out!("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' -z --profile-ruby", :cwd => chef_dir)
expect(File.exist?(path_to("config/local-mode-cache/cache/graph_profile.out"))).to be true
end

it "doesn't produce a profile when --profile-ruby is not present" do
file 'config/client.rb', <<EOM
local_mode true
cookbook_path "#{path_to('cookbooks')}"
EOM
result = shell_out!("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' -z", :cwd => chef_dir)
expect(File.exist?(path_to("config/local-mode-cache/cache/graph_profile.out"))).to be false
end
end

when_the_repository "has a cookbook that generates deprecation warnings" do
Expand Down

0 comments on commit 92ba97d

Please sign in to comment.