clientperf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = History
2
+
3
+ * v0.0.1. Just in time for Austin on Rails
data/Manifest ADDED
@@ -0,0 +1,15 @@
1
+ bin/clientperf
2
+ History.rdoc
3
+ init.rb
4
+ lib/clientperf.rb
5
+ lib/clientperf_controller.rb
6
+ lib/clientperf_result.rb
7
+ lib/clientperf_uri.rb
8
+ lib/extend_action_controller.rb
9
+ Manifest
10
+ rails/init.rb
11
+ Rakefile
12
+ README.rdoc
13
+ views/clientperf/index.html.erb
14
+ views/clientperf/show.html.erb
15
+ views/layouts/clientperf.html.erb
data/README.rdoc ADDED
@@ -0,0 +1,50 @@
1
+ = clientperf
2
+
3
+ == Synopsis
4
+
5
+ Measures the time it takes a user's browser to get from the top of a web page to the window.onload event. This includes all asset requests.
6
+
7
+ == Installation
8
+
9
+ sudo gem install clientperf
10
+ clientperf /path/to/rails/app
11
+ rake db:migrate
12
+
13
+ == Usage
14
+
15
+ http://<site>/clientperf to view metrics
16
+
17
+ == Configuration
18
+
19
+ edit config/clientperf.yml
20
+
21
+ ---
22
+ username: bob
23
+ password: foo
24
+
25
+ this allows for http basic auth on the /clientperf url
26
+
27
+ == License
28
+
29
+ Copyright (c) 2008 Eric Falcao <efalcao@gmail.com>
30
+
31
+ Permission is hereby granted, free of charge, to any person
32
+ obtaining a copy of this software and associated documentation
33
+ files (the "Software"), to deal in the Software without
34
+ restriction, including without limitation the rights to use,
35
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
36
+ copies of the Software, and to permit persons to whom the
37
+ Software is furnished to do so, subject to the following
38
+ conditions:
39
+
40
+ The above copyright notice and this permission notice shall be
41
+ included in all copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
44
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
45
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
46
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
47
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
48
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
49
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
50
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ require File.dirname(__FILE__) << "/lib/clientperf"
5
+
6
+ Echoe.new 'clientperf' do |p|
7
+ p.version = Clientperf.version
8
+ p.author = "Eric Falcao"
9
+ p.email = 'efalcao@gmail.com'
10
+ p.project = 'clientperf'
11
+ p.summary = "Instrumentation for the FiveRuns TuneUp product."
12
+ p.url = "http://github.com/efalcao/clientperf"
13
+ p.include_rakefile = true
14
+ end
data/bin/clientperf ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fileutils'
3
+ require File.dirname(__FILE__) << "/../lib/clientperf"
4
+ require File.dirname(__FILE__) << "/../lib/clientperf_config"
5
+ require File.dirname(__FILE__) << "/../lib/clientperf_migraions"
6
+
7
+ # For older Rails versions
8
+ # USAGE: clientperf [RAILS_ROOT]
9
+ rails_dir = ARGV[0] || Dir.pwd
10
+ plugin_dir = File.join(rails_dir, 'vendor/plugins')
11
+ unless File.directory?(plugin_dir)
12
+ abort "clientperf: #{plugin_dir} does not exist; cannot install plugin"
13
+ end
14
+
15
+ FileUtils.rm_rf File.join(plugin_dir, 'clientperf') rescue nil
16
+
17
+ File.readlines(File.dirname(__FILE__) << "/../Manifest").each do |line|
18
+ stub = line.strip
19
+ origin = File.dirname(__FILE__) << "/../#{stub}"
20
+ next if origin =~ /\/clientperf$/
21
+ if File.file?(origin)
22
+ destination = File.join(plugin_dir, 'clientperf', stub)
23
+ FileUtils.mkdir_p File.dirname(destination)
24
+ FileUtils.cp origin, destination
25
+ end
26
+ end
27
+
28
+ ClientperfMigrations.install(rails_dir)
29
+ ClientperfConfig.create_unless_exists
30
+
31
+ STDERR.puts "Installed clientperf (v#{Clientperf.version}) in vendor/plugins/clientperf"
@@ -0,0 +1,45 @@
1
+
2
+ # Gem::Specification for Clientperf-0.0.1
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{clientperf}
7
+ s.version = "0.0.1"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Eric Falcao"]
13
+ s.date = %q{2008-06-18}
14
+ s.default_executable = %q{clientperf}
15
+ s.description = %q{Instrumentation for the FiveRuns TuneUp product.}
16
+ s.email = %q{efalcao@gmail.com}
17
+ s.executables = ["clientperf"]
18
+ s.extra_rdoc_files = ["bin/clientperf", "lib/clientperf.rb", "lib/clientperf_controller.rb", "lib/clientperf_result.rb", "lib/clientperf_uri.rb", "lib/extend_action_controller.rb", "README.rdoc"]
19
+ s.files = ["bin/clientperf", "History.rdoc", "init.rb", "lib/clientperf.rb", "lib/clientperf_controller.rb", "lib/clientperf_result.rb", "lib/clientperf_uri.rb", "lib/extend_action_controller.rb", "Manifest", "rails/init.rb", "Rakefile", "README.rdoc", "views/clientperf/index.html.erb", "views/clientperf/show.html.erb", "views/layouts/clientperf.html.erb", "clientperf.gemspec"]
20
+ s.has_rdoc = true
21
+ s.homepage = %q{http://github.com/efalcao/clientperf}
22
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Clientperf", "--main", "README.rdoc"]
23
+ s.require_paths = ["lib"]
24
+ s.rubyforge_project = %q{clientperf}
25
+ s.rubygems_version = %q{1.0.1}
26
+ s.summary = %q{Instrumentation for the FiveRuns TuneUp product.}
27
+ end
28
+
29
+
30
+ # # Original Rakefile source (requires the Echoe gem):
31
+ #
32
+ # require 'rubygems'
33
+ # require 'echoe'
34
+ #
35
+ # require File.dirname(__FILE__) << "/lib/clientperf"
36
+ #
37
+ # Echoe.new 'clientperf' do |p|
38
+ # p.version = Clientperf.version
39
+ # p.author = "Eric Falcao"
40
+ # p.email = 'efalcao@gmail.com'
41
+ # p.project = 'clientperf'
42
+ # p.summary = "Instrumentation for the FiveRuns TuneUp product."
43
+ # p.url = "http://github.com/efalcao/clientperf"
44
+ # p.include_rakefile = true
45
+ # end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) << "/rails/init"
data/lib/clientperf.rb ADDED
@@ -0,0 +1,46 @@
1
+ module Clientperf
2
+
3
+ class << self
4
+ def load
5
+ if supported_rails_version?
6
+ require 'dispatcher'
7
+ Dispatcher.to_prepare :clientperf_route do
8
+ ActionController::Routing::Routes.add_route '/clientperf', :controller => 'clientperf', :action => 'index'
9
+ ActionController::Routing::Routes.add_route '/clientperf/measure.gif', :controller => 'clientperf', :action => 'measure'
10
+ ActionController::Routing::Routes.add_route '/clientperf/reset', :controller => 'clientperf', :action => 'reset'
11
+ ActionController::Routing::Routes.add_route '/clientperf/:id', :controller => 'clientperf', :action => 'show'
12
+ ActionController::Routing::Routes.add_route '/clientperf/:id/reset', :controller => 'clientperf', :action => 'reset'
13
+ 5.times do
14
+ route = ActionController::Routing::Routes.routes.pop
15
+ ActionController::Routing::Routes.routes.unshift(route)
16
+ end
17
+ end
18
+
19
+ Dispatcher.to_prepare :clientperf_controller_filters do
20
+ ClientperfController.filter_chain.clear
21
+ ClientperfController.before_filter :authenticate
22
+ end
23
+
24
+ ActionController::Base.append_view_path(File.dirname(__FILE__) << "/../views")
25
+ ActionController::Base.send! :include, ExtendActionController
26
+ end
27
+ end
28
+
29
+ def version
30
+ "0.0.1"
31
+ end
32
+
33
+ private
34
+
35
+ def supported_rails_version?
36
+ version = Rails::VERSION rescue nil
37
+ return true unless version
38
+ if version::MAJOR < 2
39
+ STDERR.puts "[clientperf] rails < 2.0 not supported. skipping load."
40
+ false
41
+ else
42
+ true
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ class ClientperfController < ActionController::Base
2
+ def index
3
+ @uris = ClientperfUri.find(:all, :include => :clientperf_results)
4
+ end
5
+
6
+ def show
7
+ @uri = ClientperfUri.find(params[:id], :include => :clientperf_results)
8
+ end
9
+
10
+ def reset
11
+ if request.post?
12
+ if params[:id]
13
+ ClientperfUri.destroy(params[:id])
14
+ else
15
+ ClientperfUri.destroy_all
16
+ end
17
+ end
18
+ redirect_to :action => 'index'
19
+ end
20
+
21
+ def measure
22
+ milliseconds = params[:e].to_i - params[:b].to_i rescue nil
23
+ if milliseconds && params[:u]
24
+ uri = ClientperfUri.find_or_create_by_uri(params[:u])
25
+ ClientperfResult.create(:milliseconds => milliseconds, :clientperf_uri => uri)
26
+ end
27
+ render :nothing => true
28
+ end
29
+
30
+ private
31
+
32
+ def authenticate
33
+ return true if action_name == 'measure'
34
+
35
+ config = ClientperfConfig.new
36
+ if config.has_auth?
37
+ authenticate_or_request_with_http_basic do |user_name, password|
38
+ user_name == config['username'] && password == config['password']
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ class ClientperfResult < ActiveRecord::Base
2
+ belongs_to :clientperf_uri
3
+ after_create :update_uri
4
+
5
+ private
6
+
7
+ def update_uri
8
+ clientperf_uri.update_attribute(:updated_at, Time.now)
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ class ClientperfUri < ActiveRecord::Base
2
+ has_many :clientperf_results, :dependent => :delete_all
3
+
4
+ def result_average
5
+ @result_average ||= clientperf_results.inject(0) {|sum, result| sum += result.milliseconds; next sum} / clientperf_results.size
6
+ end
7
+
8
+ def chart_url
9
+ "http://chart.apis.google.com/chart?cht=ls&chs=300x200&chd=s:#{chart_data}"
10
+ end
11
+
12
+ private
13
+
14
+ def chart_data
15
+ encode = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
16
+ max_value = clientperf_results.max {|a, b| a.milliseconds <=> b.milliseconds}.milliseconds + 10
17
+
18
+ clientperf_results.map do |result|
19
+ char = 62 * result.milliseconds / max_value.to_f
20
+ encode[char.round,1]
21
+ end.join
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ module ExtendActionController
2
+ def self.included(base)
3
+ base.alias_method_chain :process, :clientperf
4
+ end
5
+
6
+ def process_with_clientperf(request, response, *args, &block)
7
+ result = process_without_clientperf(request, response, *args, &block)
8
+ if add_clientperf?(request, response)
9
+ add_clientperf_to(response)
10
+ end
11
+ result
12
+ end
13
+
14
+ def add_clientperf_to(response)
15
+ if response.body =~ /<html[^>]*?>/im
16
+ replacement = %q(\1
17
+ <script type='text/javascript'>
18
+ var clientPerfStart = (new Date()).getTime();
19
+ var clientPerf = function() {
20
+ var attach = function(instance, eventName, listener) {
21
+ var listenerFn = listener;
22
+ if (instance.addEventListener) {
23
+ instance.addEventListener(eventName, listenerFn, false);
24
+ }
25
+ else if (instance.attachEvent) { // Internet explorer
26
+ listenerFn = function() {
27
+ listener(window.event);
28
+ };
29
+ instance.attachEvent("on" + eventName, listenerFn);
30
+ }
31
+ else {
32
+ // I could do some further attachment here, if I wanted too. for older browsers
33
+ // ex: instance['on' + eventName] = listener;
34
+ throw new Error("Event registration not supported");
35
+ }
36
+ };
37
+
38
+ var endRun = function() {
39
+ var clientPerfEnd = (new Date()).getTime();
40
+ var img = document.createElement('img');
41
+ img.src = '/clientperf/measure.gif?b=' + clientPerfStart + '&e=' + clientPerfEnd + '&u=' + location.href;
42
+ document.body.appendChild(img);
43
+ };
44
+
45
+ try {
46
+ attach(window, 'load', endRun);
47
+ }
48
+ catch(e) {
49
+ window.onload = endRun;
50
+ }
51
+ }
52
+ clientPerf();
53
+ </script>
54
+ )
55
+
56
+ response.body.sub!(/(<html[^>]*?>)/im, replacement)
57
+ response.headers["Content-Length"] = response.body.size
58
+ end
59
+ end
60
+
61
+ def add_clientperf?(request, response)
62
+ !request.xhr? && response.content_type && response.content_type.include?('html') &&
63
+ response.body && response.headers['Status'] && response.headers['Status'].include?('200') &&
64
+ controller_name != 'clientperf'
65
+ end
66
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ Clientperf.load
@@ -0,0 +1,19 @@
1
+ <%= button_to "Reset all data", {:action => 'reset'}, :confirm => "are you sure?" %>
2
+ <table>
3
+ <tr>
4
+ <td>URI</td>
5
+ <td># of times measured</td>
6
+ <td>avg. client time (ms)</td>
7
+ <td>first measured</td>
8
+ <td>last measured</td>
9
+ </tr>
10
+ <% @uris.each do |uri| %>
11
+ <tr>
12
+ <td><%= link_to uri.uri, "/clientperf/#{uri.id}" %></td>
13
+ <td><%= uri.clientperf_results.size %></td>
14
+ <td><%= uri.result_average %></td>
15
+ <td><%= uri.created_at.strftime("%M/%d/%y") %></td>
16
+ <td><%= uri.updated_at.strftime("%M/%d/%y") %></td>
17
+ </tr>
18
+ <% end %>
19
+ </table>
@@ -0,0 +1,5 @@
1
+ <%= button_to "Reset this URI", {:action => 'reset', :id => @uri.id}, :confirm => "are you sure?" %>
2
+ <h1><%= @uri.uri %></h1>
3
+ <h3>times measured: <%= @uri.clientperf_results.size %></h3>
4
+ <h3>average time: <%= @uri.result_average %>ms</h3>
5
+ <img src="<%= @uri.chart_url %>" />
@@ -0,0 +1,12 @@
1
+ <html>
2
+ <head>
3
+ <title></title>
4
+ <style type="text/css">
5
+ </style>
6
+ </head>
7
+ <body>
8
+ <h1>clientperf</h1>
9
+ <h3>a measurement tool for client-side performance</h3>
10
+ <%= yield %>
11
+ </body>
12
+ </html>
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clientperf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eric Falcao
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-18 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Instrumentation for the FiveRuns TuneUp product.
17
+ email: efalcao@gmail.com
18
+ executables:
19
+ - clientperf
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - bin/clientperf
24
+ - lib/clientperf.rb
25
+ - lib/clientperf_controller.rb
26
+ - lib/clientperf_result.rb
27
+ - lib/clientperf_uri.rb
28
+ - lib/extend_action_controller.rb
29
+ - README.rdoc
30
+ files:
31
+ - bin/clientperf
32
+ - History.rdoc
33
+ - init.rb
34
+ - lib/clientperf.rb
35
+ - lib/clientperf_controller.rb
36
+ - lib/clientperf_result.rb
37
+ - lib/clientperf_uri.rb
38
+ - lib/extend_action_controller.rb
39
+ - Manifest
40
+ - rails/init.rb
41
+ - Rakefile
42
+ - README.rdoc
43
+ - views/clientperf/index.html.erb
44
+ - views/clientperf/show.html.erb
45
+ - views/layouts/clientperf.html.erb
46
+ - clientperf.gemspec
47
+ has_rdoc: true
48
+ homepage: http://github.com/efalcao/clientperf
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --line-numbers
52
+ - --inline-source
53
+ - --title
54
+ - Clientperf
55
+ - --main
56
+ - README.rdoc
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project: clientperf
74
+ rubygems_version: 1.0.1
75
+ signing_key:
76
+ specification_version: 2
77
+ summary: Instrumentation for the FiveRuns TuneUp product.
78
+ test_files: []
79
+