mini-sharp-hub 0.0.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.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/mini-sharp-hub.gemspec +12 -0
  3. data/rack-mini-profiler-4.0.1/CHANGELOG.md +424 -0
  4. data/rack-mini-profiler-4.0.1/README.md +542 -0
  5. data/rack-mini-profiler-4.0.1/lib/enable_rails_patches.rb +5 -0
  6. data/rack-mini-profiler-4.0.1/lib/generators/rack_mini_profiler/USAGE +9 -0
  7. data/rack-mini-profiler-4.0.1/lib/generators/rack_mini_profiler/install_generator.rb +13 -0
  8. data/rack-mini-profiler-4.0.1/lib/generators/rack_mini_profiler/templates/rack_mini_profiler.rb +8 -0
  9. data/rack-mini-profiler-4.0.1/lib/generators/rack_profiler/USAGE +2 -0
  10. data/rack-mini-profiler-4.0.1/lib/generators/rack_profiler/install_generator.rb +16 -0
  11. data/rack-mini-profiler-4.0.1/lib/html/dot.1.1.2.min.js +2 -0
  12. data/rack-mini-profiler-4.0.1/lib/html/includes.css +474 -0
  13. data/rack-mini-profiler-4.0.1/lib/html/includes.js +1520 -0
  14. data/rack-mini-profiler-4.0.1/lib/html/includes.scss +698 -0
  15. data/rack-mini-profiler-4.0.1/lib/html/includes.tmpl +333 -0
  16. data/rack-mini-profiler-4.0.1/lib/html/pretty-print.js +810 -0
  17. data/rack-mini-profiler-4.0.1/lib/html/profile_handler.js +1 -0
  18. data/rack-mini-profiler-4.0.1/lib/html/rack-mini-profiler.css +3 -0
  19. data/rack-mini-profiler-4.0.1/lib/html/rack-mini-profiler.js +2 -0
  20. data/rack-mini-profiler-4.0.1/lib/html/share.html +10 -0
  21. data/rack-mini-profiler-4.0.1/lib/html/speedscope/LICENSE +21 -0
  22. data/rack-mini-profiler-4.0.1/lib/html/speedscope/README.md +3 -0
  23. data/rack-mini-profiler-4.0.1/lib/html/speedscope/demangle-cpp.1768f4cc.js +4 -0
  24. data/rack-mini-profiler-4.0.1/lib/html/speedscope/favicon-16x16.f74b3187.png +0 -0
  25. data/rack-mini-profiler-4.0.1/lib/html/speedscope/favicon-32x32.bc503437.png +0 -0
  26. data/rack-mini-profiler-4.0.1/lib/html/speedscope/file-format-schema.json +324 -0
  27. data/rack-mini-profiler-4.0.1/lib/html/speedscope/fonts/source-code-pro-regular.css +8 -0
  28. data/rack-mini-profiler-4.0.1/lib/html/speedscope/fonts/source-code-pro-v13-regular.woff +0 -0
  29. data/rack-mini-profiler-4.0.1/lib/html/speedscope/fonts/source-code-pro-v13-regular.woff2 +0 -0
  30. data/rack-mini-profiler-4.0.1/lib/html/speedscope/import.8ae8aa3d.js +123 -0
  31. data/rack-mini-profiler-4.0.1/lib/html/speedscope/index.html +2 -0
  32. data/rack-mini-profiler-4.0.1/lib/html/speedscope/release.txt +3 -0
  33. data/rack-mini-profiler-4.0.1/lib/html/speedscope/reset.8c46b7a1.css +2 -0
  34. data/rack-mini-profiler-4.0.1/lib/html/speedscope/source-map.438fa06b.js +24 -0
  35. data/rack-mini-profiler-4.0.1/lib/html/speedscope/speedscope.f27db165.js +193 -0
  36. data/rack-mini-profiler-4.0.1/lib/html/vendor.js +848 -0
  37. data/rack-mini-profiler-4.0.1/lib/mini_profiler/actions.rb +157 -0
  38. data/rack-mini-profiler-4.0.1/lib/mini_profiler/asset_version.rb +6 -0
  39. data/rack-mini-profiler-4.0.1/lib/mini_profiler/client_settings.rb +127 -0
  40. data/rack-mini-profiler-4.0.1/lib/mini_profiler/config.rb +146 -0
  41. data/rack-mini-profiler-4.0.1/lib/mini_profiler/context.rb +14 -0
  42. data/rack-mini-profiler-4.0.1/lib/mini_profiler/gc_profiler.rb +158 -0
  43. data/rack-mini-profiler-4.0.1/lib/mini_profiler/profiling_methods.rb +167 -0
  44. data/rack-mini-profiler-4.0.1/lib/mini_profiler/snapshots_transporter.rb +111 -0
  45. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/abstract_store.rb +97 -0
  46. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/file_store.rb +179 -0
  47. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/memcache_store.rb +105 -0
  48. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/memory_store.rb +233 -0
  49. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/redis_store.rb +353 -0
  50. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage.rb +7 -0
  51. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/base.rb +39 -0
  52. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/client.rb +90 -0
  53. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/custom.rb +25 -0
  54. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/page.rb +146 -0
  55. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/request.rb +186 -0
  56. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/sql.rb +89 -0
  57. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct.rb +8 -0
  58. data/rack-mini-profiler-4.0.1/lib/mini_profiler/version.rb +8 -0
  59. data/rack-mini-profiler-4.0.1/lib/mini_profiler/views.rb +198 -0
  60. data/rack-mini-profiler-4.0.1/lib/mini_profiler.rb +670 -0
  61. data/rack-mini-profiler-4.0.1/lib/mini_profiler_rails/railtie.rb +234 -0
  62. data/rack-mini-profiler-4.0.1/lib/mini_profiler_rails/railtie_methods.rb +61 -0
  63. data/rack-mini-profiler-4.0.1/lib/patches/db/activerecord.rb +44 -0
  64. data/rack-mini-profiler-4.0.1/lib/patches/db/mongo.rb +18 -0
  65. data/rack-mini-profiler-4.0.1/lib/patches/db/moped.rb +14 -0
  66. data/rack-mini-profiler-4.0.1/lib/patches/db/mysql2/alias_method.rb +30 -0
  67. data/rack-mini-profiler-4.0.1/lib/patches/db/mysql2/prepend.rb +34 -0
  68. data/rack-mini-profiler-4.0.1/lib/patches/db/mysql2.rb +7 -0
  69. data/rack-mini-profiler-4.0.1/lib/patches/db/neo4j.rb +16 -0
  70. data/rack-mini-profiler-4.0.1/lib/patches/db/nobrainer.rb +31 -0
  71. data/rack-mini-profiler-4.0.1/lib/patches/db/oracle_enhanced.rb +70 -0
  72. data/rack-mini-profiler-4.0.1/lib/patches/db/pg/alias_method.rb +121 -0
  73. data/rack-mini-profiler-4.0.1/lib/patches/db/pg/prepend.rb +115 -0
  74. data/rack-mini-profiler-4.0.1/lib/patches/db/pg.rb +7 -0
  75. data/rack-mini-profiler-4.0.1/lib/patches/db/plucky.rb +49 -0
  76. data/rack-mini-profiler-4.0.1/lib/patches/db/riak.rb +105 -0
  77. data/rack-mini-profiler-4.0.1/lib/patches/db/rsolr.rb +26 -0
  78. data/rack-mini-profiler-4.0.1/lib/patches/db/sequel.rb +12 -0
  79. data/rack-mini-profiler-4.0.1/lib/patches/net_patches.rb +27 -0
  80. data/rack-mini-profiler-4.0.1/lib/patches/sql_patches.rb +74 -0
  81. data/rack-mini-profiler-4.0.1/lib/prepend_mysql2_patch.rb +5 -0
  82. data/rack-mini-profiler-4.0.1/lib/prepend_net_http_patch.rb +5 -0
  83. data/rack-mini-profiler-4.0.1/lib/prepend_pg_patch.rb +5 -0
  84. data/rack-mini-profiler-4.0.1/lib/rack-mini-profiler.rb +13 -0
  85. data/rack-mini-profiler-4.0.1/rack-mini-profiler.gemspec +49 -0
  86. metadata +125 -0
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+ module Rack
3
+ class MiniProfiler
4
+ module Actions
5
+ def serve_snapshot(env)
6
+ MiniProfiler.authorize_request
7
+ status = 200
8
+ headers = { 'content-type' => 'text/html' }
9
+ qp = Rack::Utils.parse_nested_query(env['QUERY_STRING'])
10
+ if group_name = qp["group_name"]
11
+ list = @storage.snapshots_group(group_name)
12
+ list.each do |snapshot|
13
+ snapshot[:url] = url_for_snapshot(snapshot[:id], group_name)
14
+ end
15
+ data = {
16
+ group_name: group_name,
17
+ list: list
18
+ }
19
+ else
20
+ list = @storage.snapshots_overview
21
+ list.each do |group|
22
+ group[:url] = url_for_snapshots_group(group[:name])
23
+ end
24
+ data = {
25
+ page: "overview",
26
+ list: list
27
+ }
28
+ end
29
+ data_html = <<~HTML
30
+ <div style="display: none;" id="snapshots-data">
31
+ #{data.to_json}
32
+ </div>
33
+ HTML
34
+ response = Rack::Response.new([], status, headers)
35
+
36
+ response.write <<~HTML
37
+ <!DOCTYPE html>
38
+ <html>
39
+ <head>
40
+ <title>Rack::MiniProfiler Snapshots</title>
41
+ </head>
42
+ <body class="mp-snapshots">
43
+ HTML
44
+ response.write(data_html)
45
+ script = self.get_profile_script(env)
46
+ response.write(script)
47
+ response.write <<~HTML
48
+ </body>
49
+ </html>
50
+ HTML
51
+ response.finish
52
+ end
53
+
54
+ def serve_file(env, file_name:)
55
+ resources_env = env.dup
56
+ resources_env['PATH_INFO'] = file_name
57
+
58
+ if Gem::Version.new(Rack.release) >= Gem::Version.new("2.1.0")
59
+ rack_file = Rack::Files.new(resources_root, 'cache-control' => "max-age=#{cache_control_value}")
60
+ else
61
+ rack_file = Rack::File.new(resources_root, 'cache-control' => "max-age=#{cache_control_value}")
62
+ end
63
+
64
+ rack_file.call(resources_env)
65
+ end
66
+
67
+ def serve_results(env)
68
+ request = Rack::Request.new(env)
69
+ id = request.params['id']
70
+ group_name = request.params['group']
71
+ is_snapshot = group_name && group_name.size > 0
72
+ if is_snapshot
73
+ page_struct = @storage.load_snapshot(id, group_name)
74
+ else
75
+ page_struct = @storage.load(id)
76
+ end
77
+ if !page_struct && is_snapshot
78
+ id = ERB::Util.html_escape(id)
79
+ return [404, {}, ["Snapshot with id '#{id}' not found"]]
80
+ elsif !page_struct
81
+ @storage.set_viewed(user(env), id)
82
+ id = ERB::Util.html_escape(id)
83
+ user_info = ERB::Util.html_escape(user(env))
84
+ return [404, {}, ["Request not found: #{id} - user #{user_info}"]]
85
+ end
86
+ if !page_struct[:has_user_viewed] && !is_snapshot
87
+ page_struct[:client_timings] = TimerStruct::Client.init_from_form_data(env, page_struct)
88
+ page_struct[:has_user_viewed] = true
89
+ @storage.save(page_struct)
90
+ @storage.set_viewed(user(env), id)
91
+ end
92
+
93
+ # If we're an XMLHttpRequest, serve up the contents as JSON
94
+ if request.xhr?
95
+ result_json = page_struct.to_json
96
+ [200, { 'content-type' => 'application/json' }, [result_json]]
97
+ else
98
+ # Otherwise give the HTML back
99
+ html = generate_html(page_struct, env)
100
+ [200, { 'content-type' => 'text/html' }, [html]]
101
+ end
102
+ end
103
+
104
+ def serve_flamegraph(env)
105
+ request = Rack::Request.new(env)
106
+ id = request.params['id']
107
+ page_struct = @storage.load(id)
108
+
109
+ if !page_struct
110
+ id = ERB::Util.html_escape(id)
111
+ user_info = ERB::Util.html_escape(user(env))
112
+ return [404, {}, ["Request not found: #{id} - user #{user_info}"]]
113
+ end
114
+
115
+ if !page_struct[:flamegraph]
116
+ return [404, {}, ["No flamegraph available for #{ERB::Util.html_escape(id)}"]]
117
+ end
118
+
119
+ self.flamegraph(page_struct[:flamegraph], page_struct[:request_path], env)
120
+ end
121
+
122
+ def serve_profile_gc(env, client_settings)
123
+ return tool_disabled_message(client_settings) if !advanced_debugging_enabled?
124
+
125
+ client_settings.handle_cookie(Rack::MiniProfiler::GCProfiler.new.profile_gc(@app, env))
126
+ end
127
+
128
+ def serve_profile_memory(env, client_settings)
129
+ return tool_disabled_message(client_settings) if !advanced_debugging_enabled?
130
+
131
+ unless defined?(MemoryProfiler) && MemoryProfiler.respond_to?(:report)
132
+ message = "Please install the memory_profiler gem and require it: add gem 'memory_profiler' to your Gemfile"
133
+ _status, headers, body = @app.call(env)
134
+ body.close if body.respond_to? :close
135
+
136
+ return client_settings.handle_cookie(
137
+ text_result(message, status: 500, headers: headers)
138
+ )
139
+ end
140
+
141
+ query_params = Rack::Utils.parse_nested_query(env['QUERY_STRING'])
142
+ options = {
143
+ ignore_files: query_params['memory_profiler_ignore_files'],
144
+ allow_files: query_params['memory_profiler_allow_files'],
145
+ }
146
+ options[:top] = Integer(query_params['memory_profiler_top']) if query_params.key?('memory_profiler_top')
147
+ result = StringIO.new
148
+ report = MemoryProfiler.report(options) do
149
+ _, _, body = @app.call(env)
150
+ body.close if body.respond_to? :close
151
+ end
152
+ report.pretty_print(result)
153
+ client_settings.handle_cookie(text_result(result.string))
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ module Rack
3
+ class MiniProfiler
4
+ ASSET_VERSION = 'e0bcc9ce0ae3bb5d6b736b6f282f601f'
5
+ end
6
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ class ClientSettings
6
+
7
+ COOKIE_NAME = "__profilin"
8
+
9
+ BACKTRACE_DEFAULT = nil
10
+ BACKTRACE_FULL = 1
11
+ BACKTRACE_NONE = 2
12
+
13
+ attr_accessor :disable_profiling
14
+ attr_accessor :backtrace_level
15
+
16
+ def initialize(env, store, start)
17
+ @request = ::Rack::Request.new(env)
18
+ @cookie = @request.cookies[COOKIE_NAME]
19
+ @store = store
20
+ @start = start
21
+ @backtrace_level = nil
22
+ @orig_disable_profiling = @disable_profiling = nil
23
+
24
+ @allowed_tokens, @orig_auth_tokens = nil
25
+
26
+ if @cookie
27
+ @cookie.split(",").map { |pair| pair.split("=") }.each do |k, v|
28
+ @orig_disable_profiling = @disable_profiling = (v == 't') if k == "dp"
29
+ @backtrace_level = v.to_i if k == "bt"
30
+ @orig_auth_tokens = v.to_s.split("|") if k == "a"
31
+ end
32
+ end
33
+
34
+ if !@backtrace_level.nil? && (@backtrace_level == 0 || @backtrace_level > BACKTRACE_NONE)
35
+ @backtrace_level = nil
36
+ end
37
+
38
+ @orig_backtrace_level = @backtrace_level
39
+
40
+ end
41
+
42
+ def handle_cookie(result)
43
+ status, headers, _body = result
44
+
45
+ if (MiniProfiler.config.authorization_mode == :allow_authorized && !MiniProfiler.request_authorized?)
46
+ # this is non-obvious, don't kill the profiling cookie on errors or short requests
47
+ # this ensures that stuff that never reaches the rails stack does not kill profiling
48
+ if status.to_i >= 200 && status.to_i < 300 && ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start) > 0.1)
49
+ discard_cookie!(headers)
50
+ end
51
+ else
52
+ write!(headers)
53
+ end
54
+
55
+ result
56
+ end
57
+
58
+ def write!(headers)
59
+
60
+ tokens_changed = false
61
+
62
+ if MiniProfiler.request_authorized? && MiniProfiler.config.authorization_mode == :allow_authorized
63
+ @allowed_tokens ||= @store.allowed_tokens
64
+ tokens_changed = !@orig_auth_tokens || ((@allowed_tokens - @orig_auth_tokens).length > 0)
65
+ end
66
+
67
+ if @orig_disable_profiling != @disable_profiling ||
68
+ @orig_backtrace_level != @backtrace_level ||
69
+ @cookie.nil? ||
70
+ tokens_changed
71
+
72
+ settings = { "p" => "t" }
73
+ settings["dp"] = "t" if @disable_profiling
74
+ settings["bt"] = @backtrace_level if @backtrace_level
75
+ settings["a"] = @allowed_tokens.join("|") if @allowed_tokens && MiniProfiler.request_authorized?
76
+ settings_string = settings.map { |k, v| "#{k}=#{v}" }.join(",")
77
+ cookie = { value: settings_string, path: MiniProfiler.config.cookie_path, httponly: true }
78
+ cookie[:secure] = true if @request.ssl?
79
+ cookie[:same_site] = 'Lax'
80
+ Rack::Utils.set_cookie_header!(headers, COOKIE_NAME, cookie)
81
+ end
82
+ end
83
+
84
+ def discard_cookie!(headers)
85
+ if @cookie
86
+ Rack::Utils.delete_cookie_header!(headers, COOKIE_NAME, path: MiniProfiler.config.cookie_path)
87
+ end
88
+ end
89
+
90
+ def has_valid_cookie?
91
+ valid_cookie = !@cookie.nil?
92
+
93
+ if (MiniProfiler.config.authorization_mode == :allow_authorized) && valid_cookie
94
+ begin
95
+ @allowed_tokens ||= @store.allowed_tokens
96
+ rescue => e
97
+ if MiniProfiler.config.storage_failure != nil
98
+ MiniProfiler.config.storage_failure.call(e)
99
+ end
100
+ end
101
+
102
+ valid_cookie = @allowed_tokens &&
103
+ (Array === @orig_auth_tokens) &&
104
+ ((@allowed_tokens & @orig_auth_tokens).length > 0)
105
+ end
106
+
107
+ valid_cookie
108
+ end
109
+
110
+ def disable_profiling?
111
+ @disable_profiling
112
+ end
113
+
114
+ def backtrace_full?
115
+ @backtrace_level == BACKTRACE_FULL
116
+ end
117
+
118
+ def backtrace_default?
119
+ @backtrace_level == BACKTRACE_DEFAULT
120
+ end
121
+
122
+ def backtrace_none?
123
+ @backtrace_level == BACKTRACE_NONE
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ class Config
6
+ def self.attr_accessor(*vars)
7
+ @attributes ||= []
8
+ @attributes.concat vars
9
+ super(*vars)
10
+ end
11
+
12
+ def self.attributes
13
+ @attributes
14
+ end
15
+
16
+ def self.default
17
+ new.instance_eval {
18
+ @auto_inject = true # automatically inject on every html page
19
+ @base_url_path = "/mini-profiler-resources/".dup
20
+ @cookie_path = "/".dup
21
+ @disable_caching = true
22
+ # called prior to rack chain, to ensure we are allowed to profile
23
+ @pre_authorize_cb = lambda { |env| true }
24
+
25
+ # called after rack chain, to ensure we are REALLY allowed to profile
26
+ @skip_schema_queries = false
27
+ @storage = MiniProfiler::MemoryStore
28
+ @user_provider = Proc.new { |env| Rack::Request.new(env).ip }
29
+ @authorization_mode = :allow_all
30
+ @backtrace_threshold_ms = 0
31
+ @flamegraph_sample_rate = 0.5
32
+ @flamegraph_mode = :wall
33
+ @flamegraph_ignore_gc = false
34
+ @storage_failure = Proc.new do |exception|
35
+ if @logger
36
+ @logger.warn("MiniProfiler storage failure: #{exception.message}")
37
+ end
38
+ end
39
+ @enabled = true
40
+ @max_sql_param_length = 0 # disable sql parameter collection by default
41
+ @skip_sql_param_names = /password/ # skips parameters with the name password by default
42
+ @enable_advanced_debugging_tools = false
43
+ @snapshot_every_n_requests = -1
44
+ @max_snapshot_groups = 50
45
+ @max_snapshots_per_group = 15
46
+
47
+ # ui parameters
48
+ @autorized = true
49
+ @collapse_results = true
50
+ @max_traces_to_show = 20
51
+ @show_children = false
52
+ @show_controls = false
53
+ @show_trivial = false
54
+ @show_total_sql_count = false
55
+ @start_hidden = false
56
+ @toggle_shortcut = 'alt+p'
57
+ @html_container = 'body'
58
+ @position = "top-left"
59
+ @snapshot_hidden_custom_fields = []
60
+ @snapshots_transport_destination_url = nil
61
+ @snapshots_transport_auth_key = nil
62
+ @snapshots_redact_sql_queries = true
63
+ @snapshots_transport_gzip_requests = false
64
+ @enable_hotwire_turbo_drive_support = false
65
+
66
+ @profile_parameter = "pp"
67
+
68
+ self
69
+ }
70
+ end
71
+
72
+ attr_accessor :authorization_mode, :auto_inject, :backtrace_ignores,
73
+ :backtrace_includes, :backtrace_remove, :backtrace_threshold_ms,
74
+ :base_url_path, :cookie_path, :disable_caching, :enabled,
75
+ :flamegraph_sample_rate, :logger, :pre_authorize_cb, :skip_paths,
76
+ :skip_schema_queries, :storage, :storage_failure, :storage_instance,
77
+ :storage_options, :user_provider, :enable_advanced_debugging_tools,
78
+ :skip_sql_param_names, :suppress_encoding, :max_sql_param_length,
79
+ :content_security_policy_nonce, :enable_hotwire_turbo_drive_support,
80
+ :flamegraph_mode, :flamegraph_ignore_gc, :profile_parameter
81
+
82
+ # ui accessors
83
+ attr_accessor :collapse_results, :max_traces_to_show, :position,
84
+ :show_children, :show_controls, :show_trivial, :show_total_sql_count,
85
+ :start_hidden, :toggle_shortcut, :html_container
86
+
87
+ # snapshot related config
88
+ attr_accessor :snapshot_every_n_requests, :max_snapshots_per_group,
89
+ :snapshot_hidden_custom_fields, :snapshots_transport_destination_url,
90
+ :snapshots_transport_auth_key, :snapshots_redact_sql_queries,
91
+ :snapshots_transport_gzip_requests, :max_snapshot_groups
92
+
93
+ # Deprecated options
94
+ attr_accessor :use_existing_jquery
95
+
96
+ attr_reader :assets_url
97
+
98
+ # redefined - since the accessor defines it first
99
+ undef :authorization_mode=
100
+ # rubocop:disable Lint/DuplicateMethods
101
+ def authorization_mode=(mode)
102
+ # rubocop:enable Lint/DuplicateMethods
103
+ if mode == :whitelist
104
+ warn "[DEPRECATION] `:whitelist` authorization mode is deprecated. Please use `:allow_authorized` instead."
105
+
106
+ mode = :allow_authorized
107
+ end
108
+
109
+ warn <<~DEP unless mode == :allow_authorized || mode == :allow_all
110
+ [DEPRECATION] unknown authorization mode #{mode}. Expected `:allow_all` or `:allow_authorized`.
111
+ DEP
112
+
113
+ @authorization_mode = mode
114
+ end
115
+
116
+ def assets_url=(lmbda)
117
+ if defined?(Rack::MiniProfilerRails)
118
+ Rack::MiniProfilerRails.create_engine
119
+ end
120
+ @assets_url = lmbda
121
+ end
122
+
123
+ def vertical_position
124
+ position.include?('bottom') ? 'bottom' : 'top'
125
+ end
126
+
127
+ def horizontal_position
128
+ position.include?('right') ? 'right' : 'left'
129
+ end
130
+
131
+ def merge!(config)
132
+ if config
133
+ if Hash === config
134
+ config.each { |k, v| instance_variable_set "@#{k}", v }
135
+ else
136
+ self.class.attributes.each { |k|
137
+ v = config.send k
138
+ instance_variable_set "@#{k}", v if v
139
+ }
140
+ end
141
+ end
142
+ end
143
+
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Rack::MiniProfiler::Context
4
+ attr_accessor :inject_js, :current_timer, :page_struct, :skip_backtrace,
5
+ :full_backtrace, :discard, :mpt_init, :measure
6
+
7
+ def initialize(opts = {})
8
+ opts["measure"] = true unless opts.key? "measure"
9
+ opts.each do |k, v|
10
+ self.instance_variable_set('@' + k, v)
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Rack::MiniProfiler::GCProfiler
4
+
5
+ def initialize
6
+ @ignore = []
7
+ @ignore << @ignore.__id__
8
+ end
9
+
10
+ def object_space_stats
11
+ stats = Hash.new(0).compare_by_identity
12
+ ids = Hash.new.compare_by_identity
13
+
14
+ @ignore << stats.__id__
15
+ @ignore << ids.__id__
16
+
17
+ ObjectSpace.each_object { |o|
18
+ begin
19
+ stats[o.class] += 1
20
+ ids[o.__id__] = o if Integer === o.__id__
21
+ rescue NoMethodError
22
+ # protect against BasicObject
23
+ end
24
+ }
25
+
26
+ @ignore.each do |id|
27
+ if ids.delete(id)
28
+ klass = ObjectSpace._id2ref(id).class
29
+ stats[klass] -= 1
30
+ end
31
+ end
32
+
33
+ result = { stats: stats, ids: ids }
34
+ @ignore << result.__id__
35
+
36
+ result
37
+ end
38
+
39
+ def diff_object_stats(before, after)
40
+ diff = {}.compare_by_identity
41
+ after.each do |k, v|
42
+ diff[k] = v - before[k]
43
+ end
44
+ before.each do |k, v|
45
+ diff[k] = 0 - v unless after.has_key?(k)
46
+ end
47
+
48
+ diff
49
+ end
50
+
51
+ def analyze_strings(ids_before, ids_after)
52
+ result = {}
53
+ ids_after.each do |id, _|
54
+ obj = ObjectSpace._id2ref(id)
55
+ if String === obj && !ids_before.include?(obj.object_id)
56
+ result[obj] ||= 0
57
+ result[obj] += 1
58
+ end
59
+ end
60
+ result
61
+ end
62
+
63
+ def analyze_growth(ids_before, ids_after)
64
+ new_objects = 0
65
+ memory_allocated = 0
66
+
67
+ ids_after.each do |id, _|
68
+ if !ids_before.include?(id) && obj = ObjectSpace._id2ref(id)
69
+ # this is going to be version specific (may change in 2.1)
70
+ size = ObjectSpace.memsize_of(obj)
71
+ memory_allocated += size
72
+ new_objects += 1
73
+ end
74
+ end
75
+
76
+ [new_objects, memory_allocated]
77
+ end
78
+
79
+ def analyze_initial_state(ids_before)
80
+ memory_allocated = 0
81
+ objects = 0
82
+
83
+ ids_before.each do |id, _|
84
+ if obj = ObjectSpace._id2ref(id)
85
+ # this is going to be version specific (may change in 2.1)
86
+ memory_allocated += ObjectSpace.memsize_of(obj)
87
+ objects += 1
88
+ end
89
+ end
90
+
91
+ [objects, memory_allocated]
92
+ end
93
+
94
+ def profile_gc(app, env)
95
+
96
+ # for memsize_of
97
+ require 'objspace'
98
+
99
+ # clean up before
100
+ GC.start
101
+ stat = GC.stat
102
+ prev_gc_state = GC.disable
103
+ stat_before = object_space_stats
104
+ b = app.call(env)[2]
105
+ b.close if b.respond_to? :close
106
+ stat_after = object_space_stats
107
+ # so we don't blow out on memory
108
+ prev_gc_state ? GC.disable : GC.enable
109
+
110
+ diff = diff_object_stats(stat_before[:stats], stat_after[:stats])
111
+ string_analysis = analyze_strings(stat_before[:ids], stat_after[:ids])
112
+ new_objects, memory_allocated = analyze_growth(stat_before[:ids], stat_after[:ids])
113
+ objects_before, memory_before = analyze_initial_state(stat_before[:ids])
114
+
115
+ body = []
116
+
117
+ body << "
118
+ Overview
119
+ --------
120
+ Initial state: object count: #{objects_before}
121
+ Memory allocated outside heap (bytes): #{memory_before}
122
+
123
+ GC Stats:
124
+ --------
125
+ #{stat.map { |k, v| "#{k} : #{v}" }.sort!.join("\n")}
126
+
127
+ New bytes allocated outside of Ruby heaps: #{memory_allocated}
128
+ New objects: #{new_objects}
129
+ "
130
+
131
+ body << "
132
+ ObjectSpace delta caused by request:
133
+ -----------------------------------\n"
134
+ diff.to_a.delete_if { |_k, v| v == 0 }.sort_by! { |_k, v| v }.reverse_each do |k, v|
135
+ body << "#{k} : #{v}\n"
136
+ end
137
+
138
+ body << "\n
139
+ ObjectSpace stats:
140
+ -----------------\n"
141
+
142
+ stat_after[:stats].to_a.sort_by! { |_k, v| v }.reverse_each do |k, v|
143
+ body << "#{k} : #{v}\n"
144
+ end
145
+
146
+ body << "\n
147
+ String stats:
148
+ ------------\n"
149
+
150
+ string_analysis.to_a.sort_by! { |_k, v| -v }.take(1000).each do |string, count|
151
+ body << "#{count} : #{string}\n"
152
+ end
153
+
154
+ [200, { Rack::CONTENT_TYPE => 'text/plain' }, body]
155
+ ensure
156
+ prev_gc_state ? GC.disable : GC.enable
157
+ end
158
+ end