active-profiling 0.1.0 → 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f519cf88d1010c707548ab98932d88d81f2c837
4
+ data.tar.gz: f192a78d710d21019043f58dbe0fe5ba653b616d
5
+ SHA512:
6
+ metadata.gz: f978d65cb2a40cfd1bd50202bb9e1b90ac5d7d16d1aca8e82a4e8d991c6b1dca0784203d93ae79bb2ebbfbc49d21afdbcfa6bea1af000e58b4aa34d579b2d750
7
+ data.tar.gz: c2eb4490ad875b06886b81f4185f7851212243b3977029f8ee6c5fa331fe6049f76d7e83b7526625b15ae441cf5576952d048be289652d55d9d8641d3a6efc59
@@ -1,22 +1,22 @@
1
- Copyright (c) 2012 J Smith <dark.panda@gmail.com>
2
-
3
- Permission is hereby granted, free of charge, to any person
4
- obtaining a copy of this software and associated documentation
5
- files (the "Software"), to deal in the Software without
6
- restriction, including without limitation the rights to use,
7
- copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- copies of the Software, and to permit persons to whom the
9
- Software is furnished to do so, subject to the following
10
- conditions:
11
-
12
- The above copyright notice and this permission notice shall be
13
- included in all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
- OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2012-2017 J Smith <dark.panda@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.description = "A Rails profiling suite."
12
12
  s.summary = s.description
13
13
  s.email = "dark.panda@gmail.com"
14
+ s.license = "MIT"
14
15
  s.extra_rdoc_files = [
15
16
  "README.rdoc"
16
17
  ]
@@ -1,6 +1,4 @@
1
1
 
2
- require 'digest/md5'
3
-
4
2
  module ActionController
5
3
  module ActionProfiling
6
4
  extend ActiveSupport::Concern
@@ -9,17 +7,23 @@ module ActionController
9
7
  include ActiveProfiling::RubyProfiler
10
8
  include ActiveProfiling::GCStatistics
11
9
 
12
- around_filter :action_profiler, :if => proc {
10
+ around_filter_method = if ActionController::Base.respond_to?(:around_action)
11
+ :around_action
12
+ else
13
+ :around_filter
14
+ end
15
+
16
+ send around_filter_method, :action_profiler, :if => proc {
13
17
  Rails.application.config.active_profiling.profiler.enabled && ActiveProfiling.ruby_prof?
14
18
  }
15
19
 
16
- around_filter :action_gc_statistics, :if => proc {
20
+ send around_filter_method, :action_gc_statistics, :if => proc {
17
21
  Rails.application.config.active_profiling.gc_statistics.enabled && ActiveProfiling.gc_statistics?
18
22
  }
19
23
  end
20
24
 
21
25
  def action_profiler(*args)
22
- ruby_profiler do
26
+ ruby_profiler(:name => "#{controller_name}.#{action_name}") do
23
27
  yield
24
28
  end
25
29
  end
@@ -1,4 +1,6 @@
1
1
 
2
+ require 'active-profiling/ruby_profiler/output'
3
+
2
4
  module ActiveProfiling
3
5
  module RubyProfiler
4
6
  extend ActiveSupport::Concern
@@ -9,103 +11,8 @@ module ActiveProfiling
9
11
  #
10
12
  # For details on the various options, see the default options located in
11
13
  # ActiveProfiling::Railtie::DEFAULT_PROFILER_OPTIONS.
12
- def ruby_profiler(*args)
13
- options = Rails.application.config.active_profiling.profiler.merge(args.extract_options!)
14
-
15
- printer_class = case options[:printer]
16
- when :flat_with_line_numbers
17
- RubyProf::FlatPrinterWithLineNumbers
18
- else
19
- RubyProf.const_get("#{options[:printer].to_s.camelize}Printer")
20
- end
21
-
22
- output = if options[:output]
23
- options[:output]
24
- else
25
- case options[:printer]
26
- when :call_tree, :call_stack, :graph_html, :dot
27
- :file
28
- else
29
- :log
30
- end
31
- end
32
-
33
- return yield if output == :log && !ActiveProfiling::LogSubscriber.logger
34
-
35
- RubyProf.measure_mode = RubyProf.const_get(options[:measure_mode].to_s.upcase)
36
- GC.disable if options[:disable_gc]
37
-
38
- result = nil
39
- exception = nil
40
- profiler_result = RubyProf.profile do
41
- begin
42
- result = yield
43
- rescue
44
- exception = $!
45
- end
46
- end
47
-
48
- case output
49
- when :stdout
50
- printer_class.new(profiler_result).print($stdout, options.printer_options)
51
- when :log
52
- str = StringIO.new
53
- printer_class.new(profiler_result).print(str, options.printer_options)
54
- str.rewind
55
-
56
- ActiveSupport::Notifications.instrument('profiler_output.active_profiling', {
57
- :profiler_output => str.read,
58
- :title => options[:title] || args.first
59
- })
60
- when :file
61
- path, file_name = if args.first
62
- [ File.dirname(args.first), args.first ]
63
- elsif options[:file_name]
64
- [ File.dirname(options[:file_name]), options[:file_name] ]
65
- else
66
- time = Time.now.strftime('%Y-%m-%d-%H:%M:%S')
67
- hash = Digest::MD5.hexdigest(rand.to_s)[0..6]
68
- path = Rails.root.join('log/profiling', self.class.name.underscore)
69
- ext = case options[:printer]
70
- when :graph_html, :call_stack
71
- 'html'
72
- when :dot
73
- 'dot'
74
- else
75
- 'log'
76
- end
77
-
78
- file_name = [
79
- self.action_name,
80
- options[:measure_mode],
81
- options[:printer],
82
- time,
83
- hash,
84
- ext
85
- ].join('.')
86
-
87
- if options[:printer] == :call_tree && !options[:call_tree_prefix].blank?
88
- file_name = "#{options[:call_tree_prefix]}#{file_name}"
89
- end
90
-
91
- [ path.to_s, path.join(file_name) ]
92
- end
93
-
94
- ActiveSupport::Notifications.instrument('profiler_output_to_file.active_profiling', {
95
- :file_name => file_name
96
- })
97
-
98
- FileUtils.mkdir_p(path)
99
- printer_class.new(profiler_result).print(File.open(file_name, 'w'), options[:printer_options])
100
- end
101
-
102
- if exception
103
- raise exception
104
- else
105
- result
106
- end
107
- ensure
108
- GC.enable if options[:disable_gc]
14
+ def ruby_profiler(*args, &block)
15
+ Output.new(*args).run(&block)
109
16
  end
110
17
  end
111
18
 
@@ -0,0 +1,171 @@
1
+
2
+ module ActiveProfiling
3
+ module RubyProfiler
4
+ class Output
5
+ def initialize(*args)
6
+ @options = Rails.application.config.active_profiling.profiler.merge(args.extract_options!)
7
+ @path = args.first
8
+
9
+ @output = if @options[:output]
10
+ @options[:output]
11
+ else
12
+ case @options[:printer]
13
+ when :call_tree, :call_stack, :graph_html, :dot
14
+ :file
15
+ else
16
+ :log
17
+ end
18
+ end
19
+ end
20
+
21
+ def run
22
+ return yield if @output == :log && !ActiveProfiling::ActionController::LogSubscriber.logger
23
+
24
+ RubyProf.measure_mode = RubyProf.const_get(@options[:measure_mode].to_s.upcase)
25
+ GC.disable if @options[:disable_gc]
26
+
27
+ result = nil
28
+ exception = nil
29
+ @profiler_result = RubyProf.profile do
30
+ begin
31
+ result = yield
32
+ rescue
33
+ exception = $!
34
+ end
35
+ end
36
+
37
+ case @output
38
+ when :stdout
39
+ write_to_stdout
40
+ when :log
41
+ write_to_log
42
+ when :file
43
+ write_to_file_or_path
44
+ end
45
+
46
+ if exception
47
+ raise exception
48
+ else
49
+ result
50
+ end
51
+ ensure
52
+ GC.enable if @options[:disable_gc]
53
+ end
54
+
55
+ private
56
+
57
+ def printer_class
58
+ @printer_class ||= case @options[:printer]
59
+ when :flat_with_line_numbers
60
+ RubyProf::FlatPrinterWithLineNumbers
61
+ else
62
+ RubyProf.const_get("#{@options[:printer].to_s.camelize}Printer")
63
+ end
64
+ end
65
+
66
+ def path_and_file_name
67
+ return @path_and_file_name if defined?(@path_and_file_name)
68
+
69
+ if @path.present?
70
+ { path: File.dirname(@path), file_name: @path }
71
+ elsif @options[:file_name]
72
+ { path: File.dirname(options[:file_name]), file_name: @options[:file_name] }
73
+ else
74
+ time = Time.now.strftime('%Y-%m-%d-%H:%M:%S')
75
+ hash = Digest::MD5.hexdigest(rand.to_s)[0..6]
76
+ path = Rails.root.join('log/profiling')
77
+ ext = case @options[:printer]
78
+ when :graph_html, :call_stack
79
+ 'html'
80
+ when :dot
81
+ 'dot'
82
+ else
83
+ 'log'
84
+ end
85
+
86
+ file_name = [
87
+ @options[:name],
88
+ @options[:measure_mode],
89
+ @options[:printer],
90
+ time,
91
+ hash,
92
+ ext
93
+ ].join('.')
94
+
95
+ @path_and_file_name = {
96
+ path: path.to_s,
97
+ file_name: path.join(file_name)
98
+ }
99
+ end
100
+ end
101
+
102
+ def write_to_stdout
103
+ printer_class.new(@profiler_result).print($stdout, @options)
104
+ end
105
+
106
+ def write_to_log
107
+ str = StringIO.new
108
+ printer_class.new(@profiler_result).print(str, @options[:printer_options])
109
+ str.rewind
110
+
111
+ ActiveSupport::Notifications.instrument('profiler_output.active_profiling', {
112
+ :profiler_output => str.read,
113
+ :title => @options[:title] || @path
114
+ })
115
+ end
116
+
117
+ def write_to_file_or_path
118
+ if call_tree_printer_file_output?
119
+ write_to_path
120
+ else
121
+ write_to_file
122
+ end
123
+ end
124
+
125
+ def write_to_file
126
+ ActiveSupport::Notifications.instrument('profiler_output_to_file.active_profiling', {
127
+ :file_name => path_and_file_name[:file_name]
128
+ })
129
+
130
+ FileUtils.mkdir_p(path_and_file_name[:path])
131
+ printer_class.new(@profiler_result).print(File.open(path_and_file_name[:file_name], 'w'), @options[:printer_options])
132
+ end
133
+
134
+ def write_to_path
135
+ ActiveSupport::Notifications.instrument('profiler_output_to_file.active_profiling', {
136
+ :file_name => path_and_file_name[:path]
137
+ })
138
+
139
+ FileUtils.mkdir_p(path_and_file_name[:path])
140
+ printer_class.new(@profiler_result).print(merged_printer_options(path_and_file_name))
141
+ end
142
+
143
+ def call_tree_prefix_option
144
+ # XXX - Bit of a hack here -- newer versions of RubyProf have changed
145
+ # the method signature of CallTreePrinter#print and changed how the
146
+ # generated files are prefixed. To accomodate call tree viewers like
147
+ # [KQ]CacheGrind, we need to hack in an appropriate file prefix.
148
+ if call_tree_printer_file_output?
149
+ @options[:call_tree_prefix].try(:gsub, /\.$/, '')
150
+ else
151
+ @options[:call_tree_prefix]
152
+ end
153
+ end
154
+
155
+ def merged_printer_options(path_and_file_name)
156
+ if @options[:printer] == :call_tree && @output == :file
157
+ @options[:printer_options].merge(
158
+ profile: call_tree_prefix_option,
159
+ path: path_and_file_name[:path]
160
+ )
161
+ else
162
+ @options[:printer_options]
163
+ end
164
+ end
165
+
166
+ def call_tree_printer_file_output?
167
+ printer_class.instance_method(:print).arity == -1 && printer_class == RubyProf::CallTreePrinter
168
+ end
169
+ end
170
+ end
171
+ end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module ActiveProfiling
3
- VERSION = "0.1.0"
3
+ VERSION = '0.1.1'.freeze
4
4
  end
metadata CHANGED
@@ -1,32 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-profiling
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.1.0
4
+ version: 0.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - J Smith
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-03 00:00:00.000000000 Z
11
+ date: 2017-04-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rails
16
- type: :runtime
17
15
  requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '3.0'
22
- none: false
20
+ type: :runtime
21
+ prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
23
  requirements:
25
- - - ! '>='
24
+ - - ">="
26
25
  - !ruby/object:Gem::Version
27
26
  version: '3.0'
28
- none: false
29
- prerelease: false
30
27
  description: A Rails profiling suite.
31
28
  email: dark.panda@gmail.com
32
29
  executables: []
@@ -34,7 +31,7 @@ extensions: []
34
31
  extra_rdoc_files:
35
32
  - README.rdoc
36
33
  files:
37
- - .gitignore
34
+ - ".gitignore"
38
35
  - Gemfile
39
36
  - MIT-LICENSE
40
37
  - README.rdoc
@@ -49,32 +46,30 @@ files:
49
46
  - lib/active-profiling/gc_statistics.rb
50
47
  - lib/active-profiling/railtie.rb
51
48
  - lib/active-profiling/ruby_profiler.rb
49
+ - lib/active-profiling/ruby_profiler/output.rb
52
50
  - lib/active-profiling/version.rb
53
51
  homepage: http://github.com/dark-panda/active-profiling
54
- licenses: []
52
+ licenses:
53
+ - MIT
54
+ metadata: {}
55
55
  post_install_message:
56
56
  rdoc_options: []
57
57
  require_paths:
58
58
  - lib
59
59
  required_ruby_version: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ! '>='
61
+ - - ">="
62
62
  - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
- hash: 1112450418277949513
66
63
  version: '0'
67
- none: false
68
64
  required_rubygems_version: !ruby/object:Gem::Requirement
69
65
  requirements:
70
- - - ! '>='
66
+ - - ">="
71
67
  - !ruby/object:Gem::Version
72
68
  version: '0'
73
- none: false
74
69
  requirements: []
75
70
  rubyforge_project:
76
- rubygems_version: 1.8.24
71
+ rubygems_version: 2.6.11
77
72
  signing_key:
78
- specification_version: 3
73
+ specification_version: 4
79
74
  summary: A Rails profiling suite.
80
75
  test_files: []