rails_mini_profiler 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +47 -35
- data/app/adapters/rails_mini_profiler/database_adapter.rb +16 -0
- data/app/controllers/rails_mini_profiler/application_controller.rb +9 -6
- data/app/controllers/rails_mini_profiler/profiled_requests_controller.rb +15 -4
- data/app/helpers/rails_mini_profiler/profiled_requests_helper.rb +10 -0
- data/app/javascript/js/clipboard_controller.js +9 -2
- data/app/javascript/js/filter_controller.js +4 -0
- data/app/javascript/stylesheets/components/buttons.scss +59 -0
- data/app/javascript/stylesheets/components/{profiled_request_table/profiled_request_table.scss → dropdown.scss} +0 -76
- data/app/javascript/stylesheets/components/input.scss +10 -0
- data/app/javascript/stylesheets/{navbar.scss → components/navbar.scss} +0 -0
- data/app/javascript/stylesheets/components/page_header.scss +7 -0
- data/app/javascript/stylesheets/components/{profiled_request_table/placeholder.scss → placeholder.scss} +4 -1
- data/app/javascript/stylesheets/components/profiled_request_table.scss +55 -0
- data/app/javascript/stylesheets/components/trace.scss +93 -0
- data/app/javascript/stylesheets/profiled_requests.scss +3 -67
- data/app/javascript/stylesheets/rails-mini-profiler.scss +16 -30
- data/app/javascript/stylesheets/traces.scss +44 -76
- data/app/presenters/rails_mini_profiler/profiled_request_presenter.rb +2 -2
- data/app/presenters/rails_mini_profiler/trace_presenter.rb +9 -7
- data/app/search/rails_mini_profiler/profiled_request_search.rb +0 -1
- data/app/search/rails_mini_profiler/trace_search.rb +27 -0
- data/app/views/rails_mini_profiler/profiled_requests/shared/header/_header.erb +1 -2
- data/app/views/rails_mini_profiler/profiled_requests/shared/table/_table_head.erb +7 -7
- data/app/views/rails_mini_profiler/profiled_requests/{shared → show}/_trace.html.erb +23 -21
- data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list.erb +12 -0
- data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_header.erb +87 -0
- data/app/views/rails_mini_profiler/profiled_requests/show/_trace_list_placeholder.erb +12 -0
- data/app/views/rails_mini_profiler/profiled_requests/show.html.erb +4 -17
- data/lib/generators/rails_mini_profiler/templates/rails_mini_profiler.rb.erb +1 -0
- data/lib/rails_mini_profiler/configuration/user_interface.rb +18 -0
- data/lib/rails_mini_profiler/flamegraph_guard.rb +10 -6
- data/lib/rails_mini_profiler/middleware.rb +2 -0
- data/lib/rails_mini_profiler/user.rb +1 -1
- data/lib/rails_mini_profiler/version.rb +1 -1
- data/vendor/assets/javascripts/rails-mini-profiler.css +1 -1
- data/vendor/assets/javascripts/rails-mini-profiler.js +1 -1
- metadata +25 -9
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb1212a4d90c46143193b2173e9e136aa6757a74a6591137cba33169235d175d
|
4
|
+
data.tar.gz: f799849a5d978c2c22d39b3fa1f4be6c02541f75b7a2312d98a510a1d69a195b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
86
|
-
<img alt="Dark" src="docs/images/
|
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
|
-
|
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 [
|
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
|
162
|
-
|
163
|
-
| `badge_enabled` | `true`
|
164
|
-
| `badge_position` | `'top-left'`
|
165
|
-
| `
|
166
|
-
| `
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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 <
|
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 :
|
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
|
30
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
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,
|
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
|
-
|
40
|
-
|
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
|
-
}
|
File without changes
|
@@ -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
|
+
}
|