rails_mini_profiler 0.4.0 → 0.7.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -34
  3. data/app/adapters/rails_mini_profiler/database_adapter.rb +16 -0
  4. data/app/controllers/rails_mini_profiler/application_controller.rb +9 -15
  5. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +44 -14
  6. data/app/helpers/rails_mini_profiler/application_helper.rb +1 -1
  7. data/app/helpers/rails_mini_profiler/profiled_requests_helper.rb +10 -0
  8. data/app/javascript/images/check.svg +3 -0
  9. data/app/javascript/images/chevron.svg +3 -0
  10. data/app/javascript/images/copy.svg +6 -0
  11. data/app/javascript/images/filter.svg +1 -0
  12. data/app/javascript/images/logo_variant.svg +2 -2
  13. data/app/javascript/images/search.svg +4 -5
  14. data/app/javascript/js/checklist_controller.js +48 -0
  15. data/app/javascript/js/clipboard_controller.js +53 -0
  16. data/app/javascript/js/enable_controller.js +23 -0
  17. data/app/javascript/js/filter_controller.js +48 -0
  18. data/app/javascript/js/search_controller.js +18 -0
  19. data/app/javascript/js/select_controller.js +52 -0
  20. data/app/javascript/packs/rails-mini-profiler.js +69 -53
  21. data/app/javascript/stylesheets/components/buttons.scss +59 -0
  22. data/app/javascript/stylesheets/components/dropdown.scss +103 -0
  23. data/app/javascript/stylesheets/components/input.scss +10 -0
  24. data/app/javascript/stylesheets/{navbar.scss → components/navbar.scss} +7 -13
  25. data/app/javascript/stylesheets/components/page_header.scss +7 -0
  26. data/app/javascript/stylesheets/components/pagination.scss +14 -13
  27. data/app/javascript/stylesheets/components/placeholder.scss +36 -0
  28. data/app/javascript/stylesheets/components/profiled_request_table.scss +55 -0
  29. data/app/javascript/stylesheets/components/trace.scss +93 -0
  30. data/app/javascript/stylesheets/flamegraph.scss +3 -2
  31. data/app/javascript/stylesheets/flashes.scss +3 -5
  32. data/app/javascript/stylesheets/profiled_requests.scss +12 -161
  33. data/app/javascript/stylesheets/rails-mini-profiler.scss +81 -66
  34. data/app/javascript/stylesheets/traces.scss +52 -56
  35. data/app/models/rails_mini_profiler/profiled_request.rb +1 -1
  36. data/app/models/rails_mini_profiler/trace.rb +0 -15
  37. data/app/presenters/rails_mini_profiler/controller_trace_presenter.rb +10 -2
  38. data/app/presenters/rails_mini_profiler/instantiation_trace_presenter.rb +15 -3
  39. data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +10 -17
  40. data/app/presenters/rails_mini_profiler/render_partial_trace_presenter.rb +6 -2
  41. data/app/presenters/rails_mini_profiler/render_template_trace_presenter.rb +6 -2
  42. data/app/presenters/rails_mini_profiler/sequel_trace_presenter.rb +16 -4
  43. data/app/presenters/rails_mini_profiler/trace_presenter.rb +10 -8
  44. data/app/search/rails_mini_profiler/base_search.rb +67 -0
  45. data/app/search/rails_mini_profiler/profiled_request_search.rb +33 -0
  46. data/app/search/rails_mini_profiler/trace_search.rb +27 -0
  47. data/app/views/rails_mini_profiler/badge.html.erb +2 -2
  48. data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +8 -58
  49. data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +19 -0
  50. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_placeholder.erb +12 -0
  51. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table.erb +14 -0
  52. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +125 -0
  53. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_row.erb +21 -0
  54. data/app/views/rails_mini_profiler/profiled_requests/{shared → show}/_trace.html.erb +24 -7
  55. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list.erb +12 -0
  56. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_header.erb +87 -0
  57. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_placeholder.erb +12 -0
  58. data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +5 -18
  59. data/app/views/rails_mini_profiler/shared/_head.erb +1 -1
  60. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +2 -0
  61. data/lib/rails_mini_profiler/badge.rb +21 -12
  62. data/lib/rails_mini_profiler/configuration/user_interface.rb +31 -1
  63. data/lib/rails_mini_profiler/configuration.rb +7 -0
  64. data/lib/rails_mini_profiler/engine.rb +12 -8
  65. data/lib/rails_mini_profiler/flamegraph_guard.rb +10 -6
  66. data/lib/rails_mini_profiler/guard.rb +19 -1
  67. data/lib/rails_mini_profiler/middleware.rb +12 -10
  68. data/lib/rails_mini_profiler/request_context.rb +22 -18
  69. data/lib/rails_mini_profiler/request_wrapper.rb +12 -55
  70. data/lib/rails_mini_profiler/response_wrapper.rb +21 -17
  71. data/lib/rails_mini_profiler/tracers/controller_tracer.rb +29 -0
  72. data/lib/rails_mini_profiler/tracers/instantiation_tracer.rb +17 -0
  73. data/lib/rails_mini_profiler/tracers/null_trace.rb +7 -0
  74. data/lib/rails_mini_profiler/tracers/registry.rb +76 -0
  75. data/lib/rails_mini_profiler/tracers/rmp_tracer.rb +17 -0
  76. data/lib/rails_mini_profiler/tracers/sequel_tracer.rb +51 -0
  77. data/lib/rails_mini_profiler/tracers/sequel_tracker.rb +40 -0
  78. data/lib/rails_mini_profiler/tracers/subscriptions.rb +28 -0
  79. data/lib/rails_mini_profiler/{models → tracers}/trace.rb +11 -3
  80. data/lib/rails_mini_profiler/tracers/trace_factory.rb +27 -0
  81. data/lib/rails_mini_profiler/tracers/tracer.rb +45 -0
  82. data/lib/rails_mini_profiler/tracers/view_tracer.rb +29 -0
  83. data/lib/rails_mini_profiler/tracers.rb +12 -83
  84. data/lib/rails_mini_profiler/user.rb +1 -1
  85. data/lib/rails_mini_profiler/version.rb +1 -1
  86. data/lib/rails_mini_profiler.rb +4 -8
  87. data/vendor/assets/images/check.svg +3 -0
  88. data/vendor/assets/images/chevron.svg +3 -0
  89. data/vendor/assets/images/copy.svg +6 -0
  90. data/vendor/assets/images/filter.svg +1 -0
  91. data/vendor/assets/images/logo_variant.svg +2 -2
  92. data/vendor/assets/images/search.svg +4 -5
  93. data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
  94. data/vendor/assets/javascripts/rails-mini-profiler.js +1 -1
  95. metadata +58 -13
  96. data/app/models/rails_mini_profiler/controller_trace.rb +0 -37
  97. data/app/models/rails_mini_profiler/instantiation_trace.rb +0 -37
  98. data/app/models/rails_mini_profiler/render_partial_trace.rb +0 -37
  99. data/app/models/rails_mini_profiler/render_template_trace.rb +0 -37
  100. data/app/models/rails_mini_profiler/rmp_trace.rb +0 -35
  101. data/app/models/rails_mini_profiler/sequel_trace.rb +0 -37
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class ControllerTracer < Tracer
6
+ class << self
7
+ def subscribes_to
8
+ 'process_action.action_controller'
9
+ end
10
+
11
+ def build_from(event)
12
+ new(event).trace
13
+ end
14
+
15
+ def presents
16
+ ControllerTracePresenter
17
+ end
18
+ end
19
+
20
+ def trace
21
+ @event[:payload] = @event[:payload]
22
+ .slice(:view_runtime, :db_runtime)
23
+ .reject { |_k, v| v.blank? }
24
+ .transform_values { |value| value&.round(2) }
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class InstantiationTracer < Tracer
6
+ class << self
7
+ def subscribes_to
8
+ 'instantiation.active_record'
9
+ end
10
+
11
+ def presents
12
+ InstantiationTracePresenter
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class NullTrace < Trace; end
6
+ end
7
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ # This serves as a central store for tracers. Based on the configuration, indidual tracers are registered and are
6
+ # then available to subscribe to events or render traced events.
7
+ #
8
+ # @api private
9
+ class Registry
10
+ class << self
11
+ def setup!(config)
12
+ new(config)
13
+ end
14
+ end
15
+
16
+ def initialize(config)
17
+ @config = config
18
+ @config.tracers.each { |tracer| add(tracer) }
19
+ end
20
+
21
+ # Tracers that are available in the application, indexed by events they subscribe to.
22
+ #
23
+ # @return [Hash] a hash where keys are event names and values are the corresponding tracers
24
+ def tracers
25
+ @tracers ||=
26
+ tracer_map
27
+ .values
28
+ .each_with_object({}) do |tracer, obj|
29
+ subscriptions = wrap(tracer.subscribes_to)
30
+ subscriptions.each { |subscription| obj[subscription] = tracer }
31
+ end
32
+ end
33
+
34
+ # Presenters that are available in the application, indexed by events they should present.
35
+ #
36
+ # @return [Hash] a hash where keys are event names and values are the corresponding presenters
37
+ def presenters
38
+ @presenters ||=
39
+ tracer_map
40
+ .values
41
+ .each_with_object({}) do |tracer, obj|
42
+ presenters = tracer.presents
43
+ if presenters.is_a?(Hash)
44
+ obj.merge!(presenters)
45
+ else
46
+ obj[tracer.subscribes_to] = presenters
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def tracer_map
54
+ @tracer_map ||= {}
55
+ end
56
+
57
+ def add(tracer)
58
+ tracer = tracer.to_sym
59
+ tracer = "#{tracer.to_s.camelize}Tracer"
60
+ constant = "RailsMiniProfiler::Tracers::#{tracer}".safe_constantize
61
+
62
+ tracer_map[tracer] = constant if constant
63
+ end
64
+
65
+ def wrap(object)
66
+ if object.nil?
67
+ []
68
+ elsif object.respond_to?(:to_ary)
69
+ object.to_ary || [object]
70
+ else
71
+ [object]
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class RmpTracer < Tracer
6
+ class << self
7
+ def subscribes_to
8
+ 'rails_mini_profiler.total_time'
9
+ end
10
+
11
+ def presents
12
+ RmpTracePresenter
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class SequelTracer < Tracer
6
+ class << self
7
+ def subscribes_to
8
+ 'sql.active_record'
9
+ end
10
+
11
+ def build_from(event)
12
+ new(event).trace
13
+ end
14
+
15
+ def presents
16
+ SequelTracePresenter
17
+ end
18
+ end
19
+
20
+ def trace
21
+ return NullTrace.new if ignore?
22
+
23
+ payload = @event[:payload].slice(:name, :sql, :binds, :type_casted_binds)
24
+ typecasted_binds = payload[:type_casted_binds]
25
+ # Sometimes, typecasted binds are a proc. Not sure why. In those instances, we extract the typecasted
26
+ # values from the proc by executing call.
27
+ typecasted_binds = typecasted_binds.call if typecasted_binds.respond_to?(:call)
28
+ payload[:binds] = transform_binds(payload[:binds], typecasted_binds)
29
+ payload.delete(:type_casted_binds)
30
+ payload.reject { |_k, v| v.blank? }
31
+ @event[:payload] = payload
32
+ super
33
+ end
34
+
35
+ private
36
+
37
+ def transform_binds(binds, type_casted_binds)
38
+ binds.each_with_object([]).with_index do |(binding, object), i|
39
+ name = binding.name
40
+ value = type_casted_binds[i]
41
+ object << { name: name, value: value }
42
+ end
43
+ end
44
+
45
+ def ignore?
46
+ payload = @event[:payload]
47
+ !SqlTracker.new(name: payload[:name], query: payload[:sql]).track?
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ # Utility to clean up and simplify SQL Notification events.
6
+ #
7
+ # @api private
8
+ class SqlTracker
9
+ TRACKED_SQL_COMMANDS = %w[SELECT INSERT UPDATE DELETE].freeze
10
+ UNTRACKED_NAMES = %w[SCHEMA].freeze
11
+ UNTRACKED_TABLES = %w[
12
+ SCHEMA_MIGRATIONS
13
+ SQLITE_MASTER
14
+ ACTIVE_MONITORING_METRICS
15
+ SQLITE_TEMP_MASTER
16
+ SQLITE_VERSION
17
+ AR_INTERNAL_METADATA
18
+ ].freeze
19
+
20
+ def initialize(query:, name:)
21
+ @query = query.to_s.upcase
22
+ @name = name.to_s.upcase
23
+ end
24
+
25
+ def track?
26
+ query.start_with?(*TRACKED_SQL_COMMANDS) &&
27
+ !name.start_with?(*UNTRACKED_NAMES) &&
28
+ !untracked_tables?
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :query, :name
34
+
35
+ def untracked_tables?
36
+ UNTRACKED_TABLES.any? { |table| query.include?(table) }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ # Subscribe to application events. This is used during engine startup.
6
+ # @api private
7
+ class Subscriptions
8
+ class << self
9
+ # Subscribe to each individual active support event using a callback.
10
+ def setup!(subscriptions, &callback)
11
+ subscriptions.each do |event|
12
+ subscribe(event, &callback)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def subscribe(*subscriptions, &callback)
19
+ subscriptions.each do |subscription|
20
+ ActiveSupport::Notifications.subscribe(subscription) do |event|
21
+ callback.call(event)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- module Models
4
+ module Tracers
5
5
  # A simplified representation of a trace.
6
6
  #
7
7
  # Is transformed into [RailsMiniProfiler::Trace] when recording has finished.
@@ -23,15 +23,23 @@ module RailsMiniProfiler
23
23
  # @!attribute backtrace
24
24
  # @return [String] the line where this trace was recorded
25
25
  # @!attribute allocations
26
- # @return [Integer] the number of alloactions
26
+ # @return [Integer] the number of allocations
27
27
  # @!attribute created_at
28
28
  # @return [DateTime] the creation date
29
29
  # @!attribute updated_at
30
30
  # @return [DateTime] the last updated date
31
31
  #
32
32
  # @api private
33
- class Trace < BaseModel
33
+ class Trace < RailsMiniProfiler::Models::BaseModel
34
34
  attr_accessor :id, :name, :start, :finish, :duration, :payload, :backtrace, :allocations, :created_at, :updated_at
35
+
36
+ def ignore?
37
+ false
38
+ end
39
+
40
+ def transform!
41
+ self
42
+ end
35
43
  end
36
44
  end
37
45
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ # Creates traces based on the tracers registered with the application
6
+ #
7
+ # For example, an event with name 'sequel' will result in the lookup of a tracers that responds to that particular
8
+ # event. The tracer itself will then build the trace from the event.
9
+ #
10
+ # @api private
11
+ class TraceFactory
12
+ def initialize(registry)
13
+ @tracers = registry.tracers
14
+ end
15
+
16
+ # Create a new trace from an event
17
+ #
18
+ # @param event [ActiveSupport::Notifications::Event] an event from the application
19
+ #
20
+ # @return [Trace] a processed trace
21
+ def create(event)
22
+ tracer = @tracers[event.name] || Tracer
23
+ tracer.build_from(event)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class Tracer
6
+ class << self
7
+ def subscribes_to
8
+ []
9
+ end
10
+
11
+ def presents
12
+ TracePresenter
13
+ end
14
+
15
+ def build_from(event)
16
+ new(event).trace
17
+ end
18
+ end
19
+
20
+ def initialize(event)
21
+ @event = event_data(event)
22
+ end
23
+
24
+ def trace
25
+ Trace.new(**@event)
26
+ end
27
+
28
+ private
29
+
30
+ def event_data(event)
31
+ start = (event.time.to_f * 100_000).to_i
32
+ finish = (event.end.to_f * 100_000).to_i
33
+ {
34
+ name: event.name,
35
+ start: start,
36
+ finish: finish,
37
+ duration: finish - start,
38
+ allocations: event.allocations,
39
+ backtrace: Rails.backtrace_cleaner.clean(caller),
40
+ payload: event.payload
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ module Tracers
5
+ class ViewTracer < Tracer
6
+ class << self
7
+ def subscribes_to
8
+ %w[render_template.action_view render_partial.action_view]
9
+ end
10
+
11
+ def build_from(event)
12
+ new(event).trace
13
+ end
14
+
15
+ def presents
16
+ {
17
+ 'render_template.action_view' => RenderTemplateTracePresenter,
18
+ 'render_partial.action_view' => RenderPartialTracePresenter
19
+ }
20
+ end
21
+ end
22
+
23
+ def trace
24
+ @event[:payload].slice!(:identifier, :count)
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,85 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RailsMiniProfiler
4
- class Tracers
5
- DEFAULT_SUBSCRIPTIONS = %w[
6
- sql.active_record
7
- instantiation.active_record
8
- render_template.action_view
9
- render_partial.action_view
10
- process_action.action_controller
11
- rails_mini_profiler.total_time
12
- ].freeze
13
-
14
- class << self
15
- def setup!(&callback)
16
- DEFAULT_SUBSCRIPTIONS.each do |event|
17
- subscribe(event, &callback)
18
- end
19
- end
20
-
21
- def build_trace(event)
22
- start = (event.time.to_f * 100_000).to_i
23
- finish = (event.end.to_f * 100_000).to_i
24
- Models::Trace.new(
25
- name: event.name,
26
- start: start,
27
- finish: finish,
28
- duration: finish - start,
29
- allocations: event.allocations,
30
- backtrace: Rails.backtrace_cleaner.clean(caller),
31
- payload: format_payload(event)
32
- )
33
- end
34
-
35
- private
36
-
37
- def subscribe(*subscriptions, &callback)
38
- subscriptions.each do |subscription|
39
- ActiveSupport::Notifications.subscribe(subscription) do |event|
40
- callback.call(event)
41
- end
42
- end
43
- end
44
-
45
- def format_payload(event)
46
- case event.name
47
- when 'sql.active_record'
48
- transform_sql_event(event)
49
- when 'render_template.action_view', 'render_partial.action_view'
50
- event.payload.slice(:identifier, :count)
51
- when 'process_action.action_controller'
52
- transform_controller_event(event)
53
- else
54
- event.payload
55
- end
56
- end
57
-
58
- def transform_sql_event(event)
59
- payload = event.payload.slice(:name, :sql, :binds, :type_casted_binds)
60
- typecasted_binds = payload[:type_casted_binds]
61
- # Sometimes, typecasted binds are a proc. Not sure why. In those instances, we extract the typecasted
62
- # values from the proc by executing call.
63
- typecasted_binds = typecasted_binds.call if typecasted_binds.respond_to?(:call)
64
- payload[:binds] = transform_binds(payload[:binds], typecasted_binds)
65
- payload.delete(:type_casted_binds)
66
- payload.reject { |_k, v| v.blank? }
67
- end
68
-
69
- def transform_binds(binds, type_casted_binds)
70
- binds.each_with_object([]).with_index do |(binding, object), i|
71
- name = binding.name
72
- value = type_casted_binds[i]
73
- object << { name: name, value: value }
74
- end
75
- end
76
-
77
- def transform_controller_event(event)
78
- payload = event.payload
79
- .slice(:view_runtime, :db_runtime)
80
- .transform_values { |value| value&.round(2) }
81
- payload.reject { |_k, v| v.blank? }
82
- end
83
- end
84
- end
85
- end
3
+ require 'rails_mini_profiler/tracers/registry'
4
+ require 'rails_mini_profiler/tracers/subscriptions'
5
+ require 'rails_mini_profiler/tracers/trace'
6
+ require 'rails_mini_profiler/tracers/tracer'
7
+ require 'rails_mini_profiler/tracers/controller_tracer'
8
+ require 'rails_mini_profiler/tracers/instantiation_tracer'
9
+ require 'rails_mini_profiler/tracers/sequel_tracker'
10
+ require 'rails_mini_profiler/tracers/sequel_tracer'
11
+ require 'rails_mini_profiler/tracers/view_tracer'
12
+ require 'rails_mini_profiler/tracers/rmp_tracer'
13
+ require 'rails_mini_profiler/tracers/null_trace'
14
+ require 'rails_mini_profiler/tracers/trace_factory'
@@ -30,7 +30,7 @@ module RailsMiniProfiler
30
30
  end
31
31
 
32
32
  def find_current_user
33
- return unless Rails.env.development? || Rails.env.test?
33
+ return if Rails.env.production?
34
34
 
35
35
  user = RailsMiniProfiler.configuration.user_provider.call(@env)
36
36
  User.current_user = user
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- VERSION = '0.4.0'
4
+ VERSION = '0.7.1'
5
5
  end
@@ -7,23 +7,19 @@ require 'pagy'
7
7
  require 'rails_mini_profiler/version'
8
8
  require 'rails_mini_profiler/engine'
9
9
 
10
- require 'rails_mini_profiler/user'
11
- require 'rails_mini_profiler/request_context'
12
-
13
10
  require 'rails_mini_profiler/models/base_model'
14
- require 'rails_mini_profiler/models/trace'
11
+ require 'rails_mini_profiler/tracers'
12
+ require 'rails_mini_profiler/configuration'
15
13
 
14
+ require 'rails_mini_profiler/user'
15
+ require 'rails_mini_profiler/request_context'
16
16
  require 'rails_mini_profiler/logger'
17
- require 'rails_mini_profiler/configuration'
18
- require 'rails_mini_profiler/configuration/storage'
19
- require 'rails_mini_profiler/configuration/user_interface'
20
17
  require 'rails_mini_profiler/request_wrapper'
21
18
  require 'rails_mini_profiler/response_wrapper'
22
19
  require 'rails_mini_profiler/guard'
23
20
  require 'rails_mini_profiler/flamegraph_guard'
24
21
  require 'rails_mini_profiler/redirect'
25
22
  require 'rails_mini_profiler/badge'
26
- require 'rails_mini_profiler/tracers'
27
23
  require 'rails_mini_profiler/middleware'
28
24
 
29
25
  # Main namespace for Rails Mini Profiler
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 407.437 407.437">
2
+ <path fill="currentColor" d="M386.258 91.567l-182.54 181.945L21.179 91.567 0 112.815 203.718 315.87l203.719-203.055z"/>
3
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg"
2
+ viewBox="0 0 488.3 488.3" style="enable-background:new 0 0 488.3 488.3" xml:space="preserve">
3
+ <path fill="currentColor"
4
+ d="M314.25 85.4h-227c-21.3 0-38.6 17.3-38.6 38.6v325.7c0 21.3 17.3 38.6 38.6 38.6h227c21.3 0 38.6-17.3 38.6-38.6V124c-.1-21.3-17.4-38.6-38.6-38.6zm11.5 364.2c0 6.4-5.2 11.6-11.6 11.6h-227c-6.4 0-11.6-5.2-11.6-11.6V124c0-6.4 5.2-11.6 11.6-11.6h227c6.4 0 11.6 5.2 11.6 11.6v325.6z"/>
5
+ <path fill="currentColor"
6
+ d="M401.05 0h-227c-21.3 0-38.6 17.3-38.6 38.6 0 7.5 6 13.5 13.5 13.5s13.5-6 13.5-13.5c0-6.4 5.2-11.6 11.6-11.6h227c6.4 0 11.6 5.2 11.6 11.6v325.7c0 6.4-5.2 11.6-11.6 11.6-7.5 0-13.5 6-13.5 13.5s6 13.5 13.5 13.5c21.3 0 38.6-17.3 38.6-38.6V38.6c0-21.3-17.3-38.6-38.6-38.6z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-filter"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg>
@@ -1,5 +1,5 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1070" height="1070" viewBox="0 0 1070 1070" version="1.1">
2
- <style>path{fill:none;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4}</style>
1
+ <svg id="logo-variant" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1070" height="1070" viewBox="0 0 1070 1070" version="1.1">
2
+ <style>#logo-variant path{fill:none;stroke-width:64;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4}</style>
3
3
  <defs>
4
4
  <linearGradient id="lightShadow">
5
5
  <stop offset="0" style="stop-color:#c22121;stop-opacity:1"/>
@@ -1,10 +1,9 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
- <title>Iconly/Bulk/Search</title>
4
- <g id="Iconly/Bulk/Search" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
- <g id="Search" transform="translate(2.000000, 2.000000)" fill="#000000" fill-rule="nonzero">
3
+ <g id="Iconly/Bulk/Search" stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd">
4
+ <g id="Search" transform="translate(2.000000, 2.000000)" fill="currentColor" fill-rule="nonzero">
6
5
  <ellipse id="Ellipse_746" cx="8.59921927" cy="8.65324385" rx="8.59921927" ry="8.65324385"></ellipse>
7
- <path d="M18.674623,19.9552573 C18.3405833,19.9444414 18.0229443,19.8069986 17.7853553,19.5704698 L15.7489321,17.1901566 C15.3123366,16.7908936 15.2766365,16.1123232 15.668898,15.6689038 L15.668898,15.6689038 C15.8525005,15.4831065 16.1021409,15.3786387 16.3625268,15.3786387 C16.6229128,15.3786387 16.8725531,15.4831065 17.0561557,15.6689038 L19.6172468,17.7181208 C19.9861582,18.0957076 20.0999999,18.656254 19.9078887,19.1492153 C19.7157774,19.6421767 19.2536179,19.9754211 18.7279791,20 L18.674623,19.9552573 Z" id="Path_34202" opacity="0.400000006"></path>
6
+ <path fill="currentColor" d="M18.674623,19.9552573 C18.3405833,19.9444414 18.0229443,19.8069986 17.7853553,19.5704698 L15.7489321,17.1901566 C15.3123366,16.7908936 15.2766365,16.1123232 15.668898,15.6689038 L15.668898,15.6689038 C15.8525005,15.4831065 16.1021409,15.3786387 16.3625268,15.3786387 C16.6229128,15.3786387 16.8725531,15.4831065 17.0561557,15.6689038 L19.6172468,17.7181208 C19.9861582,18.0957076 20.0999999,18.656254 19.9078887,19.1492153 C19.7157774,19.6421767 19.2536179,19.9754211 18.7279791,20 L18.674623,19.9552573 Z" id="Path_34202" opacity="0.400000006"></path>
8
7
  </g>
9
8
  </g>
10
- </svg>
9
+ </svg>
@@ -1 +1 @@
1
- @import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap");.flash{margin-top:1rem;padding:1rem;border-radius:5px}.flash-error{color:#fff;background:var(--red-500)}.flash-notice{color:#fff;background:var(--green-400)}#wrapper{height:100vh;width:100%}#speedscope-iframe{width:100%;height:100%;border:none}.header{margin:0;padding:1.5rem 0;display:flex;justify-content:center;box-shadow:0 0 20px 0 rgba(0,0,0,.2);background:var(--primary)}.header a{color:#fff;text-decoration:none}.nav{width:var(--main-width);justify-content:space-between}.home,.nav{display:flex}.home{align-items:center;text-decoration:none}.home-logo{width:64px;height:64px}.home-title{padding:0 0 0 1rem;margin:0}.header-links{margin:0;padding:0;list-style:none;display:flex;align-items:center;font-weight:700}main{width:100%;display:flex;justify-content:center}.main-section{width:var(--main-width)}.placeholder{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:450px}.placeholder-image{height:30%;width:30%;-webkit-filter:grayscale(1) brightness(2.5)}.placeholder-text{text-align:center;color:var(--grey-400)}.profiled-requests-actions{display:flex;padding:1rem 0;justify-content:space-between;align-items:center}.search-field{padding:.5rem;border-radius:.25em;border:1px solid var(--grey-400);color:var(--grey-700)}.clear-action button{background:var(--red-500);color:#fff}.table{width:100%;border-collapse:collapse;border-radius:5px;border:1px hidden var(--border-color);box-shadow:0 0 0 1px var(--border-color)}.table thead tr{color:var(--grey-400)}.table thead th{font-weight:400}.table tr{border:1px solid var(--border-color);color:var(--grey-700);cursor:pointer}.table tr:nth-child(2n){background:var(--grey-50)}.table tbody tr:hover{background:var(--grey-100)}.table td,.table th{padding:.5rem 1rem}.request-path{max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.request-buttons{z-index:1;text-align:right}.request-buttons a{text-decoration:none;padding:0 .25rem;color:var(--grey-700)}.request-buttons a:active,.request-buttons a:focus-visible,.request-buttons a:hover{color:var(--blue-500)}.request-buttons a.link-disabled{cursor:default;pointer-events:none;text-decoration:none;color:var(--grey-200)}.request-details-data{display:flex;margin:0;padding:0}.data-item{display:flex;flex-direction:column;align-items:flex-start;list-style:none;margin-right:3rem;padding:0}.data-item small{color:var(--grey-400)}.data-item span{margin:.25rem 0}[class*=request-method-get],[class*=request-status-2]{color:#fff;background:var(--green-400)!important}[class*=request-method-patch],[class*=request-method-put],[class*=request-status-4]{color:#fff;background:var(--yellow-400)!important}[class*=request-method-delete],[class*=request-status-5]{color:#fff;background:var(--red-500)!important}.request-details-actions{margin:0;padding:2em 0;display:flex;align-items:center;justify-content:space-between}.flamegraph-button button{background:var(--grey-200)}.trace-list{margin:0;padding:0}.trace{list-style:none;display:flex;padding:.25em 0;align-items:center;justify-content:flex-start}.trace:nth-child(odd){background:var(--grey-100)}.trace .trace-bar{position:relative;margin:0;height:16px;padding:0;cursor:pointer;background:linear-gradient(to top right,var(--grey-500),var(--grey-400))}.instantiation-trace .trace-bar{background:linear-gradient(to top right,var(--green-400),var(--green-300))}.sequel-trace .trace-bar{background:linear-gradient(to top right,var(--green-500),var(--green-400))}.controller-trace .trace-bar{background:linear-gradient(to top right,var(--yellow-500),var(--yellow-400))}.render-partial-trace .trace-bar,.render-template-trace .trace-bar{background:linear-gradient(to top right,var(--blue-500),var(--blue-400))}.trace-name{margin:0;box-sizing:border-box;padding:0 .5em;overflow:hidden;font-size:14px;text-align:right;text-overflow:ellipsis;color:var(--grey-400)}.trace-payload{margin:0}.sequel-trace-query{padding:1em;background:var(--grey-100)}.sequel-trace-binds,.sequel-trace-query{overflow:auto;max-height:100px;white-space:pre-wrap}.sequel-trace-binds{margin:0 0 1em;padding:.5em 1em;font-size:12px;background:var(--grey-50)}.trace-table{margin-top:1em;width:100%;border-collapse:collapse;border:1px hidden var(--border-color)}.pagy-nav{display:flex;align-items:center;justify-content:center;padding:1em 0}.pagy-nav>.page.active,.pagy-nav>.page.disabled,.pagy-nav>.page>a{padding:.5rem 1rem;color:var(--grey-900);background:#fff;border:1px solid var(--border-color);border-right:none;text-decoration:none;cursor:pointer}.pagy-nav>.page.active:hover,.pagy-nav>.page.disabled:hover,.pagy-nav>.page>a:hover{background:var(--grey-100)}.pagy-nav>.page.prev.disabled,.pagy-nav>.page.prev a{border-radius:5px 0 0 5px}.pagy-nav>.page.next.disabled,.pagy-nav>.page.next a{border-radius:0 5px 5px 0;border-right:1px solid var(--border-color)}.pagy-nav>.page.active{cursor:default;border-color:var(--red-500);color:#fff}.pagy-nav>.page.active,.pagy-nav>.page.active:hover{background:var(--red-500)}.pagy-nav>.page.disabled{cursor:default;color:var(--grey-500)}.pagy-nav>.page.disabled:hover{background:#fff}@font-face{font-family:Open Sans;font-weight:400;font-style:normal}@font-face{font-family:Open Sans;font-weight:600;font-style:normal}@font-face{font-family:Open Sans;font-weight:700;font-style:normal}html{--grey-50:#f9fafb;--grey-100:#f3f4f6;--grey-200:#e5e7eb;--grey-400:#9ca3af;--grey-500:#6b7280;--grey-700:#374151;--grey-900:#111827;--red-400:#f87171;--red-500:#ef4444;--red-600:#dc2626;--yellow-400:#fbbf24;--yellow-500:#f59e0b;--green-300:#6ee7b7;--green-400:#34d399;--green-500:#10b981;--blue-400:#60a5fa;--blue-500:#3b82f6;--main-width:1056px;--primary:var(--red-600);--border-color:var(--grey-200);--text-color:var(--grey-900);font-family:Open Sans,monospace}body,html{width:100%;height:100%;margin:0;padding:0}body{color:var(--text-color)}h1{padding:2rem 0 1rem}button{border:none;border-radius:.25rem;padding:.5em;text-align:center;text-decoration:none;display:inline-block;font-size:1rem;cursor:pointer}button:hover{box-shadow:0 .25rem .25rem 0 var(--grey-50)}.text-left{text-align:left}.text-right{text-align:right}.pill{margin:.2rem 0;padding:.1rem .4rem;border-radius:5px;font-size:.9rem;font-weight:600;letter-spacing:.1rem;background:var(--grey-200)}.popover{display:flex;flex-direction:column;width:600px;padding:1em;color:#000}.popover-header{display:flex;padding-bottom:1em;flex-direction:row;justify-content:space-between;align-items:center}.popover-description{margin:0;padding:0}.popover-close{background:transparent;padding:0;font-weight:700;font-size:20px;color:var(--grey-400)}.popover-body{padding:1em 0}.popover-footer{border-top:1px solid var(--grey-50)}.tippy-box[data-theme~=rmp]{background:#fff;box-shadow:8px 0 30px 4px rgba(0,0,0,.2),8px 4px 10px 0 rgba(0,0,0,.05);border-radius:3px;transition:all .2s cubic-bezier(.19,1,.22,1)}.tippy-box[data-theme~=rmp][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}
1
+ @import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap");.flash{border-radius:5px;margin-top:1rem;padding:1rem}.flash-error{background:var(--red-500);color:#fff}.flash-notice{background:var(--green-400);color:#fff}#wrapper{height:100vh;width:100%}#speedscope-iframe{border:none;height:100%;width:100%}.table{border:1px hidden var(--border-color);border-collapse:collapse;border-radius:5px;box-shadow:0 0 0 1px var(--border-color);table-layout:fixed;width:100%}.table td,.table th{padding:.5rem 1rem}.table thead tr{color:var(--grey-500)}.table tr:nth-child(2n){background:var(--grey-50)}.table thead th{font-weight:400}.table-filter-icon{margin-left:.5rem;width:14px}.table tbody tr:not(.no-row){border:1px solid var(--border-color);color:var(--grey-700);cursor:pointer}.table tbody tr:not(.no-row):hover{background:var(--grey-100)}.request-checkbox{height:1rem;width:1rem;z-index:1}.request-path{max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.search-field{border:1px solid var(--grey-400);border-radius:5px;box-sizing:border-box;padding:.5rem}.profiled-requests-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between}.clear-action button{background:var(--red-500);color:#fff;font-weight:600}.clear-action button:hover{background:var(--red-600)}.profiled-request-details{align-items:center;display:flex;justify-content:space-between;padding-bottom:2rem}.data-item,.request-details-data{display:flex}.data-item{align-items:flex-start;flex-direction:column;list-style:none;margin-right:3rem;padding:0}.data-item small{color:var(--grey-400)}.data-item span{margin:.25rem 0}[class*=request-method-get],[class*=request-status-2]{background:var(--green-400)!important;color:#fff}[class*=request-method-patch],[class*=request-method-put],[class*=request-status-4]{background:var(--yellow-400)!important;color:#fff}[class*=request-method-delete],[class*=request-status-5]{background:var(--red-500)!important;color:#fff}.trace-list{border:1px solid var(--grey-200);border-radius:5px;padding:1rem}.trace-details-table{border:1px hidden var(--border-color);border-collapse:collapse;margin-top:1em;width:100%}.trace-details-table tr th{font-weight:var(--fw-semibold)}.trace-list-header{padding-bottom:1rem}.trace-list-filters,.trace-list-header{align-items:center;display:flex;justify-content:space-between}.trace-list-filters{color:var(--grey-500);width:60%}.button,button{border:none;border-radius:5px;cursor:pointer;display:inline-block;font-size:1rem;padding:.5em;text-align:center;text-decoration:none}.button:disabled,button:disabled{background:var(--grey-200);cursor:not-allowed}.btn-red{background:var(--red-500);color:#fff;font-weight:600;outline:none}.btn-red:hover{background:var(--red-600)}.btn-grey{background:var(--grey-200)}.btn-grey:hover{background:var(--grey-100)}.btn-white{background:#fff;border:1px solid var(--grey-200)}.btn-white:hover{background:var(--grey-100)}button:hover{box-shadow:0 .25rem .25rem 0 var(--grey-50)}button.none{background:none;border:none;outline:none;padding:0}button.none:hover{box-shadow:none}input[type=submit]{border:none;border-radius:5px;cursor:pointer;display:inline-block;font-size:1rem;padding:.5em;text-align:center;text-decoration:none}.header{background:var(--primary);box-shadow:0 0 20px 0 rgba(0,0,0,.2);display:flex;justify-content:center;margin:0;padding:1.5rem 0}.header a{color:#fff;text-decoration:none}.nav{justify-content:space-between;width:var(--main-width)}.home,.nav{display:flex}.home{align-items:center;text-decoration:none}.home-logo{height:64px;width:64px}.home-title{margin:0;padding:0 0 0 1rem}.header-links{font-weight:700;list-style:none;margin:0;padding:0}.header-links,.pagy-nav{align-items:center;display:flex}.pagy-nav{justify-content:center;padding:1em 0}.pagy-nav>.page.active,.pagy-nav>.page.disabled,.pagy-nav>.page>a{background:#fff;border:1px solid var(--border-color);border-right:none;color:var(--grey-900);cursor:pointer;padding:.5rem 1rem;text-decoration:none}.pagy-nav>.page.prev.disabled,.pagy-nav>.page.prev a{border-radius:5px 0 0 5px}.pagy-nav>.page.next.disabled,.pagy-nav>.page.next a{border-radius:0 5px 5px 0;border-right:1px solid var(--border-color)}.pagy-nav>.page.active{border-color:var(--red-500);color:#fff;cursor:default}.pagy-nav>.page.active,.pagy-nav>.page.active:hover{background:var(--red-500)}.pagy-nav>.page.disabled{color:var(--grey-500);cursor:default}.pagy-nav>.page.disabled:hover{background:#fff}.pagy-nav>.page.active:hover,.pagy-nav>.page.disabled:hover,.pagy-nav>.page>a:hover{background:var(--grey-100)}.page-header{padding:2.5rem 0}.page-header h1{font-size:28px}.dropdown-body{padding:.33rem .5rem}.dropdown-search-field{border:1px solid var(--grey-400);border-radius:5px;color:var(--grey-700);padding:.5rem}.dropdown-toggle{align-items:center;color:inherit;display:flex}.dropdown-toggle:hover{color:var(--grey-900)}.dropdown-container{background:#fff;border:1px solid var(--grey-200);border-radius:5px;box-shadow:0 8px 30px rgba(0,0,0,.12);box-sizing:border-box;color:var(--grey-400);cursor:default;margin-top:.3em;min-width:240px;overflow:hidden;position:absolute;z-index:1}.dropdown-container,.dropdown-search,.dropdown-search button{display:flex;flex-direction:column}.dropdown-entry{display:flex;padding:.33rem 1rem;text-decoration:none}.dropdown-entry:hover{background:var(--grey-100);color:var(--grey-900)}.dropdown-entry input{margin-right:.5em}.dropdown-header{align-items:center;background:var(--grey-100);border-bottom:1px solid var(--grey-200);display:flex;font-size:.833rem;justify-content:space-between;padding:.5rem 1rem;text-align:left}.dropdown-header button{background:none;border:none;color:var(--grey-500);font-size:.833rem;outline:none;padding:0;text-decoration:underline}.dropdown-header button:hover{box-shadow:none;color:var(--grey-900)}.dropdown-footer{background:var(--red-500);border:none;border-radius:0;color:#fff;font-weight:600;outline:none;padding:.5rem;width:100%}.dropdown-footer:hover{background:var(--red-600)}.placeholder{align-items:center;display:flex;flex-direction:column;justify-content:center;padding-bottom:2rem;width:100%}.placeholder-image{-webkit-filter:grayscale(1) brightness(2.5);height:30%;width:30%}.placeholder-text{color:var(--grey-400);padding:1rem 0;text-align:center}.placeholder-text h2{padding-bottom:1rem}.placeholder-link,.placeholder-link:visited{color:var(--grey-400)}.placeholder-link:hover{color:var(--grey-900)}.trace{align-items:center;display:flex;justify-content:flex-start;list-style:none;padding:.25em 0}.trace:nth-child(odd){background:var(--grey-100)}.trace .trace-bar{background:linear-gradient(to top right,var(--grey-500),var(--grey-400));cursor:pointer;height:16px;margin:0;padding:0;position:relative}.instantiation-trace .trace-bar{background:linear-gradient(to top right,var(--green-400),var(--green-300))}.sequel-trace .trace-bar{background:linear-gradient(to top right,var(--green-500),var(--green-400))}.controller-trace .trace-bar{background:linear-gradient(to top right,var(--yellow-500),var(--yellow-400))}.render-partial-trace .trace-bar,.render-template-trace .trace-bar{background:linear-gradient(to top right,var(--blue-500),var(--blue-400))}.trace-name{box-sizing:border-box;color:var(--grey-400);font-size:14px;margin:0;overflow:hidden;padding:0 .5em;text-align:right;text-overflow:ellipsis}.trace-payload{margin:0}.sequel-trace-query{background:var(--grey-100);padding:1em}.sequel-trace-binds,.sequel-trace-query{max-height:100px;overflow:auto;white-space:pre-wrap}.sequel-trace-binds{background:var(--grey-50);font-size:12px;margin:0 0 1em;padding:.5em 1em}.backtrace{align-items:center;background:var(--grey-100);display:flex;flex-direction:row;justify-content:space-between;padding:.5em}.backtrace button{background:none;color:var(--grey-500);height:20px;margin:0;overflow:auto;padding:0}.backtrace button svg{height:20px;width:20px}@font-face{font-family:Open Sans;font-style:normal;font-weight:400}@font-face{font-family:Open Sans;font-style:normal;font-weight:600}@font-face{font-family:Open Sans;font-style:normal;font-weight:700}html{--grey-50:#f9fafb;--grey-100:#f3f4f6;--grey-200:#e5e7eb;--grey-400:#9ca3af;--grey-500:#6b7280;--grey-700:#374151;--grey-900:#111827;--red-400:#f87171;--red-500:#ef4444;--red-600:#dc2626;--yellow-400:#fbbf24;--yellow-500:#fbbf24;--yellow-600:#d97706;--yellow-700:#b45309;--green-300:#6ee7b7;--green-400:#34d399;--green-500:#10b981;--blue-400:#60a5fa;--blue-500:#3b82f6;--main-width:1056px;--primary:var(--red-600);--border-color:var(--grey-200);--text-color:var(--grey-900);--fw-normal:400;--fw-semibold:600;--fw-bold:700;font-family:Open Sans,monospace;height:100%;width:100%}*,body,html{margin:0;padding:0}body{color:var(--text-color);height:100%}body,main{width:100%}main{display:flex;justify-content:center}.main-section{width:var(--main-width)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.hidden{display:none}.flex-row{display:flex;flex-direction:row}.flex-column{display:flex;flex-direction:column}.pill{background:var(--grey-200);border-radius:5px;font-size:.9rem;font-weight:600;letter-spacing:.1rem;margin:.2rem 0;padding:.1rem .4rem}.popover{color:#000;display:flex;flex-direction:column;padding:1em;width:600px}.popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding-bottom:1em}.popover-description{margin:0;padding:0}.popover-close{background:transparent;color:var(--grey-400);font-size:20px;font-weight:700;padding:0}.popover-body{padding:1em 0}.popover-footer{border-top:1px solid var(--grey-50)}.tippy-box[data-theme~=rmp]{background:#fff;border-radius:5px;box-shadow:8px 0 30px 4px rgba(0,0,0,.2),8px 4px 10px 0 rgba(0,0,0,.05);transition:all .2s cubic-bezier(.19,1,.22,1)}.tippy-box[data-theme~=rmp][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=rmp][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}