akainaa 0.1.0 → 0.1.2
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +4 -4
- data/akainaa.gemspec +2 -2
- data/lib/akainaa/call_node_visitor.rb +39 -0
- data/lib/akainaa/util.rb +37 -0
- data/lib/akainaa/version.rb +1 -1
- data/lib/akainaa.rb +25 -10
- metadata +5 -14
- data/Rakefile +0 -4
- data/img/webui.png +0 -0
- data/sample/.ruby-version +0 -1
- data/sample/Gemfile +0 -10
- data/sample/Gemfile.lock +0 -48
- data/sample/app.rb +0 -30
- data/sample/config.ru +0 -10
- data/sample/notification.rb +0 -9
- data/sample/theme.rb +0 -10
- data/sample/user.rb +0 -15
- data/sample/util.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6451f71725cda32349ab87402b32e6e132d8185274ba55a930fa2389fdd12279
|
4
|
+
data.tar.gz: 2b40049516aa512d8a89b607d327b1a5571b3c4221e351248d4ac13bbdc31dfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3199e1047c1295040cf043154128fcef145da13815f1cf8b69c84ec4a3237e44c525107ccb97abcc115d9d12f810e40623685843e190bb07cb99f95e35b104d
|
7
|
+
data.tar.gz: 74c12cf59e645eef87f2811d95d584a32ed5ec54b6f75019114c8f595fa206e0121cf7413c87a3b53fb4523f62cc7b45ee004aab467594f4dffd2153af00d045
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.1.2] - 2024-05-06
|
4
|
+
|
5
|
+
- Coloring all line of the method which located on multiple lines
|
6
|
+
|
7
|
+
## [0.1.1] - 2024-04-28
|
8
|
+
|
9
|
+
- Show the most executed file if path query isn't provided
|
10
|
+
|
3
11
|
## [0.1.0] - 2024-03-09
|
4
12
|
|
5
13
|
- Initial release
|
data/README.md
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Akainaa (赤いなぁ)
|
2
2
|
|
3
|
-

|
3
|
+

|
4
4
|
|
5
|
-
Akainaa is a gem
|
6
|
-
the number of executed count of code in a rack application
|
7
|
-
and provides a Web UI that shows the recorded status.
|
5
|
+
Akainaa is a gem to visualize code hotspot based on Coverage.
|
8
6
|
This gem can be used for the following purposes:
|
9
7
|
|
10
8
|
- super rough code profiler: The intensity of the red background for each line is proportional to the number of times it has been executed.
|
11
9
|
- A tool helps to understand what happened in a request: Akainaa have the reset button on Web UI, so user can easily record code execution for only one request.
|
12
10
|
|
11
|
+
You can see actual result view from [here](https://riseshia.github.io/akainaa/isucon13-baseline.html), which recorded on [isucon13](https://github.com/isucon/isucon13/tree/main/webapp/ruby) code in one benchmark run on [ISUNARABE](https://isunarabe.org/). And also [here](https://riseshia.github.io/akainaa/coverage/index.html) is the result of [simplecov-html](https://github.com/simplecov-ruby/simplecov-html)(0.12.3) from same coverage, so you can compare the result.
|
12
|
+
|
13
13
|
## Installation
|
14
14
|
|
15
15
|
Install the gem and add to the application's Gemfile by executing:
|
data/akainaa.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = spec.summary
|
13
13
|
spec.homepage = "https://github.com/riseshia/akainaa"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 3.
|
15
|
+
spec.required_ruby_version = ">= 3.2.0"
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = spec.homepage
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.files = Dir.chdir(__dir__) do
|
24
24
|
`git ls-files -z`.split("\x0").reject do |f|
|
25
25
|
(File.expand_path(f) == __FILE__) ||
|
26
|
-
f.start_with?(*%w[bin/ test/
|
26
|
+
f.start_with?(*%w[bin/ test/ sample/ docs/ img/ .git .github Gemfile Rakefile])
|
27
27
|
end
|
28
28
|
end
|
29
29
|
spec.bindir = "exe"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "prism"
|
4
|
+
|
5
|
+
module Akainaa
|
6
|
+
class CallNodeVisitor < Prism::Visitor
|
7
|
+
MethodRange = Data.define(:name, :start_line, :end_line) do
|
8
|
+
def start_line_as_idx
|
9
|
+
start_line - 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_row_range_as_idx
|
13
|
+
(start_line - 1)..(end_line - 1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :multiline_method_calls
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super
|
21
|
+
|
22
|
+
@multiline_method_calls = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def visit_call_node(node)
|
26
|
+
if node.arguments &&
|
27
|
+
node.message_loc.start_line != node.arguments.location&.end_line
|
28
|
+
|
29
|
+
@multiline_method_calls << MethodRange.new(
|
30
|
+
name: node.message,
|
31
|
+
start_line: node.message_loc.start_line,
|
32
|
+
end_line: node.arguments.location.end_line,
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/akainaa/util.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Akainaa
|
4
|
+
module Util
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# @param [String] source_path
|
8
|
+
# @param [Array<Integer>] lines
|
9
|
+
#
|
10
|
+
# @return [Array<Integer>]
|
11
|
+
def fullfill_multiline_method_calls(source_path, lines)
|
12
|
+
result = Prism.parse_file(source_path)
|
13
|
+
prog_node = result.value
|
14
|
+
|
15
|
+
visitor = ::Akainaa::CallNodeVisitor.new
|
16
|
+
visitor.visit(prog_node)
|
17
|
+
|
18
|
+
fullfilled_lines = lines.dup
|
19
|
+
|
20
|
+
visitor.multiline_method_calls.each do |method_range|
|
21
|
+
call_count = lines[method_range.start_line_as_idx]
|
22
|
+
|
23
|
+
method_range.method_row_range_as_idx.each do |idx|
|
24
|
+
if fullfilled_lines[idx].nil?
|
25
|
+
fullfilled_lines[idx] = call_count
|
26
|
+
elsif fullfilled_lines[idx] < call_count
|
27
|
+
fullfilled_lines[idx] = call_count
|
28
|
+
else
|
29
|
+
# use as it is
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
fullfilled_lines
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/akainaa/version.rb
CHANGED
data/lib/akainaa.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'coverage'
|
4
4
|
|
5
5
|
require_relative 'akainaa/version'
|
6
|
+
require_relative 'akainaa/call_node_visitor'
|
7
|
+
require_relative 'akainaa/util'
|
6
8
|
|
7
9
|
module Akainaa
|
8
10
|
class Error < StandardError; end
|
@@ -54,7 +56,7 @@ module Akainaa
|
|
54
56
|
|
55
57
|
private def extract_path_from_query(env)
|
56
58
|
matched = env['QUERY_STRING'].match(/path=([^&]+)/)
|
57
|
-
matched ? matched[1] :
|
59
|
+
matched ? matched[1] : nil
|
58
60
|
end
|
59
61
|
|
60
62
|
private def render_line(lineno, code, count, count_top)
|
@@ -74,13 +76,10 @@ module Akainaa
|
|
74
76
|
HTML
|
75
77
|
end
|
76
78
|
|
77
|
-
private def render_filelist(coverage_result, current_path:)
|
79
|
+
private def render_filelist(coverage_result, summary:, current_path:)
|
78
80
|
files = coverage_result.keys
|
79
|
-
max_count_on_proj =
|
80
|
-
|
81
|
-
.map { |cv| cv[:lines].reject(&:nil?).sum }
|
82
|
-
.max + 1
|
83
|
-
max_count_witdh = max_count_on_proj.to_s.size
|
81
|
+
max_count_on_proj = summary.max_count_on_proj
|
82
|
+
max_count_width = max_count_on_proj.to_s.size
|
84
83
|
|
85
84
|
li_elements = files.sort.map do |file|
|
86
85
|
total_count_on_file = coverage_result[file][:lines].reject(&:nil?).sum
|
@@ -89,7 +88,7 @@ module Akainaa
|
|
89
88
|
class_suffix = file == current_path ? ' current' : ''
|
90
89
|
<<~HTML
|
91
90
|
<li class="pure-menu-item">
|
92
|
-
<a href="/akainaa?path=#{file}" class="pure-menu-link filepath#{class_suffix} count-p#{count_top}"">(#{total_count_on_file.to_s.rjust(
|
91
|
+
<a href="/akainaa?path=#{file}" class="pure-menu-link filepath#{class_suffix} count-p#{count_top}"">(#{total_count_on_file.to_s.rjust(max_count_width)}) #{file}</a>
|
93
92
|
</li>
|
94
93
|
HTML
|
95
94
|
end.join
|
@@ -110,9 +109,25 @@ module Akainaa
|
|
110
109
|
HTML
|
111
110
|
end
|
112
111
|
|
112
|
+
CoverageSummary = Data.define(:file_path_has_max_count, :max_count_on_proj)
|
113
|
+
|
114
|
+
private def generate_summary(coverage_result)
|
115
|
+
file_path_has_max_count = coverage_result.max_by { |_, cv| cv[:lines].reject(&:nil?).sum }.first
|
116
|
+
max_count_on_proj = coverage_result
|
117
|
+
.values
|
118
|
+
.map { |cv| cv[:lines].reject(&:nil?).sum }
|
119
|
+
.max + 1
|
120
|
+
|
121
|
+
CoverageSummary.new(file_path_has_max_count:, max_count_on_proj:)
|
122
|
+
end
|
123
|
+
|
113
124
|
private def render_page(path)
|
114
125
|
result = Akainaa.peek_result
|
115
126
|
|
127
|
+
summary = generate_summary(result)
|
128
|
+
|
129
|
+
path = summary.file_path_has_max_count if path.nil?
|
130
|
+
|
116
131
|
path_result = result[path]
|
117
132
|
|
118
133
|
if path_result.nil?
|
@@ -123,7 +138,7 @@ module Akainaa
|
|
123
138
|
return "<" + "p>#{path} not found.<" + "/p>"
|
124
139
|
end
|
125
140
|
|
126
|
-
coverage_on_line = path_result[:lines]
|
141
|
+
coverage_on_line = Akainaa::Util.fullfill_multiline_method_calls(path, path_result[:lines])
|
127
142
|
max_count_on_file = coverage_on_line.reject(&:nil?).max + 1
|
128
143
|
|
129
144
|
lines = []
|
@@ -135,7 +150,7 @@ module Akainaa
|
|
135
150
|
lines << line
|
136
151
|
end
|
137
152
|
|
138
|
-
filelist = render_filelist(result, current_path: path)
|
153
|
+
filelist = render_filelist(result, summary:, current_path: path)
|
139
154
|
|
140
155
|
<<~HTML
|
141
156
|
<!DOCTYPE html>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: akainaa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shia
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Minimum rack middleware for coverage
|
14
14
|
email:
|
@@ -20,20 +20,11 @@ files:
|
|
20
20
|
- CHANGELOG.md
|
21
21
|
- LICENSE
|
22
22
|
- README.md
|
23
|
-
- Rakefile
|
24
23
|
- akainaa.gemspec
|
25
|
-
- img/webui.png
|
26
24
|
- lib/akainaa.rb
|
25
|
+
- lib/akainaa/call_node_visitor.rb
|
26
|
+
- lib/akainaa/util.rb
|
27
27
|
- lib/akainaa/version.rb
|
28
|
-
- sample/.ruby-version
|
29
|
-
- sample/Gemfile
|
30
|
-
- sample/Gemfile.lock
|
31
|
-
- sample/app.rb
|
32
|
-
- sample/config.ru
|
33
|
-
- sample/notification.rb
|
34
|
-
- sample/theme.rb
|
35
|
-
- sample/user.rb
|
36
|
-
- sample/util.rb
|
37
28
|
homepage: https://github.com/riseshia/akainaa
|
38
29
|
licenses:
|
39
30
|
- MIT
|
@@ -49,7 +40,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
40
|
requirements:
|
50
41
|
- - ">="
|
51
42
|
- !ruby/object:Gem::Version
|
52
|
-
version: 3.
|
43
|
+
version: 3.2.0
|
53
44
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
45
|
requirements:
|
55
46
|
- - ">="
|
data/Rakefile
DELETED
data/img/webui.png
DELETED
Binary file
|
data/sample/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
3.3.0
|
data/sample/Gemfile
DELETED
data/sample/Gemfile.lock
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
akainaa (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
base64 (0.2.0)
|
10
|
-
multi_json (1.15.0)
|
11
|
-
mustermann (3.0.0)
|
12
|
-
ruby2_keywords (~> 0.0.1)
|
13
|
-
nio4r (2.7.0)
|
14
|
-
puma (6.4.2)
|
15
|
-
nio4r (~> 2.0)
|
16
|
-
rack (3.0.9.1)
|
17
|
-
rack-protection (4.0.0)
|
18
|
-
base64 (>= 0.1.0)
|
19
|
-
rack (>= 3.0.0, < 4)
|
20
|
-
rack-session (2.0.0)
|
21
|
-
rack (>= 3.0.0)
|
22
|
-
ruby2_keywords (0.0.5)
|
23
|
-
sinatra (4.0.0)
|
24
|
-
mustermann (~> 3.0)
|
25
|
-
rack (>= 3.0.0, < 4)
|
26
|
-
rack-protection (= 4.0.0)
|
27
|
-
rack-session (>= 2.0.0, < 3)
|
28
|
-
tilt (~> 2.0)
|
29
|
-
sinatra-contrib (4.0.0)
|
30
|
-
multi_json (>= 0.0.2)
|
31
|
-
mustermann (~> 3.0)
|
32
|
-
rack-protection (= 4.0.0)
|
33
|
-
sinatra (= 4.0.0)
|
34
|
-
tilt (~> 2.0)
|
35
|
-
tilt (2.3.0)
|
36
|
-
|
37
|
-
PLATFORMS
|
38
|
-
ruby
|
39
|
-
x86_64-linux
|
40
|
-
|
41
|
-
DEPENDENCIES
|
42
|
-
akainaa!
|
43
|
-
puma (~> 6.4)
|
44
|
-
sinatra (~> 4.0)
|
45
|
-
sinatra-contrib (~> 4.0)
|
46
|
-
|
47
|
-
BUNDLED WITH
|
48
|
-
2.5.3
|
data/sample/app.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'sinatra/base'
|
4
|
-
require 'sinatra/json'
|
5
|
-
require 'securerandom'
|
6
|
-
|
7
|
-
require_relative './user'
|
8
|
-
require_relative './notification'
|
9
|
-
require_relative './util'
|
10
|
-
|
11
|
-
class App < Sinatra::Base
|
12
|
-
enable :logging
|
13
|
-
|
14
|
-
get '/api/me' do
|
15
|
-
1.times { Util.do_something }
|
16
|
-
2.times { Util.do_something }
|
17
|
-
3.times { Util.do_something }
|
18
|
-
4.times { Util.do_something }
|
19
|
-
5.times { Util.do_something }
|
20
|
-
6.times { Util.do_something }
|
21
|
-
7.times { Util.do_something }
|
22
|
-
8.times { Util.do_something }
|
23
|
-
9.times { Util.do_something }
|
24
|
-
10.times { Util.do_something }
|
25
|
-
|
26
|
-
json(
|
27
|
-
name: "riseshia",
|
28
|
-
)
|
29
|
-
end
|
30
|
-
end
|
data/sample/config.ru
DELETED
data/sample/notification.rb
DELETED
data/sample/theme.rb
DELETED
data/sample/user.rb
DELETED