rack_lineprof 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/lib/rack/lineprof.rb +54 -0
- data/lib/rack/lineprof/sample.rb +32 -0
- data/lib/rack/lineprof/source.rb +81 -0
- data/lib/rack_lineprof.rb +5 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bf63ce2f01c5dbfed1f2bd3dde124c0eb81a95b1
|
4
|
+
data.tar.gz: 61800a817dff047d6fa44a752c2166080c4ea3fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b87932598add64d4d7c97e4d423a92e0e23fe8a8681caa6121bf77a658c37b9d5be0afce778c34b002d5cf96ac70f84bec8f18e45d3692046354dbeb7c22fe2a
|
7
|
+
data.tar.gz: 98fb360d03fe208d0d9741ed17239d21e5dba750a970308a6fc1395d223e4c4a558977aad61f7a7fcfff5c1b54b99e9c726cedd5a50e3c764e6fede97ed11b50
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rblineprof'
|
2
|
+
require 'logger'
|
3
|
+
require 'term/ansicolor'
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
class Lineprof
|
7
|
+
autoload :Sample, 'rack/lineprof/sample'
|
8
|
+
autoload :Source, 'rack/lineprof/source'
|
9
|
+
|
10
|
+
CONTEXT = 0
|
11
|
+
NOMINAL = 1
|
12
|
+
WARNING = 2
|
13
|
+
CRITICAL = 3
|
14
|
+
|
15
|
+
DEFAULT_LOGGER = if defined?(::Rails)
|
16
|
+
if ::Rails.env.development?
|
17
|
+
::Logger.new(STDOUT)
|
18
|
+
else
|
19
|
+
::Logger.new(::Rails.root.join('log/profiler.log'))
|
20
|
+
end
|
21
|
+
else
|
22
|
+
::Logger.new(STDOUT)
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :app, :options
|
26
|
+
|
27
|
+
def initialize(app, options = {})
|
28
|
+
@app, @options = app, options
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
request = Rack::Request.new(env)
|
33
|
+
matcher = request.params['lineprof'] || options[:profile]
|
34
|
+
logger = options[:logger] || DEFAULT_LOGGER
|
35
|
+
|
36
|
+
return @app.call(env) unless matcher
|
37
|
+
|
38
|
+
response = nil
|
39
|
+
profile = lineprof(%r{#{matcher}}) { response = @app.call(env) }
|
40
|
+
|
41
|
+
logger.error Term::ANSIColor.blue("\n[Rack::Lineprof] #{'=' * 63}") + "\n\n" + format_profile(profile) + "\n"
|
42
|
+
|
43
|
+
response
|
44
|
+
end
|
45
|
+
|
46
|
+
def format_profile(profile)
|
47
|
+
sources = profile.map do |filename, samples|
|
48
|
+
Source.new(filename, samples, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
sources.map(&:format).compact.join "\n"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rack
|
2
|
+
class Lineprof
|
3
|
+
class Sample < Struct.new :ms, :calls, :line, :code, :level
|
4
|
+
def format(colorize = true)
|
5
|
+
formatted = if level == CONTEXT
|
6
|
+
sprintf " | % 3i %s", line, code
|
7
|
+
else
|
8
|
+
sprintf "% 6.1fms %5i | % 3i %s", ms, calls, line, code
|
9
|
+
end
|
10
|
+
|
11
|
+
return formatted unless colorize
|
12
|
+
|
13
|
+
case level
|
14
|
+
when CRITICAL
|
15
|
+
color.red formatted
|
16
|
+
when WARNING
|
17
|
+
color.yellow formatted
|
18
|
+
when NOMINAL
|
19
|
+
color.white formatted
|
20
|
+
else # CONTEXT
|
21
|
+
color.intense_black formatted
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def color
|
28
|
+
Term::ANSIColor
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Rack
|
2
|
+
class Lineprof
|
3
|
+
class Source
|
4
|
+
attr_reader :file_name, :raw_samples, :options
|
5
|
+
|
6
|
+
def initialize(file_name, raw_samples, options = {})
|
7
|
+
@file_name, @raw_samples, @options = file_name, raw_samples, options
|
8
|
+
end
|
9
|
+
|
10
|
+
def format
|
11
|
+
return nil if samples.empty?
|
12
|
+
|
13
|
+
formatted = file_name.sub(Dir.pwd + '/', '') + "\n"
|
14
|
+
|
15
|
+
prev_line = samples.first.line - 1
|
16
|
+
samples.each do |sample|
|
17
|
+
if sample.line != prev_line + 1
|
18
|
+
formatted << color.intense_black(' ' * 14 + '.' * 7) + "\n"
|
19
|
+
end
|
20
|
+
prev_line = sample.line
|
21
|
+
|
22
|
+
formatted << sample.format
|
23
|
+
end
|
24
|
+
|
25
|
+
formatted
|
26
|
+
end
|
27
|
+
|
28
|
+
def samples
|
29
|
+
@samples ||= begin
|
30
|
+
parsed = []
|
31
|
+
|
32
|
+
raw_samples.each_with_index do |sample, line|
|
33
|
+
next if line == 0 # drop file info
|
34
|
+
|
35
|
+
ms = sample[0] / 1000.0
|
36
|
+
calls = sample[2]
|
37
|
+
|
38
|
+
abnormal = ms >= thresholds[NOMINAL]
|
39
|
+
near_abnormal = (line-context..line+context).any? do |near|
|
40
|
+
near = [1, near].max
|
41
|
+
next unless raw_samples[near]
|
42
|
+
(raw_samples[near][0] / 1000.0) >= thresholds[NOMINAL]
|
43
|
+
end
|
44
|
+
|
45
|
+
next unless abnormal or near_abnormal
|
46
|
+
|
47
|
+
threshold = thresholds.invert.detect { |th, _| ms > th }
|
48
|
+
level = threshold ? threshold.last : CONTEXT
|
49
|
+
|
50
|
+
next unless code = source_lines[line - 1]
|
51
|
+
parsed << Sample.new(ms, calls, line, code, level)
|
52
|
+
end
|
53
|
+
|
54
|
+
parsed
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def source_lines
|
59
|
+
@source_lines ||= ::File.open(file_name, 'r').to_a
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def color
|
65
|
+
Term::ANSIColor
|
66
|
+
end
|
67
|
+
|
68
|
+
def context
|
69
|
+
options.fetch :context, 2
|
70
|
+
end
|
71
|
+
|
72
|
+
def thresholds
|
73
|
+
@thresholds ||= {
|
74
|
+
CRITICAL => 50,
|
75
|
+
WARNING => 5,
|
76
|
+
NOMINAL => 0.2
|
77
|
+
}.merge(options.fetch :thresholds, {})
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack_lineprof
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Evan Owen
|
8
|
+
- Patrice Lebel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-04-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.5'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.5'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rblineprof
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.3.7
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.3.7
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: term-ansicolor
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.3'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.3'
|
56
|
+
description: Rack middleware for rblineprof (github.com/tmm1/rblineprof)
|
57
|
+
email:
|
58
|
+
- kainosnoema@gmail.com
|
59
|
+
- patleb@users.noreply.github.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- lib/rack/lineprof.rb
|
65
|
+
- lib/rack/lineprof/sample.rb
|
66
|
+
- lib/rack/lineprof/source.rb
|
67
|
+
- lib/rack_lineprof.rb
|
68
|
+
homepage: https://github.com/patleb/rack_lineprof
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.5.2
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Makes line-by-line source code profiling easy.
|
92
|
+
test_files: []
|