rails_mini_profiler 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }