rorvswild 1.10.1 → 1.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec6464a7193ffe1e78cc6d84804a74e37dd66e20f086b357215e143cca8e3339
4
- data.tar.gz: 0547a433e44c778c2f7199be0e6532325e572ac868f85b2209dd99eea1ba4593
3
+ metadata.gz: b29f5881ffc0b495ede8b88ca53f68161a5bbfa09ca4005c0384a18f17a77ce9
4
+ data.tar.gz: 8cf948c1c9ea720aeb35068160e61a506085194c3ad2f5caa5b43f6c6c5ee5a2
5
5
  SHA512:
6
- metadata.gz: 5929a6e6deb9fab72c05e5446363ed3cab3368c2b3c7a2e68ef9e4fa58b0fcc1736421936b6153a8eab650f33a4337bb691744af4739bd99dad63db9c1dbdb2d
7
- data.tar.gz: d5533fe4bc53ec97eed6d52e8637a7f231ffed0d56af0716d7e1713d0d3042d88620c201d50edb61e29af26bd786d666d30a403d54ff9b64d046b15ae180fb71
6
+ metadata.gz: 90e4b903eec8db8e89d3c6fdb77397bb75e7bb09212d7cc86fea9a865b1d5d13ab7ea9e9d9d7d199fda10ad20d3b5fb12749eb41841329de0db0b6893e05e6db
7
+ data.tar.gz: 1745b14bce30d4dccc1584e35c301f55b481156f8919e5030fee11c52e879ff6b7e77b2128b286d1566f0b407666799e6b4c6551b30e457a66b3ac213e1ce0bd
data/README.md CHANGED
@@ -1,26 +1,25 @@
1
1
 
2
- # RorVsWild
2
+ # RoRvsWild
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/rorvswild.svg)](https://badge.fury.io/rb/rorvswild)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/2c4805cf658d7af794fe/maintainability)](https://codeclimate.com/github/BaseSecrete/rorvswild/maintainability)
6
5
 
7
- <img align="right" width="120px" src="./images/rorvswild_logo.jpg">
6
+ <img align="right" width="120px" src="./images/rorvswild_logo.png">
8
7
 
9
- *RoRvsWild* is a ruby gem to monitor performances and exceptions in Ruby on Rails applications.
8
+ *RoRvsWild* is a Ruby gem to monitor performances and exceptions in Ruby on Rails applications.
10
9
 
11
- This gem has a double mode, **development** and **production**.
12
- It can be used without an account to monitor your requests performances in your development environment.
13
- It can also be used in your production and staging environments with an account on https://rorvswild.com. With such an account you also get extra benefits such as 30 day trace, background jobs monitoring, exceptions monitoring and notifications.
10
+ This gem has a double mode: **development** and **production**.
11
+ It can be used without an account to monitor the performance of your requests in your development environment.
12
+ It can also be used in your production and staging environments with an account on https://rorvswild.com. With such an account, you also get additional benefits, including 30-day trace, background job monitoring, exception monitoring, and notifications.
14
13
 
15
14
  ## Development mode
16
15
 
17
16
  ### Install the gem
18
17
 
19
18
  * Add in your Gemfile `gem "rorvswild"`
20
- * Run `bundle install` in you terminal
21
- * Restart your local server and you’ll see a small button in the bottom left corner of your page.
19
+ * Run `bundle install` in your terminal.
20
+ * Restart your local server, and you’ll see a small button in the bottom left corner of your page.
22
21
 
23
- <img width="166px" src="./images/rorvswild_local_button.png">
22
+ <img width="218px" src="./images/rorvswild_local_button.png" alt="RoRvsWild Local button">
24
23
 
25
24
  Click on the button, or navigate to http://localhost:3000/rorvswild to see the details panel:
26
25
 
@@ -29,13 +28,13 @@ Click on the button, or navigate to http://localhost:3000/rorvswild to see the d
29
28
  ## Production mode
30
29
 
31
30
  **To monitor your production or staging environment, you need an API key.**
32
- Signup on https://www.rorvswild.com and create an app to get one.
31
+ Sign up on https://www.rorvswild.com and create an app to get one.
33
32
 
34
33
  * Add in your Gemfile `gem "rorvswild"`
35
- * Run `bundle install` in you terminal
36
- * Run `rorvswild-install API_KEY` in you terminal
37
- * Deploy/Restart your app
38
- * Make a few requests and refresh your app page on rorvswild.com to view the dashboard.
34
+ * Run `bundle install` in your terminal.
35
+ * Run `rorvswild-install API_KEY` in your terminal.
36
+ * Deploy/Restart your app.
37
+ * Make a few requests, and refresh your app page on rorvswild.com to view the dashboard.
39
38
 
40
39
  ![RoRvsWild Production](./images/rorvswild_prod.png)
41
40
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "set"
4
4
  require "uri"
5
+ require "zlib"
5
6
  require "json/ext"
6
7
  require "net/http"
7
8
 
@@ -24,6 +25,7 @@ module RorVsWild
24
25
  @mutex = Mutex.new
25
26
  @config = config
26
27
  @headers = {
28
+ "Content-Encoding" => "deflate",
27
29
  "Content-Type" => "application/json",
28
30
  "X-RorVsWild-Version" => RorVsWild::VERSION,
29
31
  "X-Ruby-Version" => RUBY_VERSION,
@@ -36,7 +38,7 @@ module RorVsWild
36
38
  uri = URI(api_url + path)
37
39
  post = Net::HTTP::Post.new(uri.path, @headers)
38
40
  post.basic_auth(nil, api_key)
39
- post.body = JSON.generate(data)
41
+ post.body = Zlib.deflate(JSON.generate(data), Zlib::BEST_SPEED)
40
42
  transmit(post)
41
43
  end
42
44
 
@@ -22,10 +22,12 @@ development:
22
22
  # widget: top-left, top-right, bottom-left, bottom-right or hidden
23
23
 
24
24
  # Open files in your text editor by clicking from the local widget.
25
- # VSCode: vscode://file${path}:${line}
26
- # Sublime: subl://${path}:${line}
27
- # It should be set with an env variable when developers are not using the same editor.
28
- editor_url: <%= ENV.fetch("RORVSWILD_EDITOR_URL", "vscode://file${path}:${line}") %>
25
+ # Leave commented to auto-detect from RAILS_EDITOR or EDITOR env vars (Rails 8.1+).
26
+ # Or set explicitly:
27
+ # editor_url: <%= ENV.fetch("RORVSWILD_EDITOR_URL", "vscode://file${path}:${line}") %>
28
+ # for VSCode: "vscode://file${path}:${line}"
29
+ # for Sublime: "subl://${path}:${line}"
30
+
29
31
 
30
32
  production:
31
33
  api_key: #{api_key}
@@ -74,6 +74,18 @@ RorVsWild.Local.prototype.toggleCommand = function(event) {
74
74
  document.querySelector(event.currentTarget.dataset.target).classList.toggle("is-open")
75
75
  }
76
76
 
77
+ RorVsWild.Local.prototype.toggleLowImpactSections = function(event) {
78
+ var button = event.currentTarget
79
+ var sections = document.querySelectorAll(".rorvswild-local-panel__details__section[data-low-impact]")
80
+ var isHidden = sections[0].classList.contains("is-hidden")
81
+
82
+ sections.forEach(function(section) {
83
+ section.classList.toggle("is-hidden")
84
+ })
85
+
86
+ button.textContent = isHidden ? "↑ Hide low impact sections" : "↓ View low impact sections"
87
+ }
88
+
77
89
  RorVsWild.Local.prototype.expand = function() {
78
90
  this.active = true
79
91
  this.goToRequestDetail(event)
@@ -107,6 +119,7 @@ RorVsWild.Local.formatImpact = function(impact) {
107
119
  }
108
120
 
109
121
  RorVsWild.Local.formatDateTime = function(date) {
122
+ if (!date || isNaN(date.getTime())) return ""
110
123
  var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
111
124
  var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()
112
125
  var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours()
@@ -189,9 +202,11 @@ RorVsWild.Local.Request.prototype.runtime = function() {
189
202
  RorVsWild.Local.Request.prototype.sections = function() {
190
203
  return this.data.sections.map(function(section) {
191
204
  var runtime = (section.total_runtime - section.children_runtime)
205
+ var impactValue = runtime * 100 / this.data.runtime
192
206
  return {
193
207
  id: RorVsWild.Local.nextId(),
194
- impact: RorVsWild.Local.formatImpact(runtime * 100 / this.data.runtime),
208
+ impact: RorVsWild.Local.formatImpact(impactValue),
209
+ isLowImpact: impactValue < 1,
195
210
  language: RorVsWild.Local.kindToLanguage(section.kind),
196
211
  totalRuntime: RorVsWild.Local.relevantRounding(section.total_runtime),
197
212
  asyncRuntime: RorVsWild.Local.relevantRounding(section.async_runtime),
@@ -212,6 +227,10 @@ RorVsWild.Local.Request.prototype.sections = function() {
212
227
  }.bind(this)).sort(function(a, b) { return b.selfRuntime - a.selfRuntime })
213
228
  }
214
229
 
230
+ RorVsWild.Local.Request.prototype.hasLowImpactSections = function() {
231
+ return this.sections().some(function(section) { return section.isLowImpact })
232
+ }
233
+
215
234
  RorVsWild.Local.Request.prototype.sectionsImpactPerKind = function() {
216
235
  var total = 0
217
236
  var perKind = this.sections().reduce(function(object, section) {
@@ -148,6 +148,11 @@
148
148
  {{#sections}}
149
149
  {{> RorVsWild.Local.Section}}
150
150
  {{/sections}}
151
+ {{#hasLowImpactSections}}
152
+ <div class="rorvswild-local-panel__toggle-low-impact">
153
+ <button data-events="click->toggleLowImpactSections" class="rorvswild-local-panel__toggle-low-impact__button">↓ view low impact sections</button>
154
+ </div>
155
+ {{/hasLowImpactSections}}
151
156
  </div>
152
157
  </script>
153
158
 
@@ -162,7 +167,7 @@
162
167
  </script>
163
168
 
164
169
  <script type="x-tmpl-mustache" data-partial="RorVsWild.Local.Section">
165
- <div class="rorvswild-local-panel__details__section" id="section-{{id}}">
170
+ <div class="rorvswild-local-panel__details__section {{#isLowImpact}}is-hidden{{/isLowImpact}}" {{#isLowImpact}}data-low-impact{{/isLowImpact}} id="section-{{id}}">
166
171
  <div class="rorvswild-local-panel__details__section__main">
167
172
  <span class="rorvswild-local-panel__details__section__file">
168
173
  <button data-events="click->toggleCommand" data-target="#section-{{id}}" class="rorvswild-local-panel__details__section__kind"><span>{{kind}}</button>
@@ -181,32 +186,32 @@
181
186
 
182
187
  <div class="rorvswild-local-panel__details__section__code">
183
188
  <dl>
184
- {{#isAsync}}
185
- <div>
186
- <dt title="Time spent as non blocking IO">Async runtime</dt>
187
- <dd>{{asyncRuntime}}<small>ms</small></dd>
188
- </div>
189
- {{/isAsync}}
190
189
  <div>
191
- <dt title="self + children">Total runtime</dt>
192
- <dd title="{{selfRuntime}} + {{childrenRuntime}}">{{totalRuntime}}<small>ms</small></dd>
190
+ <dt title="self runtime / calls">Average runtime</dt>
191
+ <dd title="{{selfRuntime}} / {{calls}}">{{averageRuntime}}<small>ms</small></dd>
193
192
  </div>
194
193
  <div>
195
- <dt title="total - self">Children runtime</dt>
196
- <dd title="{{totalRuntime}} - {{selfRuntime}}">{{childrenRuntime}}<small>ms</small></dd>
194
+ <dt>Calls</dt>
195
+ <dd class="dd--calls">{{calls}}<small>x</small></dd>
197
196
  </div>
198
197
  <div>
199
198
  <dt title="total - children">Self runtime</dt>
200
199
  <dd title="{{totalRuntime}} - {{childrenRuntime}}">{{selfRuntime}}<small>ms</small></dd>
201
200
  </div>
202
201
  <div>
203
- <dt>Calls</dt>
204
- <dd class="dd--calls">{{calls}}<small>x</small></dd>
202
+ <dt title="total - self">Children runtime</dt>
203
+ <dd title="{{totalRuntime}} - {{selfRuntime}}">{{childrenRuntime}}<small>ms</small></dd>
205
204
  </div>
206
205
  <div>
207
- <dt title="self runtime / calls">Average runtime</dt>
208
- <dd title="{{selfRuntime}} / {{calls}}">{{averageRuntime}}<small>ms</small></dd>
206
+ <dt title="self + children">Total runtime</dt>
207
+ <dd title="{{selfRuntime}} + {{childrenRuntime}}">{{totalRuntime}}<small>ms</small></dd>
209
208
  </div>
209
+ {{#isAsync}}
210
+ <div>
211
+ <dt title="Time spent as non blocking IO">Async runtime</dt>
212
+ <dd>{{asyncRuntime}}<small>ms</small></dd>
213
+ </div>
214
+ {{/isAsync}}
210
215
  </dl>
211
216
  {{#command}}
212
217
  <pre><code class="{{language}}">{{command}}</code></pre>
@@ -335,5 +340,5 @@
335
340
  {{/currentError}}
336
341
  </script>
337
342
 
338
- <link rel="stylesheet" media="all" href="/rorvswild.css"/>
343
+ <link rel="stylesheet" media="all" href="/rorvswild.css">
339
344
  <script src="/rorvswild.js"></script>
@@ -79,7 +79,13 @@ module RorVsWild
79
79
  end
80
80
 
81
81
  def editor_url
82
- RorVsWild.agent.config[:editor_url]
82
+ config[:editor_url] || rails_editor_url
83
+ end
84
+
85
+ def rails_editor_url
86
+ if editor = defined?(ActiveSupport::Editor) && ActiveSupport::Editor.current
87
+ editor.url_for("${path}", 999999.999999).gsub("999999.999999", "${line}").gsub("999999", "${line}")
88
+ end
83
89
  end
84
90
 
85
91
  def inject_into(html)
@@ -39,7 +39,7 @@ module RorVsWild
39
39
  private
40
40
 
41
41
  def push_to(data, name)
42
- data[:queued_at] = Time.now
42
+ data[:queued_at] = Time.now.iso8601(3)
43
43
  data[:uuid] = SecureRandom.uuid
44
44
  File.open(File.join(@directoy, "#{name}.ndjson"), "a") { |file| file.write(JSON.dump(data) + "\n") }
45
45
  end
@@ -126,6 +126,7 @@
126
126
  color: rgb(146 149 159) !important;
127
127
  cursor: pointer !important;
128
128
  line-height: 48px !important;
129
+ margin: 0 !important;
129
130
  }
130
131
 
131
132
  .rorvswild-local-panel__header nav li:hover {
@@ -350,6 +351,10 @@ h2.rorvswild-local-panel__title {
350
351
  display: block !important;
351
352
  }
352
353
 
354
+ .rorvswild-local-panel__details__section.is-hidden {
355
+ display: none !important;
356
+ }
357
+
353
358
  .rorvswild-local-panel__details__section:hover {
354
359
  background: rgb(26 29 36) !important;
355
360
  transition: all .3s !important;
@@ -433,30 +438,31 @@ a.rorvswild-local-panel__file__name:hover::after { opacity: 1; }
433
438
  .rorvswild-local-panel__details__section__code dl {
434
439
  display: flex;
435
440
  align-items: baseline;
436
- justify-content: flex-end;
437
441
  flex-wrap: wrap;
438
442
  margin: 0;
439
443
  padding: 0;
440
- text-align: right;
444
+ text-align: center;
441
445
  gap: 12px 24px;
442
446
  }
443
447
 
448
+ .rorvswild-local-panel__details__section__code dl > * {
449
+ flex: 1;
450
+ }
451
+
444
452
  .rorvswild-local-panel__details__section__code dt {
445
453
  white-space: nowrap;
446
- margin: 0;
454
+ margin: 4px 0 0;
447
455
  text-transform: uppercase;
448
456
  letter-spacing: 1px;
449
457
  font-size: 9px !important;
458
+ line-height: 12px;
459
+ font-weight: 400;
450
460
  }
451
461
 
452
462
  .rorvswild-local-panel__details__section__code dd {
453
463
  margin: 0;
454
- color: rgb(182 202 255) !important;
455
- font-weight: 700;
456
- }
457
-
458
- .rorvswild-local-panel__details__section__code dd.dd--calls {
459
464
  color: rgb(199 203 214) !important;
465
+ font-weight: 700;
460
466
  }
461
467
 
462
468
  .rorvswild-local-panel__details__section__code dl + pre[class*="language-"] {
@@ -593,6 +599,31 @@ span.rorvswild-local-panel__details__section__kind {
593
599
  overflow-wrap: break-word !important;
594
600
  }
595
601
 
602
+ .rorvswild-local-panel__toggle-low-impact {
603
+ padding: 12px !important;
604
+ }
605
+
606
+ .rorvswild-local-panel__toggle-low-impact__button {
607
+ background: transparent !important;
608
+ color: rgb(199 203 214) !important;
609
+ border: 1px solid rgb(72 75 80) !important;
610
+ box-shadow: none !important;
611
+ padding: 0px 8px !important;
612
+ font-size: 10px !important;
613
+ line-height: 24px !important;
614
+ text-transform: uppercase !important;
615
+ letter-spacing: 1px !important;
616
+ cursor: pointer !important;
617
+ font-weight: 700 !important;
618
+ transition: all 0.2s !important;
619
+ }
620
+
621
+ .rorvswild-local-panel__toggle-low-impact__button:hover {
622
+ background: transparent !important;
623
+ color: rgb(223 228 242) !important;
624
+ border-color: rgb(147 149 156) !important;
625
+ }
626
+
596
627
  /* Panel Footer */
597
628
  .rorvswild-local-panel__footer {
598
629
  width: 100% !important;
@@ -6,7 +6,7 @@ module RorVsWild
6
6
  def self.start(config = {})
7
7
  queue = RorVsWild::Local::Queue.new(config[:queue] || {})
8
8
  RorVsWild.start(config.merge(queue: queue))
9
- Rails.application.config.middleware.unshift(RorVsWild::Local::Middleware, nil)
9
+ Rails.application.config.middleware.unshift(RorVsWild::Local::Middleware, config)
10
10
  end
11
11
  end
12
12
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RorVsWild
4
+ module Plugin
5
+ class Rack
6
+ @installed = false
7
+
8
+ def self.setup(agent)
9
+ return if @installed
10
+ return if !defined?(ActiveSupport::Notifications.subscribe)
11
+ ActiveSupport::Notifications.subscribe("process_middleware.action_dispatch", new)
12
+ @installed = true
13
+ end
14
+
15
+ def start(name, id, payload)
16
+ section = RorVsWild::Section.start
17
+ section.kind = "rack"
18
+ if location = source_location(payload[:middleware])
19
+ section.file = location[0]
20
+ section.line = location[1]
21
+ section.commands << payload[:middleware]
22
+ else
23
+ section.file = payload[:middleware]
24
+ section.line = 0
25
+ end
26
+ end
27
+
28
+ def finish(name, id, payload)
29
+ RorVsWild::Section.stop
30
+ end
31
+
32
+ private
33
+
34
+ def source_location(middleware_name)
35
+ middleware = Kernel.const_get(middleware_name)
36
+ middleware.instance_method(:call).source_location
37
+ rescue NameError
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RorVsWild
4
4
  module Plugin
5
- class Middleware
5
+ module RailsEngine
6
6
  module RequestQueueTime
7
7
 
8
8
  ACCEPTABLE_HEADERS = [
@@ -49,24 +49,19 @@ module RorVsWild
49
49
  @installed = false
50
50
 
51
51
  def self.setup(agent)
52
- return if @installed
53
- Rails.application.config.middleware.unshift(RorVsWild::Plugin::Middleware, nil) if defined?(Rails)
52
+ return if @installed || !defined?(Rails::Engine)
53
+ Rails::Engine.prepend(self)
54
54
  @installed = true
55
55
  end
56
56
 
57
- def initialize(app, config)
58
- @app, @config = app, config
59
- end
60
-
61
57
  def call(env)
62
- execution = RorVsWild::Execution::Request.new(env["ORIGINAL_FULLPATH"])
58
+ execution = RorVsWild::Execution::Request.new(env["REQUEST_URI"])
63
59
  execution.add_queue_time(calculate_queue_time(env))
64
60
  RorVsWild.agent.start_execution(execution)
65
61
  section = RorVsWild::Section.start
66
- section.file, section.line = rails_engine_location
62
+ section.file, section.line = method(:call).super_method.source_location
67
63
  section.commands << "Rails::Engine#call"
68
- code, headers, body = @app.call(env)
69
- [code, headers, body]
64
+ super
70
65
  ensure
71
66
  RorVsWild::Section.stop
72
67
  RorVsWild.agent.stop_execution
@@ -79,10 +74,6 @@ module RorVsWild
79
74
 
80
75
  ((Time.now.to_f - queue_time_from_header) * 1000).round if queue_time_from_header
81
76
  end
82
-
83
- def rails_engine_location
84
- @rails_engine_location = ::Rails::Engine.instance_method(:call).source_location
85
- end
86
77
  end
87
78
  end
88
79
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RorVsWild
4
- VERSION = "1.10.1"
4
+ VERSION = "1.11.0"
5
5
  end
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.10.1
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Bernard
@@ -55,10 +55,11 @@ files:
55
55
  - lib/rorvswild/plugin/delayed_job.rb
56
56
  - lib/rorvswild/plugin/elasticsearch.rb
57
57
  - lib/rorvswild/plugin/faktory.rb
58
- - lib/rorvswild/plugin/middleware.rb
59
58
  - lib/rorvswild/plugin/mongo.rb
60
59
  - lib/rorvswild/plugin/net_http.rb
60
+ - lib/rorvswild/plugin/rack.rb
61
61
  - lib/rorvswild/plugin/rails_cache.rb
62
+ - lib/rorvswild/plugin/rails_engine.rb
62
63
  - lib/rorvswild/plugin/rails_error.rb
63
64
  - lib/rorvswild/plugin/redis.rb
64
65
  - lib/rorvswild/plugin/resque.rb
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
89
  - !ruby/object:Gem::Version
89
90
  version: '0'
90
91
  requirements: []
91
- rubygems_version: 3.6.9
92
+ rubygems_version: 4.0.3
92
93
  specification_version: 4
93
94
  summary: Ruby on Rails applications monitoring
94
95
  test_files: []