rails_watcher_viewer 0.1.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/bin/rails_watcher_viewer +5 -0
- data/lib/rails_watcher_viewer.rb +10 -0
- data/lib/rails_watcher_viewer/public/bulma.css +10525 -0
- data/lib/rails_watcher_viewer/public/call-stack.js +216 -0
- data/lib/rails_watcher_viewer/public/react-dom.development.js +21413 -0
- data/lib/rails_watcher_viewer/public/react.development.js +3155 -0
- data/lib/rails_watcher_viewer/version.rb +3 -0
- data/lib/rails_watcher_viewer/views/call_stack.erb +9 -0
- data/lib/rails_watcher_viewer/views/detail.erb +11 -0
- data/lib/rails_watcher_viewer/views/layout.erb +38 -0
- data/lib/rails_watcher_viewer/views/list.erb +25 -0
- data/lib/rails_watcher_viewer/views/most_expensive_method_calls.erb +53 -0
- data/lib/rails_watcher_viewer/views/summary.erb +56 -0
- data/lib/rails_watcher_viewer/web_app.rb +42 -0
- metadata +73 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<h2 class="subtitle">
|
|
2
|
+
Call Stack
|
|
3
|
+
</h2>
|
|
4
|
+
<div id="call-stack"></div>
|
|
5
|
+
<script>
|
|
6
|
+
var callStackContainer = document.querySelector('#call-stack');
|
|
7
|
+
window.methodCallTable = <%= @method_call_table_json %>;
|
|
8
|
+
ReactDOM.render(React.createElement(CallStacks, {"stack": <%= @stack %>}), callStackContainer);
|
|
9
|
+
</script>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Rails Watcher</title>
|
|
7
|
+
<link rel="stylesheet" href="/bulma.css">
|
|
8
|
+
<script src="/react.development.js"></script>
|
|
9
|
+
<script src="/react-dom.development.js"></script>
|
|
10
|
+
<script src="/call-stack.js"></script>
|
|
11
|
+
<style>
|
|
12
|
+
.grad {
|
|
13
|
+
background: -webkit-linear-gradient(left, rgb(247, 172, 0), rgb(255, 255, 255));
|
|
14
|
+
background: -o-linear-gradient(left, rgb(247, 172, 0), rgb(255, 255, 255));
|
|
15
|
+
background: -moz-linear-gradient(left, rgb(247, 172, 0), rgb(255, 255, 255));
|
|
16
|
+
background: linear-gradient(left, rgb(247, 172, 0), rgb(255, 255, 255));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.call-stack {
|
|
20
|
+
display: inline-block;
|
|
21
|
+
padding: 5px 5px 5px 5px;
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<div class="container">
|
|
27
|
+
<h1 class="title">
|
|
28
|
+
Rails Watcher
|
|
29
|
+
</h1>
|
|
30
|
+
<p class="subtitle">
|
|
31
|
+
<a href="https://github.com/piecehealth/rails_watcher">https://github.com/piecehealth/rails_watcher</a>
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="container">
|
|
35
|
+
<%= yield %>
|
|
36
|
+
</div>
|
|
37
|
+
</body>
|
|
38
|
+
</html>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<table class="table">
|
|
2
|
+
<thead>
|
|
3
|
+
<tr>
|
|
4
|
+
<th>Request At</th>
|
|
5
|
+
<th>Request Path</th>
|
|
6
|
+
<th>Duration</th>
|
|
7
|
+
<th></th>
|
|
8
|
+
</tr>
|
|
9
|
+
</thead>
|
|
10
|
+
<tbody>
|
|
11
|
+
<% @list.each do |l| %>
|
|
12
|
+
<tr>
|
|
13
|
+
<td><%= l[0] %></td>
|
|
14
|
+
<td><%= l[1] %></td>
|
|
15
|
+
<% duration = l[2] %>
|
|
16
|
+
<td>
|
|
17
|
+
<div class="grad" style="width: <%= (duration / 10).round %>px;">
|
|
18
|
+
<%= duration.round(2) %> ms
|
|
19
|
+
</div>
|
|
20
|
+
</td>
|
|
21
|
+
<td><a href="/show/<%= l[3] %>">Detail</a></td>
|
|
22
|
+
</tr>
|
|
23
|
+
<% end %>
|
|
24
|
+
</tbody>
|
|
25
|
+
</table>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<%
|
|
2
|
+
call_table = {}
|
|
3
|
+
|
|
4
|
+
@method_call_table.each do |_, method_call|
|
|
5
|
+
method_tag = method_call["tag"]
|
|
6
|
+
call_table[method_tag] = [0, 0, 0] unless call_table[method_tag] # [duration, realDuration, count]
|
|
7
|
+
duration = method_call["duration"]
|
|
8
|
+
call_table[method_tag][0] += duration
|
|
9
|
+
|
|
10
|
+
method_call["children"].each do |child|
|
|
11
|
+
duration -= @method_call_table[child]["duration"]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
call_table[method_tag][1] += duration
|
|
15
|
+
call_table[method_tag][2] += 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
most_expensive_method_calls = call_table.keys.sort_by { |ele| -call_table[ele][1] }
|
|
19
|
+
%>
|
|
20
|
+
|
|
21
|
+
<h2 class="subtitle">
|
|
22
|
+
Expensive methods
|
|
23
|
+
</h2>
|
|
24
|
+
|
|
25
|
+
<table class="table">
|
|
26
|
+
<thead>
|
|
27
|
+
<tr>
|
|
28
|
+
<th>Method Name</th>
|
|
29
|
+
<th>How Many Times</th>
|
|
30
|
+
<th>Net Cost (ms)</th>
|
|
31
|
+
<th>Total Cost (ms)</th>
|
|
32
|
+
</tr>
|
|
33
|
+
</thead>
|
|
34
|
+
<tbody>
|
|
35
|
+
<% most_expensive_method_calls.each do |method_call_tag| %>
|
|
36
|
+
<tr>
|
|
37
|
+
<td>
|
|
38
|
+
<%
|
|
39
|
+
tag_name = if method_call_tag.size > 70
|
|
40
|
+
method_call_tag[0, 70] + "..."
|
|
41
|
+
else
|
|
42
|
+
method_call_tag
|
|
43
|
+
end
|
|
44
|
+
%>
|
|
45
|
+
<%= tag_name %>
|
|
46
|
+
</td>
|
|
47
|
+
<td><%= call_table[method_call_tag][2] %></td>
|
|
48
|
+
<td><%= call_table[method_call_tag][1].round 4 %></td>
|
|
49
|
+
<td><%= call_table[method_call_tag][0].round 4 %></td>
|
|
50
|
+
</tr>
|
|
51
|
+
<% end %>
|
|
52
|
+
</tbody>
|
|
53
|
+
</table>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<table class="table">
|
|
2
|
+
<%
|
|
3
|
+
captured_duration = @stack.reduce(0) do |sum, stack|
|
|
4
|
+
sum + @method_call_table[stack]["duration"]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
db_time = @db_query_table.values.reduce(0) do |sum, arr|
|
|
8
|
+
sum + arr.reduce(0) do |sum2, query|
|
|
9
|
+
sum2 + query["duration"]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
render_methods = @method_call_table.values.select { |method| method["tag"] == "render" }
|
|
14
|
+
|
|
15
|
+
render_duration = render_methods.reduce(0) do |sum, render_method|
|
|
16
|
+
sum + render_method["duration"]
|
|
17
|
+
end
|
|
18
|
+
%>
|
|
19
|
+
<tbody>
|
|
20
|
+
<tr>
|
|
21
|
+
<th>Request Path</th><td><%= @summary["request_path"] %></td>
|
|
22
|
+
</tr>
|
|
23
|
+
<tr>
|
|
24
|
+
<th>Total Duration (ms)</th>
|
|
25
|
+
<td>
|
|
26
|
+
<div class="grad" style="width: <%= (@summary["duration"].to_f / 10).round %>px;">
|
|
27
|
+
<%= @summary["duration"].to_f.round 4 %>
|
|
28
|
+
</div>
|
|
29
|
+
</td>
|
|
30
|
+
</tr>
|
|
31
|
+
<tr>
|
|
32
|
+
<th>Captured Duration (ms)</th>
|
|
33
|
+
<td>
|
|
34
|
+
<div class="grad" style="width: <%= (captured_duration / 10).round %>px;">
|
|
35
|
+
<%= captured_duration.round 4 %>
|
|
36
|
+
</div>
|
|
37
|
+
</td>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr>
|
|
40
|
+
<th>Database (ms)</th>
|
|
41
|
+
<td>
|
|
42
|
+
<div class="grad" style="width: <%= (db_time / 10).round %>px;">
|
|
43
|
+
<%= db_time.round 4 %>
|
|
44
|
+
</div>
|
|
45
|
+
</td>
|
|
46
|
+
</tr>
|
|
47
|
+
<tr>
|
|
48
|
+
<th>Render (ms)</th>
|
|
49
|
+
<td>
|
|
50
|
+
<div class="grad" style="width: <%= (render_duration / 10).round %>px;">
|
|
51
|
+
<%= render_duration.round 4 %>
|
|
52
|
+
</div>
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
</tbody>
|
|
56
|
+
</table>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'sinatra/base'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
module RailsWatcherViewer
|
|
5
|
+
|
|
6
|
+
class WebApp < Sinatra::Application
|
|
7
|
+
def self.path= path
|
|
8
|
+
@@path = path
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
get '/' do
|
|
12
|
+
page_size = 30
|
|
13
|
+
count = 0
|
|
14
|
+
requests = []
|
|
15
|
+
now = Time.now
|
|
16
|
+
Dir[File.join(@@path, "*")].sort_by{ |f| File.mtime(f) - now }.each do |request_folder|
|
|
17
|
+
summary_file = File.join(request_folder, "summary.json")
|
|
18
|
+
next unless File.exists? summary_file
|
|
19
|
+
# data sample
|
|
20
|
+
# {"duration":471.1509999997361,"request_path":"/","logged_time":"2019-04-09T22:59:36.749+08:00"}
|
|
21
|
+
data = File.open(summary_file) { |f| JSON.parse(f.read) }
|
|
22
|
+
requests << [data["logged_time"], data["request_path"], data["duration"], request_folder.sub(File.join(@@path).to_s + "/", "")]
|
|
23
|
+
end
|
|
24
|
+
@list = requests.reverse[0, 30]
|
|
25
|
+
erb :list
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
get '/show/:folder' do
|
|
29
|
+
%w[summary db_query_table method_call_table read_cache_table render_stack stack].each do |var|
|
|
30
|
+
path = File.join @@path, params[:folder], "#{var}.json"
|
|
31
|
+
json = File.open(path) { |f| f.read }
|
|
32
|
+
value = JSON.parse(json)
|
|
33
|
+
if var == "method_call_table"
|
|
34
|
+
@method_call_table_json = json
|
|
35
|
+
end
|
|
36
|
+
instance_variable_set(:"@#{var}", value)
|
|
37
|
+
end
|
|
38
|
+
erb :detail
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rails_watcher_viewer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- piecehealth
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-05-09 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: sinatra
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - '='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 2.0.5
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - '='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 2.0.5
|
|
27
|
+
description: Default viewer for Rails Watcher.
|
|
28
|
+
email:
|
|
29
|
+
- piecehealth@sina.com
|
|
30
|
+
executables:
|
|
31
|
+
- rails_watcher_viewer
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- MIT-LICENSE
|
|
36
|
+
- bin/rails_watcher_viewer
|
|
37
|
+
- lib/rails_watcher_viewer.rb
|
|
38
|
+
- lib/rails_watcher_viewer/public/bulma.css
|
|
39
|
+
- lib/rails_watcher_viewer/public/call-stack.js
|
|
40
|
+
- lib/rails_watcher_viewer/public/react-dom.development.js
|
|
41
|
+
- lib/rails_watcher_viewer/public/react.development.js
|
|
42
|
+
- lib/rails_watcher_viewer/version.rb
|
|
43
|
+
- lib/rails_watcher_viewer/views/call_stack.erb
|
|
44
|
+
- lib/rails_watcher_viewer/views/detail.erb
|
|
45
|
+
- lib/rails_watcher_viewer/views/layout.erb
|
|
46
|
+
- lib/rails_watcher_viewer/views/list.erb
|
|
47
|
+
- lib/rails_watcher_viewer/views/most_expensive_method_calls.erb
|
|
48
|
+
- lib/rails_watcher_viewer/views/summary.erb
|
|
49
|
+
- lib/rails_watcher_viewer/web_app.rb
|
|
50
|
+
homepage: https://github.com/piecehealth/rails_watcher_viewer
|
|
51
|
+
licenses:
|
|
52
|
+
- MIT
|
|
53
|
+
metadata: {}
|
|
54
|
+
post_install_message:
|
|
55
|
+
rdoc_options: []
|
|
56
|
+
require_paths:
|
|
57
|
+
- lib
|
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
requirements: []
|
|
69
|
+
rubygems_version: 3.0.1
|
|
70
|
+
signing_key:
|
|
71
|
+
specification_version: 4
|
|
72
|
+
summary: Default viewer for Rails Watcher.
|
|
73
|
+
test_files: []
|