Commits

Michael Granger committed 98671aa

Initial version

Comments (0)

Files changed (10)

+# .rvm.gems generated gem export file. Note that any env variable settings will be missing. Append these after using a ';' field separator
+
+strelka -v0.2.0.pre.362
+ruby-prof -v0.12.1
+
+#!/usr/bin/env bash
+
+# This is an RVM Project .rvmrc file, used to automatically load the ruby
+# development environment upon cd'ing into the directory
+
+environment_id="ruby-1.9.3@strelka-profiler"
+
+if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
+	&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]; then
+	echo "Using ${environment_id}"
+	. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
+
+	if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]; then
+		. "${rvm_path:-$HOME/.rvm}/hooks/after_use"
+	fi
+else
+	# If the environment file has not yet been created, use the RVM CLI to select.
+	if ! rvm --create use  "$environment_id"
+		then
+		echo "Failed to create RVM environment '${environment_id}'."
+		exit 1
+	fi
+fi
+
+filename=".rvm.gems"
+if [[ -s "$filename" ]]; then
+	rvm gemset import "$filename"
+fi
+
+echo "Figure out where your dog goes during the day."
+echo
+
+# Settings
+projectDirectory     = "$CWD"
+windowTitle          = "${CWD/^.*\///} «$TM_DISPLAYNAME»"
+excludeInFileChooser = "{$exclude,.hg,pkg}"
+
+TM_RUBY                  = "/Users/mgranger/.rvm/bin/rvm-auto-ruby"
+
+TM_RSPEC_OPTS            = '-rrspec/core/formatters/webkit -Ilib:../Mongrel2/lib'
+TM_RSPEC_FORMATTER       = 'RSpec::Core::Formatters::WebKit'
+
+[ source.ruby ]
+tabSize                  = 4
+softTabs                 = false
+
+[ source.ruby.rspec ]
+tabSize                  = 4
+softTabs                 = false
+
+[ source, source.ruby, source.ruby.rspec ]
+disableIndentCorrections = true
+
+
Empty file added.
+== v0.0.1 [2012-10-17] Michael Granger <ged@FaerieMUD.org>
+
+Initial release.
+
+ChangeLog
+History.rdoc
+Manifest.txt
+README.rdoc
+Rakefile
+lib/strelka/app/profiler.rb
+spec/strelka/app/profiler_spec.rb
+= Strelka Profiler Plugin
+
+home :: http://deveiate.org/projects/Strelka-Profiler]
+code :: https://bitbucket.org/ged/strelka-profiler
+github :: https://github.com/ged/strelka-profiler
+docs :: http://deveiate.org/code/strelka-profiler
+
+
+== Description
+
+Strelka-Profiler is a App plugin for the Strelka Web Application Framework
+that can generate a profile for a Strelka application.
+
+
+== Prerequisites
+
+* Strelka >= 0.2.0
+* Ruby-Prof
+
+
+== Installation
+
+    $ gem install strelka-profiler
+
+
+== Contributing
+
+You can check out the current development source with Mercurial via its
+{project page}[https://bitbucket.org/ged/strelka-profiler]. Or if you prefer
+Git, via {its Github mirror}[https://github.com/ged/strelka-profiler].
+
+After checking out the source, run:
+
+    $ rake newb
+
+This task will install any missing dependencies, run the tests/specs,
+and generate the API documentation.
+
+
+== License
+
+Copyright (c) 2013, Michael Granger
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of the author/s, nor the names of the project's
+  contributors may be used to endorse or promote products derived from this
+  software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#!/usr/bin/env rake
+
+begin
+	require 'hoe'
+rescue LoadError
+	abort "This Rakefile requires 'hoe' (gem install hoe)"
+end
+
+# Sign gems
+Hoe.plugin :signing
+Hoe.plugin :mercurial
+Hoe.plugin :deveiate
+
+hoespec = Hoe.spec 'strelka-profiler' do
+	self.readme_file = 'README.rdoc'
+	self.history_file = 'History.rdoc'
+	self.extra_rdoc_files = FileList[ '*.rdoc' ]
+
+	self.developer 'Michael Granger', 'ged@FaerieMUD.org'
+
+	self.dependency 'strelka', '~> 0.2'
+	self.dependency 'ruby-prof', '~> 0.12'
+	self.dependency 'hoe-deveiate', '~> 0.1', :developer
+
+	self.spec_extras[:licenses] = ["BSD"]
+	self.spec_extras[:rdoc_options] = ['-f', 'fivefish', '-t', 'Strelka Profiler Plugin']
+	self.require_ruby_version( '>=1.9.2' )
+	self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
+	self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
+
+	self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
+end
+
+ENV['VERSION'] ||= hoespec.spec.version.to_s
+
+# Ensure the specs pass before checking in
+task 'hg:precheckin' => [:check_manifest, :check_history, :spec]
+
+# Rebuild the ChangeLog immediately before release
+task :prerelease => [:check_manifest, :check_history, 'ChangeLog']
+
+task :check_manifest => 'ChangeLog'
+
+
+desc "Build a coverage report"
+task :coverage do
+	ENV["COVERAGE"] = 'yes'
+	Rake::Task[:spec].invoke
+end
+

lib/strelka/app/profiler.rb

+# -*- ruby -*-
+# vim: set nosta noet ts=4 sw=4:
+# encoding: utf-8
+
+require 'ruby-prof'
+require 'forwardable'
+require 'strelka' unless defined?( Strelka )
+require 'strelka/app' unless defined?( Strelka::App )
+
+
+# Strelka::App plugin module for Profiling requests.
+module Strelka::App::Profiler
+	extend Strelka::Plugin,
+	       Configurability
+
+
+	# Library version constant
+	VERSION = '0.0.1'
+
+	# Version-control revision constant
+	REVISION = %q$Revision$
+
+
+	### Set up the profiler if the request includes a 'profile' parameter.
+	def fixup_request( request )
+		if request.params['profile']
+			RubyProf.start
+			request.notes[:profiling] = true
+		end
+
+		super
+	end
+
+	### Replace the body of the response with the profile body if profiling is enabled.
+	def fixup_response( response )
+		if RubyProf.running?
+			profile = RubyProf.stop
+
+			response.body.truncate( 0 )
+			printer = RubyProf::CallStackPrinter.new( profile )
+			printer.print( response.body, min_percent: 2 )
+			response.content_type = 'text/html'
+		end
+
+		super
+	end
+
+end # module Strelka::App::Profiler
+
+

spec/strelka/app/profiler_spec.rb

+# -*- ruby -*-
+# vim: set nosta noet ts=4 sw=4:
+# encoding: utf-8
+
+BEGIN {
+	require 'pathname'
+	basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
+
+	srcdir = basedir.parent
+	strelkadir = srcdir + 'Strelka/lib'
+
+	$LOAD_PATH.unshift( strelkadir.to_s ) unless $LOAD_PATH.include?( strelkadir.to_s )
+	$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
+}
+
+require 'rspec'
+
+require 'strelka'
+require 'strelka/plugins'
+require 'strelka/app/profiler'
+
+require 'mongrel2/testing'
+require 'strelka/testing'
+require 'strelka/behavior/plugin'
+require 'loggability/spechelpers'
+
+### Mock with RSpec
+RSpec.configure do |c|
+	c.mock_with( :rspec )
+
+	c.include( Loggability::SpecHelpers )
+	c.include( Mongrel2::SpecHelpers )
+	c.include( Strelka::Testing )
+
+	include Mongrel2::Constants
+end
+
+
+#####################################################################
+###	C O N T E X T S
+#####################################################################
+
+describe Strelka::App::Profiler do
+
+	# 0mq socket specifications for Handlers
+	TEST_SEND_SPEC = 'tcp://127.0.0.1:9998'
+	TEST_RECV_SPEC = 'tcp://127.0.0.1:9997'
+
+
+	before( :all ) do
+		setup_logging()
+		@request_factory = Mongrel2::RequestFactory.new( route: '' )
+	end
+
+	after( :all ) do
+		reset_logging()
+	end
+
+
+	it_should_behave_like( "A Strelka::App Plugin" )
+
+
+	describe "an including App" do
+
+		before( :each ) do
+			@app = Class.new( Strelka::App ) do
+				plugin :profiler
+
+				def initialize( appid='profiler-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
+					super
+				end
+				def set_signal_handlers; end
+				def start_accepting_requests; end
+				def restore_signal_handlers; end
+
+				def handle_request( req, &block )
+					super do
+						res = req.response
+						res.puts "Normal output"
+						res
+					end
+				end
+			end
+		end
+
+
+		it "doesn't touch the response if the profile parameter is not present" do
+			request = @request_factory.get( '/foo' )
+			response = @app.new.handle( request )
+			response.status_line.should =~ /200 OK/
+
+			response.to_s.should =~ /content-length: 14/i
+			response.to_s.should =~ /Normal output\n/i
+		end
+
+		it "responds with profile HTML if the profile parameter is present" do
+			request = @request_factory.get( '/foo?profile=1' )
+			response = @app.new.handle( request )
+			response.status_line.should =~ /200 OK/
+
+			response.to_s.should_not =~ /content-length: 14\r\n/i
+			response.to_s.should =~ %r{<title>ruby-prof call tree</title>}i
+		end
+			
+	end
+
+end
+