rails_mini_profiler 0.4.0 → 0.5.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +13 -10
  3. data/app/javascript/images/check.svg +3 -0
  4. data/app/javascript/images/chevron.svg +3 -0
  5. data/app/javascript/images/filter.svg +1 -0
  6. data/app/javascript/images/logo_variant.svg +2 -2
  7. data/app/javascript/images/search.svg +4 -5
  8. data/app/javascript/js/checklist_controller.js +48 -0
  9. data/app/javascript/js/enable_controller.js +24 -0
  10. data/app/javascript/js/filter_controller.js +44 -0
  11. data/app/javascript/js/search_controller.js +18 -0
  12. data/app/javascript/js/select_controller.js +47 -0
  13. data/app/javascript/packs/rails-mini-profiler.js +23 -15
  14. data/app/javascript/stylesheets/components/page_header/page_header.scss +3 -0
  15. data/app/javascript/stylesheets/components/pagination.scss +14 -13
  16. data/app/javascript/stylesheets/components/profiled_request_table/placeholder.scss +33 -0
  17. data/app/javascript/stylesheets/components/profiled_request_table/profiled_request_table.scss +179 -0
  18. data/app/javascript/stylesheets/flamegraph.scss +3 -2
  19. data/app/javascript/stylesheets/flashes.scss +3 -5
  20. data/app/javascript/stylesheets/navbar.scss +7 -13
  21. data/app/javascript/stylesheets/profiled_requests.scss +35 -120
  22. data/app/javascript/stylesheets/rails-mini-profiler.scss +90 -61
  23. data/app/javascript/stylesheets/traces.scss +17 -17
  24. data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +8 -15
  25. data/app/search/rails_mini_profiler/base_search.rb +67 -0
  26. data/app/search/rails_mini_profiler/profiled_request_search.rb +34 -0
  27. data/app/views/rails_mini_profiler/badge.html.erb +2 -2
  28. data/app/views/rails_mini_profiler/profiled_requests/index.html.erb +8 -58
  29. data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +20 -0
  30. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_placeholder.erb +12 -0
  31. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table.erb +14 -0
  32. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +125 -0
  33. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_row.erb +21 -0
  34. data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +1 -1
  35. data/lib/rails_mini_profiler/configuration.rb +3 -0
  36. data/lib/rails_mini_profiler/engine.rb +12 -8
  37. data/lib/rails_mini_profiler/middleware.rb +3 -3
  38. data/lib/rails_mini_profiler/tracing/controller_tracer.rb +15 -0
  39. data/lib/rails_mini_profiler/tracing/null_trace.rb +7 -0
  40. data/lib/rails_mini_profiler/tracing/sequel_tracer.rb +37 -0
  41. data/lib/rails_mini_profiler/tracing/sequel_tracker.rb +37 -0
  42. data/lib/rails_mini_profiler/tracing/subscriptions.rb +34 -0
  43. data/lib/rails_mini_profiler/{models → tracing}/trace.rb +10 -2
  44. data/lib/rails_mini_profiler/tracing/trace_factory.rb +37 -0
  45. data/lib/rails_mini_profiler/tracing/tracer.rb +31 -0
  46. data/lib/rails_mini_profiler/tracing/view_tracer.rb +12 -0
  47. data/lib/rails_mini_profiler/tracing.rb +11 -0
  48. data/lib/rails_mini_profiler/version.rb +1 -1
  49. data/lib/rails_mini_profiler.rb +4 -8
  50. data/vendor/assets/images/check.svg +3 -0
  51. data/vendor/assets/images/chevron.svg +3 -0
  52. data/vendor/assets/images/filter.svg +1 -0
  53. data/vendor/assets/images/logo_variant.svg +2 -2
  54. data/vendor/assets/images/search.svg +4 -5
  55. data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
  56. data/vendor/assets/javascripts/rails-mini-profiler.js +1 -1
  57. metadata +33 -4
  58. data/lib/rails_mini_profiler/tracers.rb +0 -85
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33db210bbcb4b8ee82f80aa2f88023a478ec4852e9bbcc60cf9f70baf2a0145f
4
- data.tar.gz: aed097f8f0e418feea8ce2670f173271bea7dd1f8803e542c2f50b82b953932d
3
+ metadata.gz: 7e87dd3ae71d8ef0ab8021c31b037db8b290521782577dad5a7143cbbbd2f8f1
4
+ data.tar.gz: 1f7060bde727f2dbcdd7f4b6269d2436744cfb625484ed7bf43b5e4659743e6f
5
5
  SHA512:
6
- metadata.gz: a6cc1c0d0e05949bb360d4e5d04091bcfb16419a80ca31361d617a1a34571d28dfc33f31820075646143b9a359b12aa66c9ec67bb859bbdc25feaca062b5adb8
7
- data.tar.gz: c6673b79dc6b8aacd205b5b368c1e044fb8b0e595fbb41371cf6f2c667fe31875cea9376ea551cb0e39a6c13c57cd654f41342b09bc4f41a1084a03092804fe9
6
+ metadata.gz: 4e90925e2addb71264c09084a9b4244553b466f40e87f96902e60e9301b3befe3ed898a6578e6dd4a3c5c51cb18974fecda9036e6e5d82f27f3bac5bbce9e3aa
7
+ data.tar.gz: ed964b334db077211701b956c43f9f0e778bcd260e1097f1eaface96ffacbefe5c6e6bef01e6326f06db318da925a1a0d3a72790bf6c267e0e7d1309844ff95b
@@ -7,11 +7,9 @@ module RailsMiniProfiler
7
7
  before_action :set_profiled_request, only: %i[show destroy]
8
8
 
9
9
  def index
10
- @profiled_requests = ProfiledRequest
11
- .includes(:flamegraph)
12
- .where(user_id: user_id).order(id: :desc)
13
- @profiled_requests = @profiled_requests.where('request_path LIKE ?', "%#{params[:path]}%") if params[:path]
14
- @pagy, @profiled_requests = pagy(@profiled_requests, items: configuration.ui.page_size)
10
+ @profiled_requests = ProfiledRequest.where(user_id: user_id).order(id: :desc)
11
+ search = ProfiledRequestSearch.new(index_params, scope: @profiled_requests)
12
+ @pagy, @profiled_requests = pagy(search.results, items: configuration.ui.page_size)
15
13
  @profiled_requests = @profiled_requests.map { |request| present(request) }
16
14
  end
17
15
 
@@ -31,16 +29,21 @@ module RailsMiniProfiler
31
29
 
32
30
  def destroy_all
33
31
  ProfiledRequest.transaction do
34
- requests_table_name = RailsMiniProfiler.storage_configuration.profiled_requests_table.to_sym
35
- Flamegraph.joins(:profiled_request).where(requests_table_name => { user_id: user_id }).delete_all
36
- Trace.joins(:profiled_request).where(requests_table_name => { user_id: user_id }).delete_all
37
- ProfiledRequest.where(requests_table_name => { user_id: user_id }).delete_all
32
+ profiled_requests = ProfiledRequest.where(user_id: user_id)
33
+ profiled_requests = ProfiledRequestSearch.new(index_params, scope: profiled_requests).results
34
+ Flamegraph.joins(:profiled_request).merge(profiled_requests).delete_all
35
+ Trace.joins(:profiled_request).merge(profiled_requests).delete_all
36
+ profiled_requests.delete_all
38
37
  end
39
- redirect_to profiled_requests_url, notice: 'Profiled Requests cleared'
38
+ redirect_to profiled_requests_url, notice: 'Profiled requests cleared', status: :see_other
40
39
  end
41
40
 
42
41
  private
43
42
 
43
+ def index_params
44
+ params.permit(:path, :duration, id: [], method: [], media_type: [], status: [])
45
+ end
46
+
44
47
  def user_id
45
48
  @user_id ||= User.get(request.env)
46
49
  end
@@ -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 @@
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>
@@ -0,0 +1,48 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class extends Controller {
4
+ static targets = ["count"];
5
+
6
+ connect() {
7
+ this.setCount();
8
+ }
9
+
10
+ checkAll() {
11
+ this.setAllCheckboxes(true);
12
+ this.setCount();
13
+ }
14
+
15
+ checkNone() {
16
+ this.setAllCheckboxes(false);
17
+ this.setCount();
18
+ }
19
+
20
+ onChecked() {
21
+ this.setCount();
22
+ }
23
+
24
+ setAllCheckboxes(checked) {
25
+ this.checkboxes.forEach((el) => {
26
+ const checkbox = el;
27
+
28
+ if (!checkbox.disabled) {
29
+ checkbox.checked = checked;
30
+ }
31
+ });
32
+ }
33
+
34
+ setCount() {
35
+ if (this.hasCountTarget) {
36
+ const count = this.selectedCheckboxes.length;
37
+ this.countTarget.innerHTML = `${count} selected`;
38
+ }
39
+ }
40
+
41
+ get selectedCheckboxes() {
42
+ return this.checkboxes.filter((c) => c.checked);
43
+ }
44
+
45
+ get checkboxes() {
46
+ return new Array(...this.element.querySelectorAll("input[type=checkbox]"));
47
+ }
48
+ }
@@ -0,0 +1,24 @@
1
+ import { Controller } from 'stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ["enable"];
5
+
6
+ enable() {
7
+ this.enableTarget.disabled = false;
8
+ }
9
+
10
+ disable() {
11
+ this.enableTarget.disabled = true;
12
+ }
13
+
14
+ change(event) {
15
+ if (event.type.match(/rmp:select:.*/)) {
16
+ if (event.detail.count > 0) {
17
+ this.enable();
18
+ }
19
+ else {
20
+ this.disable()
21
+ }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,44 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class extends Controller {
4
+ static targets = ["filter"];
5
+
6
+ apply() {
7
+ location.href = `${window.location.pathname}?${this.params}`;
8
+ }
9
+
10
+ post() {
11
+ const token = document.head.querySelector(
12
+ 'meta[name="csrf-token"]'
13
+ ).content;
14
+ const path = `${window.location.pathname}/destroy_all?${this.params}`;
15
+ fetch(path, {
16
+ method: "DELETE",
17
+ redirect: "follow",
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ credentials: "same-origin",
21
+ },
22
+ body: JSON.stringify({ authenticity_token: token }),
23
+ }).then((response) => {
24
+ if (response.redirected) {
25
+ window.location.href = response.url;
26
+ }
27
+ });
28
+ }
29
+
30
+ get params() {
31
+ return this.activeFilterTargets()
32
+ .map((t) => `${t.name}=${t.value}`)
33
+ .join("&");
34
+ }
35
+
36
+ activeFilterTargets() {
37
+ return this.filterTargets.filter(function (target) {
38
+ if (target.type === "checkbox" || target.type === "radio")
39
+ return target.checked;
40
+
41
+ return target.value.length > 0;
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,18 @@
1
+ import { Controller } from "stimulus";
2
+
3
+ export default class extends Controller {
4
+ static targets = ["field"];
5
+
6
+ clear(){
7
+ this.eventTarget.value = null;
8
+ window.dispatchEvent(new CustomEvent('search-controller:submit', {}))
9
+ }
10
+
11
+ submit(event) {
12
+ event.preventDefault();
13
+
14
+ if (event.key === 'Enter' || event.type === 'click') {
15
+ window.dispatchEvent(new CustomEvent('search-controller:submit', {}))
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,47 @@
1
+ import { Controller } from 'stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ['all', 'selectable']
5
+
6
+ selectAll (event) {
7
+ const checked = event.target.checked
8
+ this.allTarget.indeterminate = false
9
+ this._setAllCheckboxes(checked)
10
+ this._dispatch('change', { count: this.selectedCount })
11
+ }
12
+
13
+ onSelected () {
14
+ this.allTarget.indeterminate = !!this._indeterminate
15
+ this._dispatch('change', { count: this.selectedCount })
16
+ }
17
+
18
+ get selectedCount () {
19
+ return this.selected.length
20
+ }
21
+
22
+ get selected () {
23
+ return this.selectables.filter((c) => c.checked)
24
+ }
25
+
26
+ get selectables () {
27
+ return new Array(...this.selectableTargets)
28
+ }
29
+
30
+ _setAllCheckboxes (checked) {
31
+ this.selectables.forEach((el) => {
32
+ const checkbox = el
33
+
34
+ if (!checkbox.disabled) {
35
+ checkbox.checked = checked
36
+ }
37
+ })
38
+ }
39
+
40
+ get _indeterminate () {
41
+ return this.selected.length !== this.selectableTargets.length && this.selected.length > 0
42
+ }
43
+
44
+ _dispatch (name, detail) {
45
+ window.dispatchEvent(new CustomEvent(`rmp:select:${name}`, { bubbles: true, detail }))
46
+ }
47
+ }
@@ -3,17 +3,23 @@ import '../stylesheets/rails-mini-profiler.scss'
3
3
  import tippy from 'tippy.js'
4
4
  import 'tippy.js/dist/tippy.css'
5
5
 
6
- function setupRequestSearch() {
7
- const profiledRequestNameSearch = document.getElementById('profiled-request-search')
8
- if (profiledRequestNameSearch) {
9
- profiledRequestNameSearch.addEventListener('keyup', function (event) {
10
- if (event.key === 'Enter') {
11
- event.preventDefault()
12
- document.getElementById('profiled-request-search-form').submit()
13
- }
14
- })
15
- }
16
- }
6
+ import { Application } from 'stimulus'
7
+ import { Dropdown } from 'tailwindcss-stimulus-components'
8
+ import Checklist from '../js/checklist_controller'
9
+ import Selectable from '../js/select_controller'
10
+ import Filter from '../js/filter_controller'
11
+ import Search from '../js/search_controller'
12
+ import Enable from '../js/enable_controller'
13
+
14
+ const application = Application.start();
15
+
16
+ application.register('dropdown', Dropdown)
17
+ application.register('checklist', Checklist)
18
+ application.register('selectable', Selectable)
19
+ application.register('filters', Filter)
20
+ application.register('search', Search)
21
+ application.register('enable', Enable)
22
+
17
23
 
18
24
  function setupTraceSearch() {
19
25
  const traceNameSearch = document.getElementById('trace-search')
@@ -30,8 +36,8 @@ function setupTraceSearch() {
30
36
  function setupRequestTable() {
31
37
  const profiledRequestTable = document.getElementById('profiled-requests-table');
32
38
  if (profiledRequestTable) {
33
- const rows = profiledRequestTable.getElementsByTagName('tr')
34
- for (let i = 0; i < rows.length; i++) {
39
+ const rows = profiledRequestTable.rows;
40
+ for (let i = 1; i < rows.length; i++) {
35
41
  const currentRow = profiledRequestTable.rows[i]
36
42
  const link = currentRow.dataset.link
37
43
  const createClickHandler = function () {
@@ -39,7 +45,10 @@ function setupRequestTable() {
39
45
  window.location.href = link
40
46
  }
41
47
  }
42
- currentRow.onclick = createClickHandler(currentRow)
48
+ if (link) {
49
+ currentRow.onclick = createClickHandler(currentRow)
50
+
51
+ }
43
52
  }
44
53
  }
45
54
  }
@@ -73,7 +82,6 @@ function setupTraceBars () {
73
82
  // Trace Bar Popovers
74
83
  document.addEventListener('DOMContentLoaded', () => {
75
84
  setupRequestTable();
76
- setupRequestSearch();
77
85
  setupTraceBars();
78
86
  setupTraceSearch();
79
87
  }, false)
@@ -0,0 +1,3 @@
1
+ .page-header {
2
+ padding: 2rem 0 2rem;
3
+ }
@@ -9,18 +9,12 @@
9
9
  .pagy-nav > .page.active,
10
10
  .pagy-nav > .page > a {
11
11
  padding: 0.5rem 1rem;
12
-
13
- color: var(--grey-900);
14
-
15
- background: white;
16
12
  border: 1px solid var(--border-color);
17
13
  border-right: none;
18
- text-decoration: none;
14
+ background: white;
15
+ color: var(--grey-900);
19
16
  cursor: pointer;
20
-
21
- &:hover {
22
- background: var(--grey-100);
23
- }
17
+ text-decoration: none;
24
18
  }
25
19
 
26
20
  .pagy-nav > .page.prev a,
@@ -30,15 +24,15 @@
30
24
 
31
25
  .pagy-nav > .page.next a,
32
26
  .pagy-nav > .page.next.disabled {
33
- border-radius: 0 5px 5px 0;
34
27
  border-right: 1px solid var(--border-color);
28
+ border-radius: 0 5px 5px 0;
35
29
  }
36
30
 
37
31
  .pagy-nav > .page.active {
38
- cursor: default;
39
- background: var(--red-500);
40
32
  border-color: var(--red-500);
33
+ background: var(--red-500);
41
34
  color: white;
35
+ cursor: default;
42
36
 
43
37
  &:hover {
44
38
  background: var(--red-500);
@@ -46,9 +40,16 @@
46
40
  }
47
41
 
48
42
  .pagy-nav > .page.disabled {
49
- cursor: default;
50
43
  color: var(--grey-500);
44
+ cursor: default;
45
+
51
46
  &:hover {
52
47
  background: white;
53
48
  }
54
49
  }
50
+
51
+ .pagy-nav > .page.disabled:hover,
52
+ .pagy-nav > .page.active:hover,
53
+ .pagy-nav > .page > a:hover {
54
+ background: var(--grey-100);
55
+ }
@@ -0,0 +1,33 @@
1
+
2
+ .placeholder {
3
+ display: flex;
4
+ width: 100%;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ justify-content: center;
8
+ padding-bottom: 2rem;
9
+ }
10
+
11
+ .placeholder-image {
12
+ width: 30%;
13
+ height: 30%;
14
+ -webkit-filter: grayscale(1) brightness(2.5);
15
+ }
16
+
17
+ .placeholder-text {
18
+ padding: 1rem 0;
19
+ color: var(--grey-400);
20
+ text-align: center;
21
+ }
22
+
23
+ .placeholder-link {
24
+ color: var(--grey-400);
25
+
26
+ &:visited {
27
+ color: var(--grey-400);
28
+ }
29
+
30
+ &:hover {
31
+ color: var(--grey-900);
32
+ }
33
+ }