summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2015-10-05 17:22:09 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2015-10-05 17:22:09 -0700
commit130a94291555c03ca4775596ac940bac433b9174 (patch)
treef5051bfa89a8c6899ce9fdfa9ba3e56168277476
parent69cf21c8b35d7fb94775db377e810908e5fad54a (diff)
downloadchef-130a94291555c03ca4775596ac940bac433b9174.tar.gz
add optional ruby-profiling with --profile-ruby
dumps a large call graph into /var/chef/cache/graph_profile.out
-rw-r--r--Gemfile2
-rw-r--r--lib/chef/application/apply.rb6
-rw-r--r--lib/chef/application/client.rb8
-rw-r--r--lib/chef/application/solo.rb8
-rw-r--r--lib/chef/client.rb32
-rw-r--r--spec/integration/client/client_spec.rb17
6 files changed, 71 insertions, 2 deletions
diff --git a/Gemfile b/Gemfile
index 9d5cf0fea1..76f632976b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,6 +18,8 @@ group(:maintenance) do
end
group(:development, :test) do
+ # for profiling
+ gem "ruby-prof"
gem "simplecov"
gem 'rack', "~> 1.5.1"
diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb
index 243b441119..69129a4691 100644
--- a/lib/chef/application/apply.rb
+++ b/lib/chef/application/apply.rb
@@ -97,6 +97,12 @@ class Chef::Application::Apply < Chef::Application
:description => 'Enable whyrun mode',
:boolean => true
+ option :profile_ruby,
+ :long => "--[no-]profile-ruby",
+ :description => "Output ruby execution profile graph",
+ :boolean => true,
+ :default => false
+
option :color,
:long => '--[no-]color',
:boolean => true,
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 148257ab89..690340ca43 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -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");
@@ -55,6 +55,12 @@ class Chef::Application::Client < Chef::Application
:boolean => true,
:default => false
+ option :profile_ruby,
+ :long => "--[no-]profile-ruby",
+ :description => "Output ruby execution profile graph",
+ :boolean => true,
+ :default => false
+
option :color,
:long => '--[no-]color',
:boolean => true,
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index 5bb2a1ceb0..1fcc819068 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -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");
@@ -52,6 +52,12 @@ class Chef::Application::Solo < Chef::Application
:boolean => true,
:default => false
+ option :profile_ruby,
+ :long => "--[no-]profile-ruby",
+ :description => "Output ruby execution profile graph",
+ :boolean => true,
+ :default => false
+
option :color,
:long => '--[no-]color',
:boolean => true,
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index 7d5d463242..3315ae03dd 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -53,6 +53,11 @@ require 'chef/platform/rebooter'
require 'chef/mixin/deprecation'
require 'ohai'
require 'rbconfig'
+begin
+ require 'ruby-prof'
+rescue LoadError
+ # ruby-prof is optional.
+end
class Chef
# == Chef::Client
@@ -232,6 +237,8 @@ class Chef
# @return Always returns true.
#
def run
+ start_profiling
+
run_error = nil
runlock = RunLock.new(Chef::Config.lockfile)
@@ -284,6 +291,9 @@ class Chef
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
@@ -891,6 +901,28 @@ class Chef
attr_reader :override_runlist
attr_reader :specific_recipes
+ def profiling_prereqs!
+ if !defined? RubyProf
+ raise "You must have the ruby-prof gem installed in order to use --profile-ruby"
+ end
+ 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
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index 5b235e2720..314a9310be 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -301,6 +301,23 @@ EOM
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