rorvswild 1.6.5 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43d62b43885f0c12279773dc060954a30cfa80d0f19ca838398ba77c6b5b459b
4
- data.tar.gz: fd61331e3b88e2b1b682b0ff227349a99a806eaacbc4b64ec7ea0e22b509ae65
3
+ metadata.gz: 587f67697724c84547a0fde87674a10b35b4a36c61d5de4d032bd775fa339443
4
+ data.tar.gz: 5da27bd25a15ba85948731d383084852778545a7a86c95921194c22bf80efc7e
5
5
  SHA512:
6
- metadata.gz: 8022d6596eab0d903c5f59b6632e2b15b3c4ad7720af47f0f490ba6bb1d70867f3bd1c9e6d022bce9472002482338c0432b8f85f248bba0a8d7168f3f385d30a
7
- data.tar.gz: db65a5140351071e2ef1b668374372181d518848411fc379e46e4b1eb86ef01286dc643053728a317b3c6261e9ff07e8e5031f32f4a88d8077f62519febef46f
6
+ metadata.gz: 92cef045840fe613886cd7d2fd8370cf69afff5e86517025efaaf33d2e694c629225cd82dd728cbf8d1f89045119479dc7667ad44cb1cf935131e84e0720b067
7
+ data.tar.gz: 127d539486858d0f73ad38cb5ab4c2164c43b56c01673e114f08760e0a394b70be2bc569a0b332a7bc901347a05066d84e7407f772dd6c46ae227584930cdc49
@@ -133,6 +133,10 @@ module RorVsWild
133
133
  current_data[:error_context] = hash if current_data
134
134
  end
135
135
 
136
+ def send_server_timing=(boolean)
137
+ current_data[:send_server_timing] = boolean if current_data
138
+ end
139
+
136
140
  def current_data
137
141
  Thread.current[:rorvswild_data]
138
142
  end
@@ -182,6 +186,7 @@ module RorVsWild
182
186
 
183
187
  def queue_request
184
188
  (data = cleanup_data) && data[:name] && queue.push_request(data)
189
+ data
185
190
  end
186
191
 
187
192
  def queue_job
@@ -11,7 +11,7 @@ module RorVsWild
11
11
  CERTIFICATE_AUTHORITIES_PATH = File.expand_path("../../../cacert.pem", __FILE__)
12
12
  DEFAULT_TIMEOUT = 10
13
13
 
14
- attr_reader :api_url, :api_key, :timeout, :threads
14
+ attr_reader :api_url, :api_key, :timeout, :threads, :config
15
15
 
16
16
  def initialize(config)
17
17
  Kernel.at_exit(&method(:at_exit))
@@ -59,7 +59,7 @@ module RorVsWild
59
59
  end
60
60
 
61
61
  def self.read_from_scalingo
62
- @revision = ENV["SOURCE_VERSION"]
62
+ @revision = ENV["CONTAINER_VERSION"] || ENV["SOURCE_VERSION"]
63
63
  end
64
64
 
65
65
  def self.read_from_git
@@ -48,7 +48,9 @@ production:
48
48
  # - Redis
49
49
  # - Resque
50
50
  # - Sidekiq
51
+ #
51
52
  # logger: log/rorvswild.log # By default it uses Rails.logger or Logger.new(STDOUT)
53
+ #
52
54
  # # Deployment tracking is working without any actions from your part if the Rails app
53
55
  # # is inside a Git repositoriy, is deployed via Capistrano.
54
56
  # # In the other cases, you can provide the following details.
@@ -57,6 +59,16 @@ production:
57
59
  # description: <%= "Eventually if you have a description such as a Git message" %>
58
60
  # author: <%= "Author's name of the deployment" %>
59
61
  # email: <%= "emailOf@theAuthor.example" %>
62
+ #
63
+ # Sampling allows to send a fraction of jobs and requests.
64
+ # If your app is sending hundred of millions of requests per month,
65
+ # you will probably get the same precision if you send only a fraction of it.
66
+ # Thus, it decreases the bill at the end of the month. It's also a mitigation if
67
+ # your app is a target of a DoS. There are 2 parameters to dissociate requests and jobs.
68
+ # Indeed, for an app handling a lot of request but very few jobs, it makes sens to sample
69
+ # the former but not the latter.
70
+ # request_sampling_rate: 0.25 # 25% of requests are sent
71
+ # job_sampling_rate: 0.5 # 50% of jobs are sent
60
72
  YAML
61
73
  end
62
74
  end
@@ -41,6 +41,10 @@ RorVsWild.Local.prototype.toggle = function() {
41
41
  this.active ? this.collapse() : this.expand()
42
42
  }
43
43
 
44
+ RorVsWild.Local.prototype.toggleCommand = function(event) {
45
+ document.querySelector(event.currentTarget.getAttribute("data-target")).classList.toggle("is-open")
46
+ }
47
+
44
48
  RorVsWild.Local.prototype.expand = function() {
45
49
  this.currentRequest = this.requests[0]
46
50
  this.active = true
@@ -120,6 +124,7 @@ RorVsWild.Local.Request.prototype.sections = function() {
120
124
  return this.data.sections.map(function(section) {
121
125
  var runtime = (section.total_runtime - section.children_runtime)
122
126
  var object = {
127
+ id: RorVsWild.Local.nextId(),
123
128
  impact: RorVsWild.Local.formatImpact(runtime * 100 / this.data.runtime),
124
129
  averageRuntime: RorVsWild.Local.formatRuntime(runtime / section.calls),
125
130
  command: section.kind != "view" ? section.command : null,
@@ -5,54 +5,57 @@
5
5
 
6
6
  <script type="x-tmpl-mustache" data-partial="RorVsWild.Local">
7
7
  <div id="rorvswild-local-requests" class="rorvswild-local-panel {{containerClass}}">
8
-
9
8
  <div class="rorvswild-local-panel__header">
10
- <a href="https://www.rorvswild.com" class="rorvswild-local-panel__logo">
11
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34.83 30.83">
12
- <polygon points="17.41 9.41 13.41 9.41 9.41 13.41 17.41 21.41 25.41 13.41 21.41 9.41 17.41 9.41"/>
13
- <polyline points="1.41 21.41 9.41 29.41 17.41 21.41 25.41 29.41 33.41 21.41"/>
14
- <polyline points="9.41 5.41 5.41 1.41 1.41 5.41"/>
15
- <polyline points="33.41 5.41 29.41 1.41 25.41 5.41"/>
16
- </svg>
17
- </a>
18
-
19
- {{#currentRequest}}
20
- <span class="rorvswild-local-panel__header__title">breakdown</span>
21
- {{/currentRequest}}
22
- {{^currentRequest}}
23
- <span class="rorvswild-local-panel__header__title">history</span>
24
- {{/currentRequest}}
25
- <span class="rorvswild-local-panel__header__icons">
26
- <a href="https://github.com/BaseSecrete/rorvswild" class="rorvswild-local-panel__github" title="Source code">
27
- <svg width="16px" height="16px" viewBox="0 0 16 16">
28
- <path d="M8,0 C3.58,0 0,3.58 0,8 C0,11.54 2.29,14.53 5.47,15.59 C5.87,15.66 6.02,15.42 6.02,15.21 C6.02,15.02 6.01,14.39 6.01,13.72 C4,14.09 3.48,13.23 3.32,12.78 C3.23,12.55 2.84,11.84 2.5,11.65 C2.22,11.5 1.82,11.13 2.49,11.12 C3.12,11.11 3.57,11.7 3.72,11.94 C4.44,13.15 5.59,12.81 6.05,12.6 C6.12,12.08 6.33,11.73 6.56,11.53 C4.78,11.33 2.92,10.64 2.92,7.58 C2.92,6.71 3.23,5.99 3.74,5.43 C3.66,5.23 3.38,4.41 3.82,3.31 C3.82,3.31 4.49,3.1 6.02,4.13 C6.66,3.95 7.34,3.86 8.02,3.86 C8.7,3.86 9.38,3.95 10.02,4.13 C11.55,3.09 12.22,3.31 12.22,3.31 C12.66,4.41 12.38,5.23 12.3,5.43 C12.81,5.99 13.12,6.7 13.12,7.58 C13.12,10.65 11.25,11.33 9.47,11.53 C9.76,11.78 10.01,12.26 10.01,13.01 C10.01,14.08 10,14.94 10,15.21 C10,15.42 10.15,15.67 10.55,15.59 C13.71,14.53 16,11.53 16,8 C16,3.58 12.42,0 8,0 L8,0 Z"></path>
9
+ <div class="rorvswild-local-panel__width-limiter">
10
+ <a href="https://www.rorvswild.com" class="rorvswild-local-panel__logo">
11
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34.83 30.83">
12
+ <polygon points="17.41 9.41 13.41 9.41 9.41 13.41 17.41 21.41 25.41 13.41 21.41 9.41 17.41 9.41"/>
13
+ <polyline points="1.41 21.41 9.41 29.41 17.41 21.41 25.41 29.41 33.41 21.41"/>
14
+ <polyline points="9.41 5.41 5.41 1.41 1.41 5.41"/>
15
+ <polyline points="33.41 5.41 29.41 1.41 25.41 5.41"/>
29
16
  </svg>
30
17
  </a>
31
- {{#embedded}}
32
- <div data-events="click->collapse" class="rorvswild-local-panel__close" title="Close">
33
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
34
- <line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>
18
+
19
+ {{#currentRequest}}
20
+ <span class="rorvswild-local-panel__header__title">breakdown</span>
21
+ {{/currentRequest}}
22
+ {{^currentRequest}}
23
+ <span class="rorvswild-local-panel__header__title">history</span>
24
+ {{/currentRequest}}
25
+ <span class="rorvswild-local-panel__header__icons">
26
+ <a href="https://github.com/BaseSecrete/rorvswild" class="rorvswild-local-panel__github" title="Source code">
27
+ <svg width="16px" height="16px" viewBox="0 0 16 16">
28
+ <path d="M8,0 C3.58,0 0,3.58 0,8 C0,11.54 2.29,14.53 5.47,15.59 C5.87,15.66 6.02,15.42 6.02,15.21 C6.02,15.02 6.01,14.39 6.01,13.72 C4,14.09 3.48,13.23 3.32,12.78 C3.23,12.55 2.84,11.84 2.5,11.65 C2.22,11.5 1.82,11.13 2.49,11.12 C3.12,11.11 3.57,11.7 3.72,11.94 C4.44,13.15 5.59,12.81 6.05,12.6 C6.12,12.08 6.33,11.73 6.56,11.53 C4.78,11.33 2.92,10.64 2.92,7.58 C2.92,6.71 3.23,5.99 3.74,5.43 C3.66,5.23 3.38,4.41 3.82,3.31 C3.82,3.31 4.49,3.1 6.02,4.13 C6.66,3.95 7.34,3.86 8.02,3.86 C8.7,3.86 9.38,3.95 10.02,4.13 C11.55,3.09 12.22,3.31 12.22,3.31 C12.66,4.41 12.38,5.23 12.3,5.43 C12.81,5.99 13.12,6.7 13.12,7.58 C13.12,10.65 11.25,11.33 9.47,11.53 C9.76,11.78 10.01,12.26 10.01,13.01 C10.01,14.08 10,14.94 10,15.21 C10,15.42 10.15,15.67 10.55,15.59 C13.71,14.53 16,11.53 16,8 C16,3.58 12.42,0 8,0 L8,0 Z"></path>
35
29
  </svg>
36
- </div>
37
- {{/embedded}}
38
- </span>
30
+ </a>
31
+ {{#embedded}}
32
+ <div data-events="click->collapse" class="rorvswild-local-panel__close" title="Close">
33
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
34
+ <line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>
35
+ </svg>
36
+ </div>
37
+ {{/embedded}}
38
+ </span>
39
+ </div>
39
40
  </div>
40
41
  <div class="rorvswild-local-panel__content">
41
- {{#currentRequest}}
42
- <div data-events="click->goToHistory" class="rorvswild-local-panel__back-button" title="Go to history">
43
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
44
- <line x1="20" y1="12" x2="4" y2="12"></line>
45
- <polyline points="10 18 4 12 10 6"></polyline>
46
- </svg>
47
- </div>
48
- {{> RorVsWild.Local.RequestDetails}}
49
- {{/currentRequest}}
42
+ <div class="rorvswild-local-panel__width-limiter">
43
+ {{#currentRequest}}
44
+ <div data-events="click->goToHistory" class="rorvswild-local-panel__back-button" title="Go to history">
45
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
46
+ <line x1="20" y1="12" x2="4" y2="12"></line>
47
+ <polyline points="10 18 4 12 10 6"></polyline>
48
+ </svg>
49
+ </div>
50
+ {{> RorVsWild.Local.RequestDetails}}
51
+ {{/currentRequest}}
50
52
 
51
- {{^currentRequest}}
52
- {{#requests}}
53
- {{> RorVsWild.Local.RequestSummary}}
54
- {{/requests}}
55
- {{/currentRequest}}
53
+ {{^currentRequest}}
54
+ {{#requests}}
55
+ {{> RorVsWild.Local.RequestSummary}}
56
+ {{/requests}}
57
+ {{/currentRequest}}
58
+ </div>
56
59
  </div>
57
60
  <div class="rorvswild-local-panel__footer">
58
61
  This data is not sent to rorvswild.com. <a href="https://www.rorvswild.com" class="rorvswild-local-panel__footer__link">Create an account</a> to monitor your production environment.
@@ -66,12 +69,12 @@
66
69
 
67
70
  <script type="x-tmpl-mustache" data-partial="RorVsWild.Local.RequestSummary">
68
71
  <div data-events="click->goToRequestDetails" data-request-id="{{id}}" class="rorvswild-local-panel__request">
69
- <span class="rorvswild-local-panel__request__name">
70
- {{name}}
71
- <span class="rorvswild-local-panel__request__path">
72
+ <div class="rorvswild-local-panel__request__name">
73
+ <span>{{name}}</span>
74
+ <div class="rorvswild-local-panel__request__path">
72
75
  {{path}}
73
- </span>
74
- </span>
76
+ </div>
77
+ </div>
75
78
  <span class="rorvswild-local-panel__request__runtime">{{runtime}}<small>ms</small></span>
76
79
  <span class="rorvswild-local-panel__request__started-at">{{queuedAt}}</span>
77
80
  </div>
@@ -98,26 +101,31 @@
98
101
  </script>
99
102
 
100
103
  <script type="x-tmpl-mustache" data-partial="RorVsWild.Local.Section">
101
- <div class="rorvswild-local-panel__request-details__section">
104
+ <div class="rorvswild-local-panel__request-details__section" id="section-{{id}}">
102
105
  <div class="rorvswild-local-panel__request-details__section__main">
103
106
  <span class="rorvswild-local-panel__request-details__section__file">
107
+ {{#command}}
108
+ <button data-events="click->toggleCommand" data-target="#section-{{id}}" class="rorvswild-local-panel__request-details__section__kind"><span>{{kind}}</button>
109
+ {{/command}}
110
+ {{^command}}
111
+ <span class="rorvswild-local-panel__request-details__section__kind">{{kind}}</span>
112
+ {{/command}}
104
113
  {{#url}}
105
114
  <a href="{{url}}" class="rorvswild-local-panel__request-details__section__file__name" title="Open in your editor">{{file}}<span>:{{line}}</span></a>
106
115
  {{/url}}
107
116
  {{^url}}
108
117
  <span class="rorvswild-local-panel__request-details__section__file__name">{{file}}<span>:{{line}}</span></span>
109
118
  {{/url}}
110
- <div class="rorvswild-local-panel__request-details__section__code">
111
- <span class="rorvswild-local-panel__request-details__section__kind">{{kind}}</span>
112
- <span class="rorvswild-local-panel__request-details__section__command">
113
- <pre><code class="{{language}}">{{command}}</code></pre>
114
- </span>
115
- </div>
116
119
  </span>
117
120
  <span class="rorvswild-local-panel__request-details__section__average" title="average runtime">{{averageRuntime}}<small>ms</small></span>
118
121
  <span class="rorvswild-local-panel__request-details__section__calls" title="calls">x{{calls}}</span>
119
122
  <span class="rorvswild-local-panel__request-details__section__impact" title="impact">{{impact}}<small>&#37;</small></span>
120
123
  </div>
124
+ {{#command}}
125
+ <div class="rorvswild-local-panel__request-details__section__code">
126
+ <pre><code class="{{language}}">{{command}}</code></pre>
127
+ </div>
128
+ {{/command}}
121
129
  </div>
122
130
  </script>
123
131
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RorVsWild
2
4
  module Local
3
5
  class Middleware
@@ -99,7 +101,7 @@ module RorVsWild
99
101
  end
100
102
 
101
103
  def empty_html_page
102
- "<!DOCTYPE html>\n<html><head></head><body></body></html>"
104
+ "<!DOCTYPE html>\n<html><head></head><body></body></html>".dup
103
105
  end
104
106
 
105
107
  def log_incompatible_middleware_warning
@@ -96,11 +96,15 @@
96
96
  /* Panel Header */
97
97
  .rorvswild-local-panel__header {
98
98
  background: rgb(26 29 36) !important;
99
- padding: 12px !important;
100
99
  box-shadow: 0 1px 2px 0 rgba(14,18,26, .8) !important;
100
+ }
101
+
102
+ .rorvswild-local-panel__header .rorvswild-local-panel__width-limiter {
101
103
  display: flex;
104
+ padding: 12px !important;
102
105
  }
103
106
 
107
+
104
108
  .rorvswild-local-panel__header__title {
105
109
  color: rgb(199 203 214) !important;
106
110
  text-transform: uppercase !important;
@@ -113,7 +117,7 @@
113
117
  .rorvswild-local-panel svg {
114
118
  height: 24px !important;
115
119
  width: 24px !important;
116
- stroke-width: 2 !important;
120
+ stroke-width: 2.5 !important;
117
121
  fill: none !important;
118
122
  stroke-linecap: square !important;
119
123
  stroke: rgb(146 149 159) !important;
@@ -150,7 +154,7 @@
150
154
  .rorvswild-local-panel__content {
151
155
  flex: 1 !important;
152
156
  height: calc(100% - 48px) !important;
153
- overflow-y: auto;
157
+ overflow-y: scroll;
154
158
  overscroll-behavior: contain;
155
159
  }
156
160
 
@@ -187,10 +191,20 @@
187
191
  font-weight: 700;
188
192
  }
189
193
 
194
+ .rorvswild-local-panel__request__name > span {
195
+ text-decoration-color: rgb(146 149 159);
196
+ text-decoration: underline;
197
+ text-decoration-thickness: 1px;
198
+ text-underline-offset: 1px;
199
+ }
200
+
190
201
  .rorvswild-local-panel__request__path {
191
202
  color: rgb(146 149 159) !important;
192
203
  font-weight: 400;
193
204
  display: block !important;
205
+ text-decoration: none !important;
206
+ text-decoration-thickness: 0 !important;
207
+ text-decoration-color: transparent !important;
194
208
  }
195
209
 
196
210
  .rorvswild-local-panel__request__started-at {
@@ -241,6 +255,7 @@ h2.rorvswild-local-panel__request__name__title {
241
255
 
242
256
  .rorvswild-local-panel__request-details__section__main {
243
257
  display: flex !important;
258
+ gap: 8px;
244
259
  width: 100% !important;
245
260
  flex-wrap: wrap !important;
246
261
  }
@@ -251,16 +266,18 @@ h2.rorvswild-local-panel__request__name__title {
251
266
  overflow-wrap: break-word !important;
252
267
  min-width: 0 !important;
253
268
  color: rgb(199 203 214) !important;
269
+ display: flex;
270
+ gap: 8px;
254
271
  }
255
272
 
256
273
  a.rorvswild-local-panel__request-details__section__file__name {
257
274
  text-decoration-color: rgb(146 149 159);
258
275
  font-weight: 700;
276
+ text-decoration-thickness: 1px;
277
+ text-underline-offset: 1px;
259
278
  }
260
279
 
261
- a.rorvswild-local-panel__request-details__section__file__name:hover {
262
- text-decoration-color: rgb(199 203 214);
263
- }
280
+ a.rorvswild-local-panel__request-details__section__file__name:hover { text-decoration-color: rgb(199 203 214); }
264
281
 
265
282
  a.rorvswild-local-panel__request-details__section__file__name::after {
266
283
  content: '↗';
@@ -282,45 +299,96 @@ a.rorvswild-local-panel__request-details__section__file__name:hover::after { opa
282
299
  color: rgb(182 202 255) !important;
283
300
  font-weight: 700 !important;
284
301
  width: 48px !important;
285
- margin:0 12px 0 0 !important;
302
+ text-align: right;
303
+ margin-left: auto;
286
304
  }
287
305
 
288
306
  .rorvswild-local-panel__request-details__section__calls {
289
307
  color: rgb(199 203 214) !important;
290
308
  width: 48px !important;
291
- margin: 0 12px 0 0 !important;
309
+ text-align: right;
292
310
  }
293
311
 
294
312
  .rorvswild-local-panel__request-details__section__impact {
295
313
  color: rgb(199 203 214) !important;
296
314
  width: 48px !important;
297
315
  font-weight: 700 !important;
298
- margin: 0 12px 0 0 !important;
316
+ text-align: right;
299
317
  }
300
318
 
301
319
  .rorvswild-local-panel__request-details__section__code {
302
- display: flex !important;
303
320
  color: rgb(146 149 159) !important;
304
- margin-top: 8px !important;
321
+ background: rgb(14 15 20);
322
+ padding: 12px;
323
+ margin: 12px -12px -12px;
324
+ overflow: hidden !important;
325
+ display: none;
305
326
  }
306
327
 
307
328
  .rorvswild-local-panel__request-details__section__kind {
308
- background: rgb(38 41 49) !important;
329
+ background: rgb(38 41 49);
309
330
  font-size: 10px !important;
310
331
  text-transform: uppercase !important;
311
332
  text-align: center !important;
312
- letter-spacing: 2px !important;
313
- width: 72px !important;
333
+ letter-spacing: 1px !important;
334
+ width: 64px !important;
314
335
  height: 24px !important;
336
+ min-height: 24px;
337
+ padding: 0;
315
338
  display: inline-block !important;
339
+ flex-shrink: 0;
316
340
  }
317
341
 
318
- .rorvswild-local-panel__request-details__section__command {
319
- color: rgb(146 149 159) !important;
320
- flex: 1 !important;
321
- margin-left: 12px !important;
322
- opacity: 1;
323
- overflow: hidden !important;
342
+ button.rorvswild-local-panel__request-details__section__kind {
343
+ box-shadow: 0 0 0 1px rgb(72 75 80) inset;
344
+ border: none;
345
+ font-weight: 700;
346
+ position: relative;
347
+ }
348
+
349
+ button.rorvswild-local-panel__request-details__section__kind span {
350
+ display: inline-block;
351
+ max-width: calc(5ch + 5px);
352
+ white-space: nowrap;
353
+ overflow: hidden;
354
+ }
355
+
356
+ button.rorvswild-local-panel__request-details__section__kind:hover { box-shadow: 0 0 0 1px rgb(147 149 156) inset; }
357
+
358
+ button.rorvswild-local-panel__request-details__section__kind::after {
359
+ content: "";
360
+ display: block;
361
+ box-sizing: border-box;
362
+ position: absolute;
363
+ width: 4px;
364
+ height: 4px;
365
+ border-bottom: 1px solid rgb(146 149 159);
366
+ border-right: 1px solid rgb(146 149 159);
367
+ transform: rotate(45deg);
368
+ right: 6px;
369
+ top:calc(50% - 3px);
370
+ }
371
+
372
+ button.rorvswild-local-panel__request-details__section__kind:hover::after { border-color: inherit; }
373
+
374
+ span.rorvswild-local-panel__request-details__section__kind {
375
+ background: rgb(14 15 20) !important;
376
+ color: rgb(146 149 159)!important;
377
+ }
378
+
379
+ .rorvswild-local-panel__request-details__section.is-open .rorvswild-local-panel__request-details__section__code {
380
+ display: flex;
381
+ border-bottom: 1px solid rgb(26 29 36) !important
382
+ }
383
+
384
+ .rorvswild-local-panel__request-details__section.is-open .rorvswild-local-panel__request-details__section__kind {
385
+ color: rgb(182 202 255) !important;
386
+ background-color: rgb(14 15 20) !important;
387
+ }
388
+
389
+ .rorvswild-local-panel__request-details__section.is-open .rorvswild-local-panel__request-details__section__kind::after {
390
+ transform: rotate(225deg);
391
+ transform-origin: 2.5px 3px;
324
392
  }
325
393
 
326
394
  /* Panel Footer */
@@ -346,10 +414,8 @@ a.rorvswild-local-panel__footer__link {
346
414
 
347
415
  .rorvswild-local-panel__request__runtime { margin-left: 12px !important; }
348
416
 
349
- .rorvswild-local-panel__request-details__section__average,
350
- .rorvswild-local-panel__request-details__section__calls,
351
- .rorvswild-local-panel__request-details__section__impact {
352
- text-align: right !important;
353
- margin: 0 0 0 12px !important;
417
+ .rorvswild-local-panel__width-limiter {
418
+ max-width: 1520px;
419
+ margin: 0 auto;
354
420
  }
355
421
  }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RorVsWild
2
4
  module Plugin
3
5
  module DelayedJob
@@ -7,7 +9,14 @@ module RorVsWild
7
9
  Delayed::Worker.plugins << Class.new(Delayed::Plugin) do
8
10
  callbacks do |lifecycle|
9
11
  lifecycle.around(:invoke_job) do |job, *args, &block|
10
- RorVsWild.agent.measure_job(job.name, parameters: job.payload_object) { block.call(job) }
12
+ if job.payload_object.class.name == "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper"
13
+ job_name, job_args = job.payload_object.job_data.values_at("job_class", "arguments")
14
+ elsif job.payload_object.is_a?(Delayed::PerformableMethod)
15
+ job_name, job_args = job.name, job.payload_object.args
16
+ else
17
+ job_name, job_args = job.name, job.payload_object
18
+ end
19
+ RorVsWild.agent.measure_job(job_name, parameters: job_args) { block.call(job) }
11
20
  end
12
21
  end
13
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RorVsWild
2
4
  module Plugin
3
5
  class Middleware
@@ -13,19 +15,65 @@ module RorVsWild
13
15
 
14
16
  def call(env)
15
17
  RorVsWild.agent.start_request
16
- RorVsWild.agent.current_data[:path] = env["ORIGINAL_FULLPATH".freeze]
18
+ RorVsWild.agent.current_data[:path] = env["ORIGINAL_FULLPATH"]
17
19
  section = RorVsWild::Section.start
18
20
  section.file, section.line = rails_engine_location
19
- section.command = "Rails::Engine#call".freeze
20
- @app.call(env)
21
+ section.command = "Rails::Engine#call"
22
+ code, headers, body = @app.call(env)
23
+ [code, headers, body]
21
24
  ensure
22
25
  RorVsWild::Section.stop
23
- RorVsWild.agent.stop_request
26
+ inject_server_timing(RorVsWild.agent.stop_request, headers)
24
27
  end
25
28
 
29
+ private
30
+
26
31
  def rails_engine_location
27
32
  @rails_engine_location = ::Rails::Engine.instance_method(:call).source_location
28
33
  end
34
+
35
+ def format_server_timing_header(sections)
36
+ sections.map do |section|
37
+ if section.kind == "view"
38
+ "#{section.kind};dur=#{section.self_runtime};desc=\"#{section.file}\""
39
+ else
40
+ "#{section.kind};dur=#{section.self_runtime};desc=\"#{section.file}:#{section.line}\""
41
+ end
42
+ end.join(", ")
43
+ end
44
+
45
+ def format_server_timing_ascii(sections, total_width = 80)
46
+ max_time = sections.map(&:self_runtime).max
47
+ chart_width = (total_width * 0.25).to_i
48
+ rows = sections.map { |section|
49
+ [
50
+ section.kind == "view" ? section.file : "#{section.file}:#{section.line}",
51
+ "█" * (section.self_runtime * (chart_width-1) / max_time),
52
+ "#{section.self_runtime}ms"
53
+ ]
54
+ }
55
+ time_width = rows.map { |cols| cols[2].size }.max + 1
56
+ label_width = total_width - chart_width - time_width
57
+ rows.each { |cols| cols[0] = truncate_backwards(cols[0], label_width) }
58
+ template = "%-#{label_width}s%#{chart_width}s%#{time_width}s"
59
+ rows.map { |cols| format(template, *cols) }.join("\n")
60
+ end
61
+
62
+ def truncate_backwards(string, width)
63
+ string.size > width ? "…" + string[-(width - 1)..-1] : string
64
+ end
65
+
66
+ def inject_server_timing(data, headers)
67
+ return if !data || !data[:send_server_timing] || !(sections = data[:sections])
68
+ sections = sections.sort_by(&:self_runtime).reverse[0,10]
69
+ headers["Server-Timing"] = format_server_timing_header(sections)
70
+ if data[:name] && RorVsWild.logger.level <= Logger::Severity::DEBUG
71
+ RorVsWild.logger.debug(["┤ #{data[:name]} ├".center(80, "─"),
72
+ format_server_timing_ascii(sections),
73
+ "─" * 80, nil].join("\n")
74
+ )
75
+ end
76
+ end
29
77
  end
30
78
  end
31
79
  end
@@ -14,15 +14,17 @@ module RorVsWild
14
14
  @client = client
15
15
  @mutex = Mutex.new
16
16
  @metrics = RorVsWild::Metrics.new if defined?(Metrics)
17
+ @request_sampling_rate = client.config[:request_sampling_rate]
18
+ @job_sampling_rate = client.config[:job_sampling_rate]
17
19
  Kernel.at_exit { flush }
18
20
  end
19
21
 
20
22
  def push_job(data)
21
- push_to(jobs, data)
23
+ push_to(jobs, data) if !@job_sampling_rate || rand <= @job_sampling_rate
22
24
  end
23
25
 
24
26
  def push_request(data)
25
- push_to(requests, data)
27
+ push_to(requests, data) if !@request_sampling_rate || rand <= @request_sampling_rate
26
28
  end
27
29
 
28
30
  def push_to(array, data)
@@ -1,3 +1,3 @@
1
1
  module RorVsWild
2
- VERSION = "1.6.5".freeze
2
+ VERSION = "1.7.1".freeze
3
3
  end
data/lib/rorvswild.rb CHANGED
@@ -50,6 +50,10 @@ module RorVsWild
50
50
  agent.merge_error_context(hash) if agent
51
51
  end
52
52
 
53
+ def self.send_server_timing=(boolean)
54
+ agent.send_server_timing = boolean if agent
55
+ end
56
+
53
57
  def self.initialize_logger(destination = nil)
54
58
  if destination.respond_to?(:info) && destination.respond_to?(:warn) && destination.respond_to?(:error)
55
59
  destination
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rorvswild
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.5
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Bernard
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-04-18 00:00:00.000000000 Z
12
+ date: 2024-06-03 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Performances and errors insights for rails developers.
15
15
  email:
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubygems_version: 3.2.22
89
+ rubygems_version: 3.3.26
90
90
  signing_key:
91
91
  specification_version: 4
92
92
  summary: Ruby on Rails applications monitoring