rorvswild 1.6.5 → 1.7.1

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.
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