active-profiling 0.1.2 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5722 -0
- data/.rubocop_todo.yml +20 -0
- data/FUNDING.yml +2 -0
- data/Gemfile +6 -7
- data/MIT-LICENSE +1 -1
- data/Rakefile +2 -4
- data/active-profiling.gemspec +18 -15
- data/lib/active-profiling/action_controller/action_profiling.rb +7 -10
- data/lib/active-profiling/action_controller/log_subscriber.rb +17 -18
- data/lib/active-profiling/action_controller.rb +1 -0
- data/lib/active-profiling/active_record/backtrace_log_subscriber.rb +16 -14
- data/lib/active-profiling/active_record.rb +1 -1
- data/lib/active-profiling/gc_statistics.rb +14 -19
- data/lib/active-profiling/railtie.rb +19 -18
- data/lib/active-profiling/ruby_profiler/output.rb +102 -108
- data/lib/active-profiling/ruby_profiler.rb +2 -1
- data/lib/active-profiling/version.rb +2 -1
- data/lib/active-profiling.rb +1 -1
- metadata +15 -11
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2024-04-15 15:03:39 UTC using RuboCop version 1.63.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
11
|
+
Metrics/PerceivedComplexity:
|
12
|
+
Max: 9
|
13
|
+
|
14
|
+
# Offense count: 1
|
15
|
+
# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
16
|
+
# CheckDefinitionPathHierarchyRoots: lib, spec, test, src
|
17
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
18
|
+
Naming/FileName:
|
19
|
+
Exclude:
|
20
|
+
- 'lib/active-profiling.rb'
|
data/FUNDING.yml
ADDED
data/Gemfile
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
source
|
3
|
+
source 'https://rubygems.org'
|
3
4
|
|
4
5
|
gemspec
|
5
6
|
|
6
|
-
gem
|
7
|
-
gem
|
8
|
-
|
9
|
-
if File.exists?('Gemfile.local')
|
10
|
-
instance_eval File.read('Gemfile.local')
|
11
|
-
end
|
7
|
+
gem 'rake'
|
8
|
+
gem 'rdoc'
|
9
|
+
gem 'rubocop', require: false
|
12
10
|
|
11
|
+
instance_eval File.read('Gemfile.local') if File.exist?('Gemfile.local')
|
data/MIT-LICENSE
CHANGED
data/Rakefile
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
# -*- ruby -*-
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'rubygems'
|
5
4
|
require 'rubygems/package_task'
|
@@ -7,7 +6,7 @@ require 'rake/testtask'
|
|
7
6
|
require 'rdoc/task'
|
8
7
|
require 'bundler/gem_tasks'
|
9
8
|
|
10
|
-
|
9
|
+
$LOAD_PATH.push File.expand_path(File.dirname(__FILE__), 'lib')
|
11
10
|
|
12
11
|
version = ActiveProfiling::VERSION
|
13
12
|
|
@@ -25,4 +24,3 @@ Rake::RDocTask.new do |t|
|
|
25
24
|
t.rdoc_dir = 'doc'
|
26
25
|
t.rdoc_files.include('README.rdoc', 'MIT-LICENSE', 'lib/**/*.rb')
|
27
26
|
end
|
28
|
-
|
data/active-profiling.gemspec
CHANGED
@@ -1,26 +1,29 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path('
|
3
|
+
require File.expand_path('lib/active-profiling/version', __dir__)
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'active-profiling'
|
7
7
|
s.version = ActiveProfiling::VERSION
|
8
8
|
|
9
|
-
s.required_rubygems_version = Gem::Requirement.new(
|
10
|
-
s.
|
11
|
-
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
10
|
+
s.required_ruby_version = '>= 3.0'
|
11
|
+
|
12
|
+
s.authors = ['J Smith']
|
13
|
+
s.description = 'A Rails profiling suite.'
|
12
14
|
s.summary = s.description
|
13
|
-
s.email =
|
14
|
-
s.license =
|
15
|
+
s.email = 'dark.panda@gmail.com'
|
16
|
+
s.license = 'MIT'
|
15
17
|
s.extra_rdoc_files = [
|
16
|
-
|
18
|
+
'README.rdoc'
|
17
19
|
]
|
18
|
-
s.files = `git ls-files`.split(
|
20
|
+
s.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
19
21
|
s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
20
|
-
s.
|
21
|
-
s.
|
22
|
-
s.require_paths = ["lib"]
|
22
|
+
s.homepage = 'https://github.com/dark-panda/active-profiling'
|
23
|
+
s.require_paths = ['lib']
|
23
24
|
|
24
|
-
s.add_dependency(
|
25
|
+
s.add_dependency('rails', ['>= 6.0'])
|
26
|
+
s.metadata = {
|
27
|
+
'rubygems_mfa_required' => 'true'
|
28
|
+
}
|
25
29
|
end
|
26
|
-
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module ActionController
|
3
4
|
module ActionProfiling
|
@@ -13,25 +14,21 @@ module ActionController
|
|
13
14
|
:around_filter
|
14
15
|
end
|
15
16
|
|
16
|
-
send around_filter_method, :action_profiler, :
|
17
|
+
send around_filter_method, :action_profiler, if: proc {
|
17
18
|
Rails.application.config.active_profiling.profiler.enabled && ActiveProfiling.ruby_prof?
|
18
19
|
}
|
19
20
|
|
20
|
-
send around_filter_method, :action_gc_statistics, :
|
21
|
+
send around_filter_method, :action_gc_statistics, if: proc {
|
21
22
|
Rails.application.config.active_profiling.gc_statistics.enabled && ActiveProfiling.gc_statistics?
|
22
23
|
}
|
23
24
|
end
|
24
25
|
|
25
|
-
def action_profiler(
|
26
|
-
ruby_profiler(:
|
27
|
-
yield
|
28
|
-
end
|
26
|
+
def action_profiler(*, &block)
|
27
|
+
ruby_profiler(name: "#{controller_name}.#{action_name}", &block)
|
29
28
|
end
|
30
29
|
|
31
|
-
def action_gc_statistics(
|
32
|
-
gc_statistics
|
33
|
-
yield
|
34
|
-
end
|
30
|
+
def action_gc_statistics(*, &block)
|
31
|
+
gc_statistics(&block)
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
@@ -1,49 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module ActiveProfiling::ActionController
|
3
4
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
4
5
|
def profiler_output(event)
|
5
|
-
return unless logger
|
6
|
-
logger.send("#{config.profiler.log_level}?")
|
6
|
+
return unless logger&.send("#{config.profiler.log_level}?")
|
7
7
|
|
8
|
-
report =
|
8
|
+
report = indent(event.payload[:profiler_output])
|
9
9
|
title = event.payload[:title]
|
10
10
|
|
11
11
|
logger.send(
|
12
12
|
config.profiler.log_level,
|
13
|
-
"#{color("Profiler Output: #{title}", YELLOW, true)}\n#{report}"
|
13
|
+
"#{color("Profiler Output: #{title}", YELLOW, bold: true)}\n#{report}"
|
14
14
|
)
|
15
15
|
end
|
16
16
|
|
17
17
|
def profiler_output_to_file(event)
|
18
|
-
return unless logger
|
19
|
-
logger.send("#{config.profiler.log_level}?")
|
18
|
+
return unless logger&.send("#{config.profiler.log_level}?")
|
20
19
|
|
21
20
|
logger.send(
|
22
21
|
config.profiler.log_level,
|
23
|
-
color("Wrote profiling information to #{event.payload[:file_name]}", YELLOW, true)
|
22
|
+
color("Wrote profiling information to #{event.payload[:file_name]}", YELLOW, bold: true)
|
24
23
|
)
|
25
24
|
end
|
26
25
|
|
27
26
|
def gc_statistics(event)
|
28
|
-
return unless logger
|
29
|
-
logger.send("#{config.gc_statistics.log_level}?")
|
27
|
+
return unless logger&.send("#{config.gc_statistics.log_level}?")
|
30
28
|
|
31
|
-
|
32
|
-
title = event.payload[:title]
|
33
|
-
report = self.indent(event.payload[:report])
|
29
|
+
return if event.payload[:report].blank?
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
31
|
+
title = event.payload[:title]
|
32
|
+
report = indent(event.payload[:report])
|
33
|
+
|
34
|
+
logger.send(
|
35
|
+
config.gc_statistics.log_level,
|
36
|
+
"#{color("GC Statistics: #{title}", YELLOW, bold: true)}\n#{report}"
|
37
|
+
)
|
40
38
|
end
|
41
39
|
|
42
40
|
def logger
|
43
41
|
::Rails.logger
|
44
42
|
end
|
45
43
|
|
46
|
-
|
44
|
+
private
|
45
|
+
|
47
46
|
def config
|
48
47
|
Rails.application.config.active_profiling
|
49
48
|
end
|
@@ -1,33 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module ActiveProfiling::ActiveRecord
|
3
4
|
class BacktraceLogSubscriber < ::ActiveSupport::LogSubscriber
|
4
5
|
def sql(event)
|
5
|
-
return unless
|
6
|
-
config.log_level &&
|
7
|
-
logger &&
|
8
|
-
logger.send("#{config.log_level}?")
|
6
|
+
return unless skip_backtrace?
|
9
7
|
|
10
8
|
payload = event.payload
|
11
9
|
|
12
|
-
return if
|
10
|
+
return if payload[:name] == 'SCHEMA'
|
13
11
|
|
14
12
|
backtrace = event.send(:caller).collect { |line|
|
15
|
-
if line_match(line)
|
16
|
-
" #{line}"
|
17
|
-
end
|
13
|
+
" #{line}" if line_match(line)
|
18
14
|
}.compact
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
return if backtrace.empty?
|
17
|
+
|
18
|
+
name = color(payload[:name], YELLOW, true)
|
19
|
+
logger.send(config.log_level, " #{name}\n#{backtrace.join("\n")}")
|
24
20
|
end
|
25
21
|
|
26
22
|
def logger
|
27
23
|
::ActiveRecord::Base.logger
|
28
24
|
end
|
29
25
|
|
30
|
-
|
26
|
+
private
|
27
|
+
|
28
|
+
def skip_backtrace?
|
29
|
+
config.enabled &&
|
30
|
+
config.log_level &&
|
31
|
+
logger&.send("#{config.log_level}?")
|
32
|
+
end
|
33
|
+
|
31
34
|
def config
|
32
35
|
Rails.application.config.active_profiling.active_record.backtrace_logger
|
33
36
|
end
|
@@ -39,4 +42,3 @@ module ActiveProfiling::ActiveRecord
|
|
39
42
|
end
|
40
43
|
|
41
44
|
ActiveProfiling::ActiveRecord::BacktraceLogSubscriber.attach_to :active_record
|
42
|
-
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module ActiveProfiling
|
3
4
|
module GCStatistics
|
@@ -6,7 +7,7 @@ module ActiveProfiling
|
|
6
7
|
if defined?(GC::Profiler)
|
7
8
|
def gc_statistics_report(options = {})
|
8
9
|
options = {
|
9
|
-
:
|
10
|
+
disable_gc: false
|
10
11
|
}.merge(options)
|
11
12
|
|
12
13
|
GC.disable if options[:disable_gc]
|
@@ -15,14 +16,11 @@ module ActiveProfiling
|
|
15
16
|
|
16
17
|
retval = yield
|
17
18
|
|
18
|
-
if options[:disable_gc]
|
19
|
-
GC.enable
|
20
|
-
end
|
19
|
+
GC.enable if options[:disable_gc]
|
21
20
|
|
22
21
|
result = GC::Profiler.result
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
[retval, result]
|
26
24
|
ensure
|
27
25
|
GC.enable if options[:disable_gc]
|
28
26
|
GC::Profiler.disable
|
@@ -31,7 +29,7 @@ module ActiveProfiling
|
|
31
29
|
elsif GC.respond_to?(:enable_stats)
|
32
30
|
def gc_statistics_report(options = {})
|
33
31
|
options = {
|
34
|
-
:
|
32
|
+
disable_gc: false
|
35
33
|
}.merge(options)
|
36
34
|
|
37
35
|
GC.disable if options[:disable_gc]
|
@@ -47,18 +45,17 @@ module ActiveProfiling
|
|
47
45
|
"Time (ms): #{GC.time / 1000.0}"
|
48
46
|
].join("\n")
|
49
47
|
|
50
|
-
|
51
|
-
|
48
|
+
[retval, result]
|
52
49
|
ensure
|
53
50
|
GC.enable if options[:disable_gc]
|
54
51
|
GC.disable_stats
|
55
52
|
GC.clear_stats
|
56
53
|
end
|
57
54
|
else
|
58
|
-
$stderr.
|
55
|
+
$stderr.warn 'NOTICE: this version of Ruby cannot report on GC statistics.'
|
59
56
|
|
60
|
-
def gc_statistics_report(*
|
61
|
-
[
|
57
|
+
def gc_statistics_report(*)
|
58
|
+
[yield, nil]
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
@@ -85,21 +82,19 @@ module ActiveProfiling
|
|
85
82
|
# with the GC statistics patch found here:
|
86
83
|
#
|
87
84
|
# http://blog.pluron.com/2008/02/memory-profilin.html
|
88
|
-
def gc_statistics(*args)
|
85
|
+
def gc_statistics(*args, &block)
|
89
86
|
options = Rails.application.config.active_profiling.gc_statistics.merge(args.extract_options!)
|
90
87
|
|
91
|
-
result, gc_report = gc_statistics_report(options)
|
92
|
-
yield
|
93
|
-
end
|
88
|
+
result, gc_report = gc_statistics_report(options, &block)
|
94
89
|
|
95
90
|
ActiveSupport::Notifications.instrument('gc_statistics.active_profiling', {
|
96
|
-
:
|
97
|
-
:
|
91
|
+
report: gc_report,
|
92
|
+
title: options[:title] || args.first
|
98
93
|
})
|
99
94
|
|
100
95
|
result
|
101
96
|
end
|
102
97
|
end
|
103
98
|
|
104
|
-
|
99
|
+
extend(GCStatistics)
|
105
100
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module ActiveProfiling
|
3
4
|
class Railtie < Rails::Railtie
|
@@ -43,23 +44,23 @@ module ActiveProfiling
|
|
43
44
|
# :print_file => true
|
44
45
|
# }
|
45
46
|
DEFAULT_PROFILER_OPTIONS = {
|
46
|
-
:
|
47
|
+
enabled: false,
|
47
48
|
|
48
|
-
:
|
49
|
+
measure_mode: :process_time,
|
49
50
|
|
50
|
-
:
|
51
|
+
disable_gc: true,
|
51
52
|
|
52
|
-
:
|
53
|
+
printer: :graph,
|
53
54
|
|
54
|
-
:
|
55
|
+
call_tree_prefix: 'callgrind.out.',
|
55
56
|
|
56
|
-
:
|
57
|
+
output: nil,
|
57
58
|
|
58
|
-
:
|
59
|
+
log_level: :info,
|
59
60
|
|
60
|
-
:
|
61
|
-
:
|
62
|
-
:
|
61
|
+
printer_options: {
|
62
|
+
min_percent: 1,
|
63
|
+
print_file: true
|
63
64
|
}
|
64
65
|
}.freeze
|
65
66
|
|
@@ -77,11 +78,11 @@ module ActiveProfiling
|
|
77
78
|
# whenever you need to and see results as you go.
|
78
79
|
# * +:log_level+ - The log level to spit the GC statistics to.
|
79
80
|
DEFAULT_GC_STATISTICS_OPTIONS = {
|
80
|
-
:
|
81
|
+
enabled: false,
|
81
82
|
|
82
|
-
:
|
83
|
+
disable_gc: false,
|
83
84
|
|
84
|
-
:
|
85
|
+
log_level: :info
|
85
86
|
}.freeze
|
86
87
|
|
87
88
|
# These settings are the default values used for the ActiveRecord
|
@@ -98,11 +99,11 @@ module ActiveProfiling
|
|
98
99
|
# /^#{Rails.root}(?!(\/vendor\/rails|\/\.bundle))/ so that only lines
|
99
100
|
# in your application code are logged.
|
100
101
|
DEFAULT_AR_BACKTRACE_LOGGER_OPTIONS = {
|
101
|
-
:
|
102
|
+
enabled: false,
|
102
103
|
|
103
|
-
:
|
104
|
+
verbose: false,
|
104
105
|
|
105
|
-
:
|
106
|
+
log_level: :debug
|
106
107
|
}.freeze
|
107
108
|
|
108
109
|
config.active_profiling = ActiveSupport::OrderedOptions.new
|
@@ -111,13 +112,13 @@ module ActiveProfiling
|
|
111
112
|
config.active_profiling.active_record = ActiveSupport::OrderedOptions.new
|
112
113
|
config.active_profiling.active_record.backtrace_logger = ActiveSupport::OrderedOptions.new
|
113
114
|
|
114
|
-
initializer
|
115
|
+
initializer 'active_profiling.set_profiling_config' do |app|
|
115
116
|
options = app.config.active_profiling
|
116
117
|
|
117
118
|
options.profiler.reverse_merge!(DEFAULT_PROFILER_OPTIONS)
|
118
119
|
options.gc_statistics.reverse_merge!(DEFAULT_GC_STATISTICS_OPTIONS)
|
119
120
|
options.active_record.backtrace_logger.reverse_merge!(DEFAULT_AR_BACKTRACE_LOGGER_OPTIONS)
|
120
|
-
options.active_record.backtrace_logger[:matcher] ||=
|
121
|
+
options.active_record.backtrace_logger[:matcher] ||= %r{#{Rails.root}(?!(/vendor/rails|/\.bundle))}
|
121
122
|
end
|
122
123
|
end
|
123
124
|
end
|