rails_mini_profiler 0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +302 -0
  4. data/app/assets/config/rails_mini_profiler_manifest.js +1 -0
  5. data/app/assets/javascripts/rails_mini_profiler.js +15 -0
  6. data/app/assets/stylesheets/rails_mini_profiler/application.css +16 -0
  7. data/app/controllers/rails_mini_profiler/application_controller.rb +33 -0
  8. data/app/controllers/rails_mini_profiler/flamegraphs_controller.rb +23 -0
  9. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +68 -0
  10. data/app/helpers/rails_mini_profiler/application_helper.rb +23 -0
  11. data/app/helpers/rails_mini_profiler/profiled_requests_helper.rb +16 -0
  12. data/app/javascript/images/bookmark.svg +10 -0
  13. data/app/javascript/images/chart.svg +12 -0
  14. data/app/javascript/images/check.svg +3 -0
  15. data/app/javascript/images/chevron.svg +3 -0
  16. data/app/javascript/images/delete.svg +9 -0
  17. data/app/javascript/images/filter.svg +1 -0
  18. data/app/javascript/images/graph.svg +11 -0
  19. data/app/javascript/images/logo.svg +18 -0
  20. data/app/javascript/images/logo_variant.svg +32 -0
  21. data/app/javascript/images/search.svg +9 -0
  22. data/app/javascript/images/setting.svg +10 -0
  23. data/app/javascript/images/show.svg +11 -0
  24. data/app/javascript/js/checklist_controller.js +48 -0
  25. data/app/javascript/js/enable_controller.js +24 -0
  26. data/app/javascript/js/filter_controller.js +44 -0
  27. data/app/javascript/js/search_controller.js +18 -0
  28. data/app/javascript/js/select_controller.js +47 -0
  29. data/app/javascript/packs/rails-mini-profiler.js +88 -0
  30. data/app/javascript/stylesheets/components/page_header/page_header.scss +3 -0
  31. data/app/javascript/stylesheets/components/pagination.scss +55 -0
  32. data/app/javascript/stylesheets/components/profiled_request_table/placeholder.scss +33 -0
  33. data/app/javascript/stylesheets/components/profiled_request_table/profiled_request_table.scss +179 -0
  34. data/app/javascript/stylesheets/flamegraph.scss +10 -0
  35. data/app/javascript/stylesheets/flashes.scss +15 -0
  36. data/app/javascript/stylesheets/navbar.scss +44 -0
  37. data/app/javascript/stylesheets/profiled_requests.scss +89 -0
  38. data/app/javascript/stylesheets/rails-mini-profiler.scss +205 -0
  39. data/app/javascript/stylesheets/traces.scss +82 -0
  40. data/app/models/rails_mini_profiler/application_record.rb +17 -0
  41. data/app/models/rails_mini_profiler/controller_trace.rb +37 -0
  42. data/app/models/rails_mini_profiler/flamegraph.rb +37 -0
  43. data/app/models/rails_mini_profiler/instantiation_trace.rb +37 -0
  44. data/app/models/rails_mini_profiler/profiled_request.rb +65 -0
  45. data/app/models/rails_mini_profiler/render_partial_trace.rb +37 -0
  46. data/app/models/rails_mini_profiler/render_template_trace.rb +37 -0
  47. data/app/models/rails_mini_profiler/rmp_trace.rb +35 -0
  48. data/app/models/rails_mini_profiler/sequel_trace.rb +37 -0
  49. data/app/models/rails_mini_profiler/trace.rb +46 -0
  50. data/app/presenters/rails_mini_profiler/base_presenter.rb +25 -0
  51. data/app/presenters/rails_mini_profiler/controller_trace_presenter.rb +18 -0
  52. data/app/presenters/rails_mini_profiler/instantiation_trace_presenter.rb +14 -0
  53. data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +38 -0
  54. data/app/presenters/rails_mini_profiler/render_partial_trace_presenter.rb +11 -0
  55. data/app/presenters/rails_mini_profiler/render_template_trace_presenter.rb +15 -0
  56. data/app/presenters/rails_mini_profiler/rmp_trace_presenter.rb +9 -0
  57. data/app/presenters/rails_mini_profiler/sequel_trace_presenter.rb +69 -0
  58. data/app/presenters/rails_mini_profiler/trace_presenter.rb +61 -0
  59. data/app/search/rails_mini_profiler/base_search.rb +67 -0
  60. data/app/search/rails_mini_profiler/profiled_request_search.rb +34 -0
  61. data/app/views/layouts/rails_mini_profiler/application.html.erb +15 -0
  62. data/app/views/layouts/rails_mini_profiler/flamegraph.html.erb +11 -0
  63. data/app/views/models/_flamegraph.json.jb +3 -0
  64. data/app/views/models/_profiled_request.jb +3 -0
  65. data/app/views/models/_trace.jb +3 -0
  66. data/app/views/rails_mini_profiler/badge.html.erb +37 -0
  67. data/app/views/rails_mini_profiler/flamegraphs/show.html.erb +13 -0
  68. data/app/views/rails_mini_profiler/flamegraphs/show.json.jb +3 -0
  69. data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +9 -0
  70. data/app/views/rails_mini_profiler/profiled_requests/index.json.jb +3 -0
  71. data/app/views/rails_mini_profiler/profiled_requests/shared/_trace.html.erb +40 -0
  72. data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +20 -0
  73. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_placeholder.erb +12 -0
  74. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table.erb +14 -0
  75. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +125 -0
  76. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_row.erb +21 -0
  77. data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +40 -0
  78. data/app/views/rails_mini_profiler/profiled_requests/show.json.jb +5 -0
  79. data/app/views/rails_mini_profiler/shared/_flashes.html.erb +8 -0
  80. data/app/views/rails_mini_profiler/shared/_head.erb +13 -0
  81. data/app/views/rails_mini_profiler/shared/_navbar.html.erb +15 -0
  82. data/config/routes.rb +11 -0
  83. data/db/migrate/20210621185018_create_rmp.rb +46 -0
  84. data/lib/generators/rails_mini_profiler/USAGE +2 -0
  85. data/lib/generators/rails_mini_profiler/install_generator.rb +40 -0
  86. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.js.erb +13 -0
  87. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +29 -0
  88. data/lib/rails_mini_profiler/badge.rb +84 -0
  89. data/lib/rails_mini_profiler/configuration/storage.rb +47 -0
  90. data/lib/rails_mini_profiler/configuration/user_interface.rb +48 -0
  91. data/lib/rails_mini_profiler/configuration.rb +65 -0
  92. data/lib/rails_mini_profiler/engine.rb +34 -0
  93. data/lib/rails_mini_profiler/flamegraph_guard.rb +47 -0
  94. data/lib/rails_mini_profiler/guard.rb +57 -0
  95. data/lib/rails_mini_profiler/logger.rb +25 -0
  96. data/lib/rails_mini_profiler/middleware.rb +74 -0
  97. data/lib/rails_mini_profiler/models/base_model.rb +23 -0
  98. data/lib/rails_mini_profiler/redirect.rb +33 -0
  99. data/lib/rails_mini_profiler/request_context.rb +86 -0
  100. data/lib/rails_mini_profiler/request_wrapper.rb +69 -0
  101. data/lib/rails_mini_profiler/response_wrapper.rb +32 -0
  102. data/lib/rails_mini_profiler/tracing/controller_tracer.rb +15 -0
  103. data/lib/rails_mini_profiler/tracing/null_trace.rb +7 -0
  104. data/lib/rails_mini_profiler/tracing/sequel_tracer.rb +37 -0
  105. data/lib/rails_mini_profiler/tracing/sequel_tracker.rb +37 -0
  106. data/lib/rails_mini_profiler/tracing/subscriptions.rb +34 -0
  107. data/lib/rails_mini_profiler/tracing/trace.rb +45 -0
  108. data/lib/rails_mini_profiler/tracing/trace_factory.rb +37 -0
  109. data/lib/rails_mini_profiler/tracing/tracer.rb +31 -0
  110. data/lib/rails_mini_profiler/tracing/view_tracer.rb +12 -0
  111. data/lib/rails_mini_profiler/tracing.rb +11 -0
  112. data/lib/rails_mini_profiler/user.rb +40 -0
  113. data/lib/rails_mini_profiler/version.rb +5 -0
  114. data/lib/rails_mini_profiler.rb +79 -0
  115. data/lib/tasks/rails_mini_profiler_tasks.rake +8 -0
  116. data/public/rails_mini_profiler/speedscope/LICENSE +21 -0
  117. data/public/rails_mini_profiler/speedscope/demangle-cpp.1768f4cc.js +4 -0
  118. data/public/rails_mini_profiler/speedscope/demangle-cpp.1768f4cc.js.map +1 -0
  119. data/public/rails_mini_profiler/speedscope/favicon-16x16.f74b3187.png +0 -0
  120. data/public/rails_mini_profiler/speedscope/favicon-32x32.bc503437.png +0 -0
  121. data/public/rails_mini_profiler/speedscope/file-format-schema.json +324 -0
  122. data/public/rails_mini_profiler/speedscope/import.e3a73ef4.js +117 -0
  123. data/public/rails_mini_profiler/speedscope/import.e3a73ef4.js.map +1 -0
  124. data/public/rails_mini_profiler/speedscope/index.html +2 -0
  125. data/public/rails_mini_profiler/speedscope/release.txt +3 -0
  126. data/public/rails_mini_profiler/speedscope/reset.8c46b7a1.css +2 -0
  127. data/public/rails_mini_profiler/speedscope/reset.8c46b7a1.css.map +1 -0
  128. data/public/rails_mini_profiler/speedscope/source-map.438fa06b.js +24 -0
  129. data/public/rails_mini_profiler/speedscope/source-map.438fa06b.js.map +1 -0
  130. data/public/rails_mini_profiler/speedscope/speedscope.026f36b0.js +200 -0
  131. data/public/rails_mini_profiler/speedscope/speedscope.026f36b0.js.map +1 -0
  132. data/vendor/assets/images/bookmark.svg +10 -0
  133. data/vendor/assets/images/chart.svg +12 -0
  134. data/vendor/assets/images/check.svg +3 -0
  135. data/vendor/assets/images/chevron.svg +3 -0
  136. data/vendor/assets/images/delete.svg +9 -0
  137. data/vendor/assets/images/filter.svg +1 -0
  138. data/vendor/assets/images/graph.svg +11 -0
  139. data/vendor/assets/images/logo.svg +18 -0
  140. data/vendor/assets/images/logo_variant.svg +32 -0
  141. data/vendor/assets/images/search.svg +9 -0
  142. data/vendor/assets/images/setting.svg +10 -0
  143. data/vendor/assets/images/show.svg +11 -0
  144. data/vendor/assets/javascripts/rails-mini-profiler.css +1 -0
  145. data/vendor/assets/javascripts/rails-mini-profiler.js +1 -0
  146. metadata +248 -0
@@ -0,0 +1,13 @@
1
+ <div id=wrapper>
2
+ <iframe id=speedscope-iframe></iframe>
3
+ </div>
4
+ <script type="text/javascript">
5
+ const graph = <%= raw @flamegraph %>
6
+ const json = JSON.stringify(graph)
7
+ const blob = new Blob([json], { type: 'text/plain' })
8
+ const objUrl = encodeURIComponent(URL.createObjectURL(blob))
9
+ const iframe = document.getElementById('speedscope-iframe')
10
+ const baseUrl = window.location.origin;
11
+ const iframeUrl = baseUrl + '/rails_mini_profiler/speedscope/index.html#profileURL=' + objUrl + '&title=' + 'Flamegraph';
12
+ iframe.setAttribute('src', iframeUrl)
13
+ </script>
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ render 'models/flamegraph', flamegraph: @flamegraph
@@ -0,0 +1,9 @@
1
+
2
+ <div
3
+ data-controller="filters selectable"
4
+ data-action="search-controller:submit@window->filters#apply">
5
+ <%= render "rails_mini_profiler/profiled_requests/shared/header/header" %>
6
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/table" %>
7
+ </div>
8
+ <%== pagy_nav(@pagy) if @pagy.pages > 1 %>
9
+ <br>
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ render partial: 'models/profiled_request', collection: @profiled_requests, as: :profiled_request
@@ -0,0 +1,40 @@
1
+ <li class="trace <%= trace.type %>">
2
+ <span class="trace-name " style="width: calc(calc(<%= trace.from_start_percent %>% * .9) + 10%)"><%= trace.label %></span>
3
+ <div class="trace-bar" style="width: max(calc(<%= trace.duration_percent %>% * .9), 5px)">
4
+ <div class="popover">
5
+ <section class="popover-header">
6
+ <h1 class="popover-description"><%= trace.description %></h1>
7
+ <button class="popover-close">x</button>
8
+ </section>
9
+ <section class="popover-body">
10
+ <%= trace.payload %>
11
+ <table class="trace-table">
12
+ <thead>
13
+ <tr>
14
+ <th class="text-left"></th>
15
+ <th class="text-right">Response Time</th>
16
+ <th class="text-right">Allocations</th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ <tr>
21
+ <td>Total</td>
22
+ <td class="text-right"><%= trace.duration %>ms</td>
23
+ <td class="text-right"><%= trace.allocations %></td>
24
+ </tr>
25
+ <tr>
26
+ <td>Relative</td>
27
+ <td class="text-right"><%= trace.duration_percent %>%</td>
28
+ <td class="text-right"><%= trace.allocations_percent %>%</td>
29
+ </tr>
30
+ </table>
31
+ </section>
32
+
33
+ <% if trace.backtrace %>
34
+ <section class="popover-footer">
35
+ <pre><%= trace.backtrace %></pre>
36
+ </section>
37
+ <% end %>
38
+ </div>
39
+ </div>
40
+ </li>
@@ -0,0 +1,20 @@
1
+ <div class="page-header profiled-requests-header">
2
+ <div class="">
3
+ <h1>Profiled Requests</h1>
4
+ </div>
5
+ <div>
6
+ <%= button_tag('Delete Selected',
7
+ disabled: params[:id].blank?,
8
+ data: {
9
+ controller: 'enable',
10
+ 'enable-target': 'enable',
11
+ action: 'rmp:select:change@window->enable#change click->filters#post'
12
+ }) -%>
13
+ <%= link_to(destroy_all_profiled_requests_url,
14
+ method: :delete,
15
+ class: 'clear-action',
16
+ data: { confirm: "This will delete all requests. Are you sure?" }) do %>
17
+ <%= button_tag('Delete All') %>
18
+ <% end %>
19
+ </div>
20
+ </div>
@@ -0,0 +1,12 @@
1
+ <tr class="no-row">
2
+ <td colspan="100%">
3
+ <div class="placeholder">
4
+ <%= inline_svg('logo_variant.svg', class: 'placeholder-image') %>
5
+ <div class="placeholder-text">
6
+ <h2>No Requests found!</h2>
7
+ <p>Send some requests to your app or modify your filters</p>
8
+ </div>
9
+ <%= link_to('Clear Filters', profiled_requests_path, class: 'placeholder-link') %>
10
+ </div>
11
+ </td>
12
+ </tr>
@@ -0,0 +1,14 @@
1
+ <table
2
+ id="profiled-requests-table"
3
+ class="table">
4
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/table_head" %>
5
+ <tbody>
6
+ <% if @profiled_requests.empty? %>
7
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/placeholder" %>
8
+ <% else %>
9
+ <% @profiled_requests.each do |profiled_request| %>
10
+ <%= render "rails_mini_profiler/profiled_requests/shared/table/table_row", profiled_request: profiled_request %>
11
+ <% end %>
12
+ <% end %>
13
+ </tbody>
14
+ </table>
@@ -0,0 +1,125 @@
1
+ <thead>
2
+ <tr>
3
+ <th style="width: 20px;" class="text-left">
4
+ <%= label_tag nil do %>
5
+ <%= check_box_tag 'selected[]', nil,
6
+ params.fetch(:selected, []).size == @pagy.items,
7
+ class: "request-checkbox",
8
+ data: {
9
+ action: 'click->selectable#selectAll',
10
+ 'selectable-target': 'all'
11
+ }
12
+ %>
13
+ <% end %>
14
+ </th>
15
+ <th style="width: 25%;" class="text-left" data-controller="dropdown">
16
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
17
+ Path <%= inline_svg('search.svg', class: 'table-filter-icon') %> </button>
18
+ <div data-controller="search" data-dropdown-target="menu" class="dropdown-container hidden">
19
+ <div class="dropdown-body">
20
+ <%= form_with url: profiled_requests_url, method: :get do |form| %>
21
+ <%= form.search_field :path,
22
+ value: params[:path],
23
+ placeholder: 'Search Path',
24
+ class: 'dropdown-search-field',
25
+ data: { 'filters-target': 'filter' } %>
26
+ <%= form.submit 'Search', class: 'dropdown-search-button', data: { action: 'click->search#submit' } -%>
27
+ <% end %>
28
+ </div>
29
+ </div>
30
+ </th>
31
+ <th style="width: 10%;" class="" data-controller="dropdown">
32
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
33
+ Method <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
34
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
35
+ <div class="dropdown-header">
36
+ Select Method...
37
+ <button class="clear-filters" data-action="checklist#checkNone">
38
+ Clear filter
39
+ </button>
40
+ </div>
41
+ <% %w[get put post delete].map(&:upcase).each do |method| %>
42
+ <%= label_tag nil, class: "dropdown-entry" do %>
43
+ <%= check_box_tag 'method[]', method, params.fetch(:method, []).include?(method),
44
+ class: "",
45
+ data: { 'filters-target': "filter" } %>
46
+ <%= method %>
47
+ <% end %>
48
+ <% end %>
49
+ <button class="dropdown-footer" data-action="filters#apply">
50
+ Apply
51
+ </button>
52
+ </div>
53
+ </th>
54
+ <th style="width: 10%;" class="" data-controller="dropdown">
55
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
56
+ Status <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
57
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
58
+ <div class="dropdown-header">
59
+ Select Status...
60
+ <button class="clear-filters" data-action="checklist#checkNone filters#apply">
61
+ Clear filter
62
+ </button>
63
+ </div>
64
+ <% %w[200 300 400 500].each do |status| %>
65
+ <%= label_tag nil, class: "dropdown-entry" do %>
66
+ <%= check_box_tag 'status[]', status, params.fetch(:status, []).include?(status),
67
+ class: "",
68
+ data: { 'filters-target': "filter" } %>
69
+ <%= status %>
70
+ <% end %>
71
+ <% end %>
72
+ <button class="dropdown-footer" data-action="filters#apply">
73
+ Apply
74
+ </button>
75
+ </div>
76
+ </th>
77
+ <th style="width: 15%" class="" data-controller="dropdown">
78
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
79
+ Media Type <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
80
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
81
+ <div class="dropdown-header">
82
+ Select Media Type...
83
+ <button class="clear-filters" data-action="checklist#checkNone filters#apply">
84
+ Clear filter
85
+ </button>
86
+ </div>
87
+ <% %w[text/html application/json application/xml].each do |media_type| %>
88
+ <%= label_tag nil, class: "dropdown-entry" do %>
89
+ <%= check_box_tag 'media_type[]', media_type, params.fetch(:media_type, []).include?(media_type),
90
+ class: "",
91
+ data: { target: "filters.filter" } %>
92
+ <%= media_type %>
93
+ <% end %>
94
+ <% end %>
95
+ <button class="dropdown-footer" data-action="filters#apply">
96
+ Apply
97
+ </button>
98
+ </div>
99
+ </th>
100
+ <th style="width: 10%" class="text-left" data-controller="dropdown">
101
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" data-dropdown-target="button" class="dropdown-toggle none">
102
+ Duration <%= inline_svg('filter.svg', class: 'table-filter-icon') %> </button>
103
+ <div data-controller="checklist" data-dropdown-target="menu" class="dropdown-container hidden">
104
+ <div class="dropdown-header">
105
+ Select Duration...
106
+ <button class="clear-filters" data-action="checklist#checkNone filters#apply">
107
+ Clear filter
108
+ </button>
109
+ </div>
110
+ <% %w[>100ms >250ms].each do |duration| %>
111
+ <%= label_tag nil, class: "dropdown-entry" do %>
112
+ <%= radio_button_tag 'duration', duration, params.fetch(:duration, []).include?(duration),
113
+ class: "",
114
+ data: { target: "filters.filter" } %>
115
+ <%= duration %>
116
+ <% end %>
117
+ <% end %>
118
+ <button class="dropdown-footer" data-action="filters#apply">
119
+ Apply
120
+ </button>
121
+ </div>
122
+ </th>
123
+ <th style="width: 15%" class="text-left">Date</th>
124
+ </tr>
125
+ </thead>
@@ -0,0 +1,21 @@
1
+ <tr data-link="<%= profiled_request_path(profiled_request.id) %>">
2
+ <td class="">
3
+ <%= label_tag nil do %>
4
+ <%= check_box_tag 'id[]', profiled_request.id,
5
+ params.fetch(:selected, []).include?(profiled_request.id),
6
+ class: "request-checkbox",
7
+ data: {
8
+ 'selectable-target': 'selectable',
9
+ 'filters-target': 'filter',
10
+ action: 'click->selectable#onSelected'
11
+ },
12
+ onclick: "event.stopPropagation();" %>
13
+ <% end %>
14
+ </td>
15
+ <td class="request-path"><%= profiled_request.request_name %></td>
16
+ <td class="text-left"> <%= profiled_request.request_method %> </td>
17
+ <td class="text-left"> <%= profiled_request.response_status %> </td>
18
+ <td class="text-left"> <%= profiled_request.response_media_type %> </td>
19
+ <td class="text-left"><%= profiled_request.duration %> ms</td>
20
+ <td class="text-left"><%= profiled_request.created_at %></td>
21
+ </tr>
@@ -0,0 +1,40 @@
1
+ <section class="page-header">
2
+ <h1> <%= @profiled_request.request_path %> </h1>
3
+
4
+ <ul class="request-details-data">
5
+ <li class="data-item">
6
+ <small>Method</small>
7
+ <span class="pill request-method request-method-<%= @profiled_request.request_method %>"><%= @profiled_request.request_method %></span>
8
+ </li>
9
+ <li class="data-item">
10
+ <small>Status</small>
11
+ <span class="pill request-status request-status-<%= @profiled_request.response_status %>"><%= @profiled_request.response_status %></span>
12
+ </li>
13
+ <li class="data-item">
14
+ <small>Response Time</small>
15
+ <span><%= @profiled_request.duration %>ms</span>
16
+ </li>
17
+ <li class="data-item">
18
+ <small>Allocations</small>
19
+ <span><%= @profiled_request.allocations %></span>
20
+ </li>
21
+
22
+ </ul>
23
+
24
+ </section>
25
+
26
+ <section class="request-details-actions">
27
+ <%= form_with id: 'trace-form', url: profiled_request_url(@profiled_request.id), method: :get do |form| %>
28
+ <%= form.search_field :search, id: 'trace-search', placeholder: 'Search Traces...', class: 'search-field' %>
29
+ <% end %>
30
+ <%= @profiled_request.flamegraph_button %>
31
+ </section>
32
+
33
+ <section>
34
+ <h2>Traces</h2>
35
+ <ol class="trace-list">
36
+ <% @traces.each do |trace| %>
37
+ <%= render "rails_mini_profiler/profiled_requests/shared/trace", trace: trace %>
38
+ <% end %>
39
+ </ol>
40
+ </section>
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ request = render 'models/profiled_request', profiled_request: @profiled_request
4
+ request[:traces] = render partial: 'models/trace', collection: @traces, as: :trace
5
+ request
@@ -0,0 +1,8 @@
1
+ <% flash.each do |type, message| %>
2
+ <% if type == "alert" %>
3
+ <div class="flash flash-error"><%= message %></div>
4
+ <% end %>
5
+ <% if type == "notice" %>
6
+ <div class="flash flash-notice"><%= message %></div>
7
+ <% end %>
8
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <head>
2
+ <title>Rails Mini Profiler</title>
3
+ <%= csrf_meta_tags %>
4
+ <%= csp_meta_tag %>
5
+
6
+ <% if defined?(Webpacker::Engine) %>
7
+ <%= javascript_pack_tag "rails-mini-profiler" %>
8
+ <%= stylesheet_pack_tag 'rails-mini-profiler' %>
9
+ <% else %>
10
+ <%= javascript_include_tag "rails_mini_profiler" %>
11
+ <%= stylesheet_link_tag "rails_mini_profiler/application", media: "all" %>
12
+ <%end %>
13
+ </head>
@@ -0,0 +1,15 @@
1
+ <header class="header">
2
+ <nav class="nav">
3
+ <a class="home" href="<%= profiled_requests_path %>">
4
+ <%= inline_svg('logo.svg', class: 'home-logo') %>
5
+ <h1 class="home-title">Rails Mini Profiler </h1>
6
+ </a>
7
+ <ul class="header-links">
8
+ <li>
9
+ <a href="https://github.com/hschne/rails-mini-profiler#rails-mini-profiler">
10
+ Docs
11
+ </a>
12
+ </li>
13
+ </ul>
14
+ </nav>
15
+ </header>
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ RailsMiniProfiler::Engine.routes.draw do
4
+ root 'profiled_requests#index'
5
+ resources :profiled_requests, only: %i[index show destroy] do
6
+ collection do
7
+ delete 'destroy_all'
8
+ end
9
+ end
10
+ resources :flamegraphs, only: %i[show]
11
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateRmp < ActiveRecord::Migration[6.0]
4
+ def change
5
+ create_table :rmp_profiled_requests do |t|
6
+ t.string :user_id
7
+ t.bigint :start
8
+ t.bigint :finish
9
+ t.integer :duration
10
+ t.bigint :allocations
11
+ t.string :request_path
12
+ t.string :request_query_string
13
+ t.string :request_method
14
+ t.json :request_headers
15
+ t.text :request_body
16
+ t.integer :response_status
17
+ t.text :response_body
18
+ t.json :response_headers
19
+ t.string :response_media_type
20
+
21
+ t.timestamps
22
+
23
+ t.index :created_at
24
+ end
25
+
26
+ create_table :rmp_traces do |t|
27
+ t.belongs_to :rmp_profiled_request, null: false, foreign_key: true
28
+ t.string :name
29
+ t.bigint :start
30
+ t.bigint :finish
31
+ t.integer :duration
32
+ t.bigint :allocations
33
+ t.json :payload
34
+ t.json :backtrace
35
+
36
+ t.timestamps
37
+ end
38
+
39
+ create_table :rmp_flamegraphs do |t|
40
+ t.belongs_to :rmp_profiled_request, null: false, foreign_key: true
41
+ t.binary :data
42
+
43
+ t.timestamps
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,2 @@
1
+ description:
2
+ Enable rails-mini-profiler in development for your application.
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ # Generators for Rails Mini Profiler
5
+ module Generators
6
+ # A basic installation generator to help set up users apps
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path('templates', __dir__)
9
+
10
+ # Install Rails Mini Profiler to your Rails app
11
+ #
12
+ # Updates the routes file to mount the engine, adds an initializer and copies a migration.
13
+ desc 'Install rails-mini-profiler'
14
+
15
+ def install
16
+ route("mount RailsMiniProfiler::Engine => '/rails_mini_profiler'")
17
+ template 'rails_mini_profiler.rb.erb', 'config/initializers/rails_mini_profiler.rb'
18
+ system('rails rails_mini_profiler:install:migrations')
19
+ webpacker_install if defined?(Webpacker::Engine)
20
+ end
21
+
22
+ private
23
+
24
+ def webpacker_install
25
+ webpacker_config_file = Rails.root.join('config', 'webpacker.yml')
26
+ unless File.exist?(webpacker_config_file)
27
+ say "Webpacker is not installed. Run 'rails webpacker:install' and rerun installation to complete setup"
28
+ return
29
+ end
30
+
31
+ run 'yarn add @rails-mini-profiler/assets'
32
+ webpack_config = YAML.load_file(webpacker_config_file)[Rails.env]
33
+ destination = Rails.root.join(webpack_config['source_path'],
34
+ webpack_config['source_entry_path'],
35
+ 'rails-mini-profiler.js')
36
+ template('rails_mini_profiler.js.erb', destination)
37
+ end
38
+ end
39
+ end
40
+ end