rails_mini_profiler 0.6.0 → 0.7.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +47 -35
  3. data/app/adapters/rails_mini_profiler/database_adapter.rb +16 -0
  4. data/app/controllers/rails_mini_profiler/application_controller.rb +9 -6
  5. data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +15 -4
  6. data/app/helpers/rails_mini_profiler/profiled_requests_helper.rb +10 -0
  7. data/app/javascript/js/clipboard_controller.js +9 -2
  8. data/app/javascript/js/filter_controller.js +4 -0
  9. data/app/javascript/stylesheets/components/buttons.scss +59 -0
  10. data/app/javascript/stylesheets/components/{profiled_request_table/profiled_request_table.scss → dropdown.scss} +0 -76
  11. data/app/javascript/stylesheets/components/input.scss +10 -0
  12. data/app/javascript/stylesheets/{navbar.scss → components/navbar.scss} +0 -0
  13. data/app/javascript/stylesheets/components/page_header.scss +7 -0
  14. data/app/javascript/stylesheets/components/{profiled_request_table/placeholder.scss → placeholder.scss} +4 -1
  15. data/app/javascript/stylesheets/components/profiled_request_table.scss +55 -0
  16. data/app/javascript/stylesheets/components/trace.scss +93 -0
  17. data/app/javascript/stylesheets/profiled_requests.scss +3 -67
  18. data/app/javascript/stylesheets/rails-mini-profiler.scss +16 -30
  19. data/app/javascript/stylesheets/traces.scss +44 -76
  20. data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +2 -2
  21. data/app/presenters/rails_mini_profiler/trace_presenter.rb +9 -7
  22. data/app/search/rails_mini_profiler/profiled_request_search.rb +0 -1
  23. data/app/search/rails_mini_profiler/trace_search.rb +27 -0
  24. data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +1 -2
  25. data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +7 -7
  26. data/app/views/rails_mini_profiler/profiled_requests/{shared → show}/_trace.html.erb +23 -21
  27. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list.erb +12 -0
  28. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_header.erb +87 -0
  29. data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_placeholder.erb +12 -0
  30. data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +4 -17
  31. data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +1 -0
  32. data/lib/rails_mini_profiler/configuration/user_interface.rb +18 -0
  33. data/lib/rails_mini_profiler/flamegraph_guard.rb +10 -6
  34. data/lib/rails_mini_profiler/middleware.rb +2 -0
  35. data/lib/rails_mini_profiler/user.rb +1 -1
  36. data/lib/rails_mini_profiler/version.rb +1 -1
  37. data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
  38. data/vendor/assets/javascripts/rails-mini-profiler.js +1 -1
  39. metadata +25 -9
  40. data/app/javascript/stylesheets/components/page_header/page_header.scss +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ee7ad78091b3a10151ce83c08c255e9ccc78c16112a74a89c939876c52146ed
4
- data.tar.gz: 33c09a36420c374b1b40a8cdbaec6a9a5a0ef5822dddc9bb2e6a47902c0ddce3
3
+ metadata.gz: bb1212a4d90c46143193b2173e9e136aa6757a74a6591137cba33169235d175d
4
+ data.tar.gz: f799849a5d978c2c22d39b3fa1f4be6c02541f75b7a2312d98a510a1d69a195b
5
5
  SHA512:
6
- metadata.gz: a40ccbdbfd8a40b8b9eba3ba9a1f29436bd25f645640112ad0cda3426a7b4c3c4b8fe174569c304c3a8dbe3cc1c1987d5b6bee4b2c4a52309cd0e273879f437e
7
- data.tar.gz: 7f7527d2d8fd2e898951a36ecfb0e413cf1264b1dc495a637e4cd1a802ab690df754ae3c39d5d626e37c931120430c0f8a58a78262c5672b0f27edf7c2262ae3
6
+ metadata.gz: ae143e874778e4af9560e5b6521003c5d4933ec86ffe5900a56c57b93791a3d0faa3ac18294cecccac12048dc35c38a70aa7a53ffa91b12d2025a89c0acc0384
7
+ data.tar.gz: f2a8ca075571593f1cce9d1b59910ea5aac8f95a06c277298be9e0e93be5dcd1b013fbaefbef22bf173f6e2db40fed29068cfda44d422aa372cdde30818ec9cf
data/README.md CHANGED
@@ -63,8 +63,6 @@ route:
63
63
  ```ruby
64
64
  # routes.rb
65
65
  Rails.application.routes.draw do
66
- ...
67
-
68
66
  mount RailsMiniProfiler::Engine => '/rails_mini_profiler'
69
67
  end
70
68
  ```
@@ -76,18 +74,18 @@ top right that is injected into your pages.
76
74
 
77
75
  ![overview](docs/images/overview.png)
78
76
 
79
- Requests to your application will be profiled automatically. You can view all stored requests by navigating to `yourapp/rails_mini_profiler/profiled_requests`.
77
+ Requests to your application will be profiled automatically. You can view and search all stored requests by navigating to `yourapp/rails_mini_profiler/profiled_requests`.
80
78
 
81
79
  ### Request Details
82
80
 
83
81
  <p align="center">
84
82
  <img alt="Light" src="docs/images/trace.png" width="45%">
85
83
  &nbsp; &nbsp; &nbsp; &nbsp;
86
- <img alt="Dark" src="docs/images/sequel.png" width="45%">
84
+ <img alt="Dark" src="docs/images/trace-details.png" width="45%">
87
85
  </p>
88
86
 
89
87
  This view shows you how your requests spend their time. How much of it is spent in the DB, how much in rendering views?
90
- By clicking on individual traces you can find out detailed information.
88
+ May can filter and clicking on individual traces to gain deeper insights and see detailed information.
91
89
 
92
90
  ### Flamegraphs
93
91
 
@@ -114,15 +112,8 @@ Rails Mini Profiler provides a wide array of configuration options. You can find
114
112
  | `skip_paths` | `[]` | An array of request paths that should not be profiled. Regex allowed. |
115
113
  | `storage` | `Storage.new` | Storage configuration. See [Storage](#Storage). |
116
114
  | `ui` | `UserInterface.new` | UI configuration. See [UI](#UI). |
117
- | `user_provider` | `Rack::Request.new(env).ip` | How to identify users. See [Users](#Users) |
118
-
119
- ### Request Configuration
115
+ | `user_provider` | `Rack::Request.new(env).ip` | How to identify users. See [Authorization](#Authorization) |
120
116
 
121
- You may override the configuration by sending request parameters. The following parameters are available:
122
-
123
- | Name | Description |
124
- | ---------------- | ------------------------------------------------------------------------------------------- |
125
- | `rmp_flamegraph` | Overrides `flamegraph_enabled` If set to `true` will redirect to the flamegraph immediatly. |
126
117
 
127
118
  ### Storage
128
119
 
@@ -140,7 +131,7 @@ Rails Mini Profiler does not offer an automatic way to clean up old profiling in
140
131
 
141
132
  ```ruby
142
133
  # Clockwork
143
- every(1.month, 'purge rails mini profiler' do
134
+ every(1.month, 'purge rails mini profiler') do
144
135
  ProfiledRequestCleanupJob.perform_later
145
136
  end
146
137
 
@@ -158,25 +149,33 @@ end
158
149
 
159
150
  Rails Mini Profiler allows you to configure various UI features.
160
151
 
161
- | Name | Default | Description |
162
- |---------------------|--------------|-------------------------------------------------------------------------------------------------|
163
- | `badge_enabled` | `true` | Should the hedgehog 🦔 badge be injected into pages? |
164
- | `badge_position` | `'top-left'` | Where to display the badge. Options are `'top-left', 'top-right', 'bottom-left, 'bottom-right'` |
165
- | `page_size` | `25` | The page size for lists shown in the UI. |
166
- | `webpacker_enabled` | `true` | Use Webpacker if available? Disable to fall back to the asset pipeline.
152
+ | Name | Default | Description |
153
+ |---------------------|---------------------------|-------------------------------------------------------------------------------------------------|
154
+ | `badge_enabled` | `true` | Should the hedgehog 🦔 badge be injected into pages? |
155
+ | `badge_position` | `'top-left'` | Where to display the badge. Options are `'top-left', 'top-right', 'bottom-left, 'bottom-right'` |
156
+ | `base_controller` | `ApplicationController` | Which controller UI controllers should inherit from. |
157
+ | `page_size` | `25` | The page size for lists shown in the UI. |
158
+ | `webpacker_enabled` | `true` | Use Webpacker if available? Disable to fall back to the asset pipeline. |
167
159
 
160
+ ### Request Configuration
168
161
 
169
- ### Users
162
+ You may override static configuration on a per-request by attaching request parameters. For example, `https://myapp.com/api/mydata?rmp_flamegraph=false`
170
163
 
171
- Profiling information is segregated by user ID. That means users cannot see each other's profiled requests.
164
+ | Name | Description |
165
+ | ---------------- | ------------------------------------------------------------------------------------------- |
166
+ | `rmp_flamegraph` | Overrides `flamegraph_enabled` If set to `true` will redirect to the flamegraph immediately. |
167
+
168
+ ### Authorization
172
169
 
173
- Per default, individual users are identified by their IP address. You may change this by setting a custom user provider:
170
+ Profiling information is segregated by user ID. That means users cannot see each other's profiled requests. Per default, individual users are identified by their IP adress.
171
+
172
+ You may change this by setting a custom user provider:
174
173
 
175
174
  ```ruby
176
175
  config.user_provider = proc { |env| Rack::Request.new(env).ip }
177
176
  ```
178
177
 
179
- You may also explicitly set the user from the application itself:
178
+ You may also explicitly set the user by modifying your application controller (or the controller you have configured as UI base controller):
180
179
 
181
180
  ```ruby
182
181
  class ApplicationController < ActionController::Base
@@ -186,15 +185,18 @@ class ApplicationController < ActionController::Base
186
185
  end
187
186
  ```
188
187
 
189
- Note that you **must** set the current user when running Rails Mini Profiler in production. No profiles will be saved otherwise.
188
+ `ApplicationController` is used as the default base class for UI controllers. To change it, you may use `configuration.ui.base_controller`.
190
189
 
191
190
  ### Profiling in Production
192
191
 
193
192
  Rails Mini Profiler is not intended for performance reporting. There are other tools for that ( [Skylight](https://www.skylight.io/),
194
- [New Relic](https://newrelic.com/), [DataDog](https://www.datadoghq.com/)...).
193
+ [New Relic](https://newrelic.com/), [DataDog](https://www.datadoghq.com/)...). But you can still use RMP in production to profile specific requests.
194
+
195
+ Per default, *no requests will be profiled* in production, and the Rails Mini Profiler UI will be inaccessible.
196
+
197
+ #### Enabling Profiling
195
198
 
196
- However, you can still use it in production to profile specific requests. Since profiling impacts performance, it is recommended
197
- that you limit which requests are being profiled:
199
+ Since profiling impacts performance, it is recommended that you limit which requests are being profiled:
198
200
 
199
201
  ```ruby
200
202
  RailsMiniProfiler.configure do |config|
@@ -202,7 +204,17 @@ RailsMiniProfiler.configure do |config|
202
204
  end
203
205
  ```
204
206
 
205
- Only requests by explicitly set users will be stored. To configure how individual users are identified see [Users](#Users)
207
+ #### Authorizing Users
208
+
209
+ You must explicitly authorize profiling for users, as well as authenticate them to the UI:
210
+
211
+ ```ruby
212
+ class ApplicationController < ActionController::Base
213
+ before_action do
214
+ RailsMiniProfiler::User.authorize(current_user.id) # Requests by this user will now be profiled, and they get access to the UI
215
+ end
216
+ end
217
+ ```
206
218
 
207
219
  ## Why Rails Mini Profiler?
208
220
 
@@ -212,13 +224,13 @@ Improving the performance of any application is a 3-step process. You have to an
212
224
  2. Why is it slow?
213
225
  3. Did my solution fix the slowness?
214
226
 
215
- I'm a huge fan of [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler), and AMP tools such as [Skylight](https://www.skylight.io/) or [Scout APM](https://scoutapm.com), and each of these tools has its place.
227
+ I'm a huge fan of [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler), and APM tools such as [Skylight](https://www.skylight.io/) or [Scout APM](https://scoutapm.com). Each of these tools has its own areas where it succeeds.
216
228
 
217
- APM tools are excellent for profiling your app in production - aka. they show you what is slow - and offer _some_ hints as to what causes the slowdown. `rack-mini-profiler` can do some sampling in production, but excels at providing detailed insight into _why_ something is slow, using Flamegraphs and detailed query information.
229
+ APM tools are excellent for profiling your app in production - aka. they show you what is slow - and offer _some_ hints as to what causes the slowdown. `rack-mini-profiler` can do some sampling in production, but excels at providing detailed insight into _why_ something is slow by providing Flamegraphs and detailed query information.
218
230
 
219
231
  Rails Mini Profiler improves upon `rack-mini-profiler` in the latter regard. It is a developer tool, rather than a monitoring tool, and sets a big focus on developer experience. Simply put, it aims to be the best tool available to help you figure out _why_ specific requests are slow.
220
232
 
221
- As such, compared to `rack-mini-profiler`, it does not support non-Rails apps (e.g. Sinatra) or production sampling, but provides a much better user experience and better supports API-only applications.
233
+ As such, compared to `rack-mini-profiler`, it does not support non-Rails apps (e.g. Sinatra) or production sampling, but provides a much better user experience and better support for API-only applications.
222
234
 
223
235
  ## Troubleshooting
224
236
 
@@ -243,13 +255,13 @@ rails db:migrate
243
255
 
244
256
  Rails Mini Profiler supports API-only apps, but you have to make some small adjustments to use it. At the top of `application.rb` add [Sprockets](https://github.com/rails/sprockets-rails):
245
257
 
246
- ```
258
+ ```ruby
247
259
  require "sprockets/railtie"
248
260
  ```
249
261
 
250
262
  Then, modify `application.rb`:
251
263
 
252
- ```
264
+ ```ruby
253
265
  module ApiOnly
254
266
  class Application < Rails::Application
255
267
 
@@ -259,7 +271,7 @@ module ApiOnly
259
271
  end
260
272
  ```
261
273
 
262
- **Note: Sprockets and flash are currently required for some of Rails Mini Profiler's UI features. These modifications may no longer be needed in the future.
274
+ **Note**: Sprockets and flash are currently required for some of Rails Mini Profiler's UI features. These modifications may no longer be needed in the future.
263
275
 
264
276
  ### No Flamegraphs are being recored?
265
277
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMiniProfiler
4
+ class DatabaseAdapter
5
+ class << self
6
+ def cast_to_text(column)
7
+ if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
8
+ # Cast json field to text to have access to the LIKE operator
9
+ "#{column}::text"
10
+ else
11
+ column
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsMiniProfiler
4
- class ApplicationController < ActionController::Base
5
- include Pagy::Backend
6
-
4
+ class ApplicationController < RailsMiniProfiler.configuration.ui.base_controller
7
5
  rescue_from ActiveRecord::RecordNotFound, with: ->(error) { handle(error, 404) }
8
6
 
9
- before_action :check_current_user
7
+ before_action :check_rmp_user
10
8
 
11
9
  protected
12
10
 
@@ -26,8 +24,13 @@ module RailsMiniProfiler
26
24
  end
27
25
  end
28
26
 
29
- def check_current_user
30
- redirect_back(fallback_location: root_path) unless User.get(request.env).present?
27
+ def check_rmp_user
28
+ user = User.get(request.env).present?
29
+ redirect_back(fallback_location: fallback_location) unless user
30
+ end
31
+
32
+ def fallback_location
33
+ defined?(main_app.root_path) ? main_app.root_path : '/'
31
34
  end
32
35
  end
33
36
  end
@@ -4,6 +4,8 @@ require_dependency 'rails_mini_profiler/application_controller'
4
4
 
5
5
  module RailsMiniProfiler
6
6
  class ProfiledRequestsController < ApplicationController
7
+ include Pagy::Backend
8
+
7
9
  before_action :set_profiled_request, only: %i[show destroy]
8
10
 
9
11
  def index
@@ -14,11 +16,16 @@ module RailsMiniProfiler
14
16
  end
15
17
 
16
18
  def show
17
- @traces = @profiled_request.traces
18
- @traces = @traces.where("#{payload_column} LIKE ?", "%#{params[:search]}%") if params[:search]
19
- @traces = @traces
19
+ search = TraceSearch.new(show_params, scope: @profiled_request.traces)
20
+ context = {
21
+ start: @profiled_request.start,
22
+ finish: @profiled_request.finish,
23
+ total_duration: @profiled_request.duration,
24
+ total_allocations: @profiled_request.allocations
25
+ }
26
+ @traces = search.results
20
27
  .order(:start)
21
- .map { |trace| present(trace, profiled_request: @profiled_request) }
28
+ .map { |trace| present(trace, context: context) }
22
29
  @profiled_request = present(@profiled_request)
23
30
  end
24
31
 
@@ -40,6 +47,10 @@ module RailsMiniProfiler
40
47
 
41
48
  private
42
49
 
50
+ def show_params
51
+ params.permit(:id, :payload, :duration, :allocations, name: [])
52
+ end
53
+
43
54
  def index_params
44
55
  params.permit(:path, :duration, id: [], method: [], media_type: [], status: [])
45
56
  end
@@ -12,5 +12,15 @@ module RailsMiniProfiler
12
12
  def formatted_allocations(allocations)
13
13
  number_to_human(allocations, units: { unit: '', thousand: 'k', million: 'M', billion: 'B', trillion: 'T' })
14
14
  end
15
+
16
+ def trace_display_name(name)
17
+ {
18
+ 'sql.active_record': 'ActiveRecord Query',
19
+ 'instantiation.active_record': 'ActiveRecord Instantiation',
20
+ 'render_template.action_view': 'Render View',
21
+ 'render_partial.action_view': 'Render Partial',
22
+ 'process_action.action_controller': 'Controller'
23
+ }[name.to_sym]
24
+ end
15
25
  end
16
26
  end
@@ -36,11 +36,18 @@ export default class extends Controller {
36
36
  }
37
37
 
38
38
  const copiedClass = this.data.get("copiedClass");
39
- console.log(copiedClass);
40
- this.buttonTarget.classList.add(copiedClass);
39
+ if (copiedClass) {
40
+ this.buttonTarget.classList.add(copiedClass);
41
+ }
42
+ const copiedMessage = this.data.get("copiedMessage");
43
+ const content = this.buttonTarget.innerHTML;
44
+ if (copiedMessage) {
45
+ this.buttonTarget.innerHTML = copiedMessage;
46
+ }
41
47
 
42
48
  this.timeout = setTimeout(() => {
43
49
  this.buttonTarget.classList.remove(copiedClass);
50
+ this.buttonTarget.innerHTML = content;
44
51
  }, this.successDuration);
45
52
  }
46
53
  }
@@ -7,6 +7,10 @@ export default class extends Controller {
7
7
  location.href = `${window.location.pathname}?${this.params}`;
8
8
  }
9
9
 
10
+ reset() {
11
+ location.href = `${window.location.pathname}`;
12
+ }
13
+
10
14
  post() {
11
15
  const token = document.head.querySelector(
12
16
  'meta[name="csrf-token"]'
@@ -0,0 +1,59 @@
1
+ button,
2
+ .button {
3
+ display: inline-block;
4
+ padding: 0.5em 0.5em;
5
+ border: none;
6
+ border-radius: 5px;
7
+ cursor: pointer;
8
+ font-size: 1rem;
9
+ text-align: center;
10
+ text-decoration: none;
11
+
12
+ &:disabled {
13
+ background: var(--grey-200);
14
+ cursor: not-allowed;
15
+ }
16
+ }
17
+
18
+ .btn-red {
19
+ background: var(--red-500);
20
+ color: white;
21
+ font-weight: 600;
22
+ outline: none;
23
+
24
+ &:hover {
25
+ background: var(--red-600);
26
+ }
27
+ }
28
+
29
+ .btn-grey {
30
+ background: var(--grey-200);
31
+
32
+ &:hover {
33
+ background: var(--grey-100);
34
+ }
35
+ }
36
+
37
+ .btn-white {
38
+ border: 1px solid var(--grey-200);
39
+ background: white;
40
+
41
+ &:hover {
42
+ background: var(--grey-100);
43
+ }
44
+ }
45
+
46
+ button:hover {
47
+ box-shadow: 0 0.25rem 0.25rem 0 var(--grey-50);
48
+ }
49
+
50
+ button.none {
51
+ padding: 0;
52
+ border: none;
53
+ background: none;
54
+ outline: none;
55
+
56
+ &:hover {
57
+ box-shadow: none;
58
+ }
59
+ }
@@ -1,54 +1,3 @@
1
- .table {
2
- width: 100%;
3
- border: hidden 1px var(--border-color);
4
-
5
- /* Hack to get table row borders, see https://stackoverflow.com/a/2586780/2553104 */
6
- border-collapse: collapse;
7
- border-radius: 5px;
8
- box-shadow: 0 0 0 1px var(--border-color);
9
- table-layout: fixed;
10
- }
11
-
12
- .table th,
13
- .table td {
14
- padding: 0.5rem 1rem;
15
- }
16
-
17
- .table thead tr {
18
- border: hidden 1px var(--border-color);
19
- box-shadow: 0 0 0 1px var(--border-color);
20
- color: var(--grey-400);
21
- }
22
-
23
- .table tr:nth-child(even) {
24
- background: var(--grey-50);
25
- }
26
-
27
- .table thead th {
28
- font-weight: 400;
29
- }
30
-
31
- .table-filter-icon {
32
- width: 14px;
33
- margin-left: 0.5rem;
34
- }
35
-
36
- .table tbody tr:not(.no-row) {
37
- border: solid 1px var(--border-color);
38
- color: var(--grey-700);
39
- cursor: pointer;
40
- }
41
-
42
- .table tbody tr:not(.no-row):hover {
43
- background: var(--grey-100);
44
- }
45
-
46
- .request-checkbox {
47
- z-index: 1;
48
- width: 1rem;
49
- height: 1rem;
50
- }
51
-
52
1
  .dropdown-body {
53
2
  padding: 0.33rem 0.5rem;
54
3
  }
@@ -152,28 +101,3 @@
152
101
  background: var(--red-600);
153
102
  }
154
103
  }
155
-
156
- .dropdown-search-button {
157
- display: inline-block;
158
- padding: 0.5em 0.5em;
159
- border: none;
160
- background: var(--red-500);
161
- border-radius: 5px;
162
- color: white;
163
- cursor: pointer;
164
- font-size: 1rem;
165
- font-weight: 600;
166
- text-align: center;
167
- text-decoration: none;
168
-
169
- &:hover {
170
- background: var(--red-600);
171
- }
172
- }
173
-
174
- .request-path {
175
- overflow: hidden;
176
- max-width: 280px;
177
- text-overflow: ellipsis;
178
- white-space: nowrap;
179
- }
@@ -0,0 +1,10 @@
1
+ input[type=submit] {
2
+ display: inline-block;
3
+ padding: 0.5em 0.5em;
4
+ border: none;
5
+ border-radius: 5px;
6
+ cursor: pointer;
7
+ font-size: 1rem;
8
+ text-align: center;
9
+ text-decoration: none;
10
+ }
@@ -0,0 +1,7 @@
1
+ .page-header {
2
+ padding: 2.5rem 0 2.5rem;
3
+ }
4
+
5
+ .page-header h1 {
6
+ font-size: 28px;
7
+ }
@@ -1,4 +1,3 @@
1
-
2
1
  .placeholder {
3
2
  display: flex;
4
3
  width: 100%;
@@ -20,6 +19,10 @@
20
19
  text-align: center;
21
20
  }
22
21
 
22
+ .placeholder-text h2 {
23
+ padding-bottom: 1rem;
24
+ }
25
+
23
26
  .placeholder-link {
24
27
  color: var(--grey-400);
25
28
 
@@ -0,0 +1,55 @@
1
+ .table {
2
+ width: 100%;
3
+ border: hidden 1px var(--border-color);
4
+
5
+ /* Hack to get table row borders, see https://stackoverflow.com/a/2586780/2553104 */
6
+ border-collapse: collapse;
7
+ border-radius: 5px;
8
+ box-shadow: 0 0 0 1px var(--border-color);
9
+ table-layout: fixed;
10
+ }
11
+
12
+ .table th,
13
+ .table td {
14
+ padding: 0.5rem 1rem;
15
+ }
16
+
17
+ .table thead tr {
18
+ color: var(--grey-500);
19
+ }
20
+
21
+ .table tr:nth-child(even) {
22
+ background: var(--grey-50);
23
+ }
24
+
25
+ .table thead th {
26
+ font-weight: 400;
27
+ }
28
+
29
+ .table-filter-icon {
30
+ width: 14px;
31
+ margin-left: 0.5rem;
32
+ }
33
+
34
+ .table tbody tr:not(.no-row) {
35
+ border: solid 1px var(--border-color);
36
+ color: var(--grey-700);
37
+ cursor: pointer;
38
+ }
39
+
40
+ .table tbody tr:not(.no-row):hover {
41
+ background: var(--grey-100);
42
+ }
43
+
44
+ .request-checkbox {
45
+ z-index: 1;
46
+ width: 1rem;
47
+ height: 1rem;
48
+ }
49
+
50
+ .request-path {
51
+ overflow: hidden;
52
+ max-width: 280px;
53
+ text-overflow: ellipsis;
54
+ white-space: nowrap;
55
+ }
@@ -0,0 +1,93 @@
1
+ .trace {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: flex-start;
5
+ padding: 0.25em 0;
6
+ list-style: none;
7
+ }
8
+
9
+ .trace:nth-child(odd) {
10
+ background: var(--grey-100);
11
+ }
12
+
13
+ .trace .trace-bar {
14
+ position: relative;
15
+ height: 16px;
16
+ padding: 0;
17
+ margin: 0;
18
+ background: linear-gradient(to top right, var(--grey-500), var(--grey-400));
19
+ cursor: pointer;
20
+ }
21
+
22
+ .instantiation-trace .trace-bar {
23
+ background: linear-gradient(to top right, var(--green-400), var(--green-300));
24
+ }
25
+
26
+ .sequel-trace .trace-bar {
27
+ background: linear-gradient(to top right, var(--green-500), var(--green-400));
28
+ }
29
+
30
+ .controller-trace .trace-bar {
31
+ background: linear-gradient(to top right, var(--yellow-500), var(--yellow-400));
32
+ }
33
+
34
+ .render-template-trace .trace-bar,
35
+ .render-partial-trace .trace-bar {
36
+ background: linear-gradient(to top right, var(--blue-500), var(--blue-400));
37
+ }
38
+
39
+ .trace-name {
40
+ overflow: hidden;
41
+ box-sizing: border-box;
42
+ padding: 0 0.5em;
43
+ margin: 0;
44
+ color: var(--grey-400);
45
+ font-size: 14px;
46
+ text-align: right;
47
+ text-overflow: ellipsis;
48
+ }
49
+
50
+ .trace-payload {
51
+ margin: 0;
52
+ }
53
+
54
+ .sequel-trace-query {
55
+ overflow: auto;
56
+ max-height: 100px;
57
+ padding: 1em 1em;
58
+ background: var(--grey-100);
59
+ white-space: pre-wrap;
60
+ }
61
+
62
+ .sequel-trace-binds {
63
+ overflow: auto;
64
+ max-height: 100px;
65
+ padding: 0.5em 1em;
66
+ margin: 0 0 1em 0;
67
+ background: var(--grey-50);
68
+ font-size: 12px;
69
+ white-space: pre-wrap;
70
+ }
71
+
72
+ .backtrace {
73
+ display: flex;
74
+ flex-direction: row;
75
+ align-items: center;
76
+ justify-content: space-between;
77
+ padding: 0.5em;
78
+ background: var(--grey-100);
79
+ }
80
+
81
+ .backtrace button {
82
+ overflow: auto;
83
+ height: 20px;
84
+ padding: 0;
85
+ margin: 0;
86
+ background: none;
87
+ color: var(--grey-500);
88
+ }
89
+
90
+ .backtrace button svg {
91
+ width: 20px;
92
+ height: 20px;
93
+ }