clientperf 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +3 -0
- data/Manifest +15 -0
- data/README.rdoc +50 -0
- data/Rakefile +14 -0
- data/bin/clientperf +31 -0
- data/clientperf.gemspec +45 -0
- data/init.rb +1 -0
- data/lib/clientperf.rb +46 -0
- data/lib/clientperf_controller.rb +42 -0
- data/lib/clientperf_result.rb +10 -0
- data/lib/clientperf_uri.rb +23 -0
- data/lib/extend_action_controller.rb +66 -0
- data/rails/init.rb +1 -0
- data/views/clientperf/index.html.erb +19 -0
- data/views/clientperf/show.html.erb +5 -0
- data/views/layouts/clientperf.html.erb +12 -0
- metadata +79 -0
data/History.rdoc
ADDED
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"
|
data/clientperf.gemspec
ADDED
@@ -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,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 %>" />
|
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
|
+
|