clientperf 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+