rorvswild 1.5.16 → 1.6.0

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: ffb6ec6265892f727afe8fe18df63993e111da43c2e9cace51a3836c478988ca
4
- data.tar.gz: e13d2690d2b9a9cfd771542092e22d88759f8cf554d2480e18edc8277f204a1d
3
+ metadata.gz: b40a18c6bc14739968aabfda67d1ce3b68fbd582ef16b66bc35e636ab1cc4137
4
+ data.tar.gz: d90c55f88561d249a723de427ce522e27133cbf2fed8c68639e029b0a7f2a6f1
5
5
  SHA512:
6
- metadata.gz: 85df854f496092f2438769c82a6d1ab568743f47a0d684d9db564289cd8b022412e0cf9ec9629cfb5652a1666f5ec15c054f4ce6dba3da2af067141d4343a9c8
7
- data.tar.gz: 736abc9c08a7970086daabc8c29c2272745a4cc37df53fe90362000fbcdbe61d4e2272f1b9db9d01a04e912bcc1b34f81281ce025ce13d75142fb6d35c87f2b7
6
+ metadata.gz: 5ecb2843e5cf8d0556a4b412011d5facb3fdc9a936ab19836758acf3d0fb7de90ccccdad7cb4f599fc3fe9f1bbb39d112b3674a43aec1d1313d5264a643ea58a
7
+ data.tar.gz: e4bcb64980a094b6a4743c24d35452fc86fe53f347286272129103a321ac34e15e4ebd3fbb6d7fba24f7a77cc7b920b6b9ce626328baf91a671cb9e3382b09e4
@@ -34,12 +34,12 @@ module RorVsWild
34
34
  RorVsWild.logger.debug("Start RorVsWild #{RorVsWild::VERSION}")
35
35
  setup_plugins
36
36
  cleanup_data
37
+ send_deployment
37
38
  end
38
39
 
39
40
  def load_features
40
41
  features = config[:features] || []
41
- features.include?("server_metrics")
42
- require "rorvswild/metrics" if features.include?("server_metrics")
42
+ RorVsWild.logger.info("Server metrics are now monitored enabled by default") if features.include?("server_metrics")
43
43
  end
44
44
 
45
45
  def setup_plugins
@@ -85,7 +85,7 @@ module RorVsWild
85
85
  raise
86
86
  ensure
87
87
  current_data[:runtime] = RorVsWild.clock_milliseconds - current_data[:started_at]
88
- post_job
88
+ queue_job
89
89
  end
90
90
  end
91
91
 
@@ -96,7 +96,7 @@ module RorVsWild
96
96
  def stop_request
97
97
  return unless current_data
98
98
  current_data[:runtime] = RorVsWild.clock_milliseconds - current_data[:started_at]
99
- post_request
99
+ queue_request
100
100
  end
101
101
 
102
102
  def catch_error(extra_details = nil, &block)
@@ -109,7 +109,7 @@ module RorVsWild
109
109
  end
110
110
 
111
111
  def record_error(exception, extra_details = nil)
112
- post_error(exception_to_hash(exception, extra_details))
112
+ send_error(exception_to_hash(exception, extra_details))
113
113
  end
114
114
 
115
115
  def push_exception(exception, options = nil)
@@ -153,21 +153,8 @@ module RorVsWild
153
153
  config[:ignore_jobs].include?(name)
154
154
  end
155
155
 
156
- def os_description
157
- @os_description ||= `uname -sr`
158
- rescue Exception => ex
159
- @os_description = RbConfig::CONFIG["host_os"]
160
- end
161
-
162
- def hostname
163
- if gae_instance = ENV["GAE_INSTANCE"] || ENV["CLOUD_RUN_EXECUTION"]
164
- gae_instance
165
- elsif dyno = ENV["DYNO"] # Heroku
166
- dyno.start_with?("run.") ? "run.*" :
167
- dyno.start_with?("release.") ? "release.*" : dyno
168
- else
169
- Socket.gethostname
170
- end
156
+ def send_deployment
157
+ client.post("/deployments", deployment: Deployment.to_h)
171
158
  end
172
159
 
173
160
  #######################
@@ -177,7 +164,12 @@ module RorVsWild
177
164
  private
178
165
 
179
166
  def initialize_data
180
- Thread.current[:rorvswild_data] = {sections: [], section_stack: [], started_at: RorVsWild.clock_milliseconds}
167
+ Thread.current[:rorvswild_data] = {
168
+ sections: [],
169
+ section_stack: [],
170
+ environment: Host.to_h,
171
+ started_at: RorVsWild.clock_milliseconds,
172
+ }
181
173
  end
182
174
 
183
175
  def cleanup_data
@@ -186,15 +178,15 @@ module RorVsWild
186
178
  result
187
179
  end
188
180
 
189
- def post_request
181
+ def queue_request
190
182
  (data = cleanup_data) && data[:name] && queue.push_request(data)
191
183
  end
192
184
 
193
- def post_job
185
+ def queue_job
194
186
  queue.push_job(cleanup_data)
195
187
  end
196
188
 
197
- def post_error(hash)
189
+ def send_error(hash)
198
190
  client.post_async("/errors".freeze, error: hash)
199
191
  end
200
192
 
@@ -208,15 +200,7 @@ module RorVsWild
208
200
  backtrace: exception.backtrace || ["No backtrace"],
209
201
  exception: exception.class.to_s,
210
202
  extra_details: context,
211
- environment: {
212
- os: os_description,
213
- user: Etc.getlogin,
214
- host: Socket.gethostname,
215
- ruby: RUBY_DESCRIPTION,
216
- pid: Process.pid,
217
- cwd: Dir.pwd,
218
- lib_paths: locator.lib_paths,
219
- },
203
+ environment: Host.to_h,
220
204
  }
221
205
  end
222
206
 
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RorVsWild
4
+ module Deployment
5
+ def self.revision
6
+ read_once && @revision
7
+ end
8
+
9
+ def self.description
10
+ read_once && @description
11
+ end
12
+
13
+ def self.author
14
+ read_once && @author
15
+ end
16
+
17
+ def self.email
18
+ read_once && @email
19
+ end
20
+
21
+ def self.ruby
22
+ RUBY_VERSION
23
+ end
24
+
25
+ def self.rails
26
+ Rails.version if defined?(Rails)
27
+ end
28
+
29
+ def self.rorvswild
30
+ RorVsWild::VERSION
31
+ end
32
+
33
+ def self.to_h
34
+ @to_h ||= {revision: revision, description: description, author: author, email: email, ruby: ruby, rails: rails, rorvswild: rorvswild}.compact
35
+ end
36
+
37
+ def self.read
38
+ read_from_heroku || read_from_scalingo || read_from_git || read_from_capistrano
39
+ end
40
+
41
+ def self.read_once
42
+ @already_read || read
43
+ @already_read = true
44
+ end
45
+
46
+ private
47
+
48
+ def self.read_from_heroku
49
+ return unless ENV["HEROKU_SLUG_COMMIT"]
50
+ @revision = ENV["HEROKU_SLUG_COMMIT"]
51
+ @description = ENV["HEROKU_SLUG_DESCRIPTION"]
52
+ end
53
+
54
+ def self.read_from_scalingo
55
+ return unless ENV["SOURCE_VERSION"]
56
+ @revision = ENV["SOURCE_VERSION"]
57
+ end
58
+
59
+ def self.read_from_git
60
+ @revision = normalize_string(`git rev-parse HEAD`) rescue nil
61
+ return unless @revision
62
+ lines = `git log -1 --pretty=%an%n%ae%n%B`.lines rescue nil
63
+ return unless lines
64
+ @author = normalize_string(lines[0])
65
+ @email = normalize_string(lines[1])
66
+ @description = lines[2..-1] && normalize_string(lines[2..-1].join)
67
+ @revision
68
+ end
69
+
70
+ def self.read_from_capistrano
71
+ return unless File.readable?("REVISION")
72
+ return unless @revision = File.read("REVISION")
73
+ lines = `git --git-dir ../../repo log --format=%an%n%ae%n%B -n 1 #{@revision}`.lines rescue nil
74
+ return unless lines
75
+ @author = normalize_string(lines[0])
76
+ @email = normalize_string(lines[1])
77
+ @description = lines[2..-1] && normalize_string(lines[2..-1].join)
78
+ @revision
79
+ end
80
+
81
+ def self.normalize_string(string)
82
+ if string
83
+ string = string.strip
84
+ string.empty? ? nil : string
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RorVsWild
4
+ module Host
5
+ def self.os
6
+ @os_description ||= `uname -sr`.strip
7
+ rescue Exception => ex
8
+ @os_description = RbConfig::CONFIG["host_os"]
9
+ end
10
+
11
+ def self.user
12
+ Etc.getlogin
13
+ end
14
+
15
+ def self.ruby
16
+ RUBY_DESCRIPTION
17
+ end
18
+
19
+ def self.rails
20
+ Rails.version if defined?(Rails)
21
+ end
22
+
23
+ def self.name
24
+ if gae_instance = ENV["GAE_INSTANCE"] || ENV["CLOUD_RUN_EXECUTION"]
25
+ gae_instance
26
+ elsif dyno = ENV["DYNO"] # Heroku
27
+ dyno.start_with?("run.") ? "run.*" :
28
+ dyno.start_with?("release.") ? "release.*" : dyno
29
+ else
30
+ Socket.gethostname
31
+ end
32
+ end
33
+
34
+ def self.pid
35
+ Process.pid
36
+ end
37
+
38
+ def self.cwd
39
+ Dir.pwd
40
+ end
41
+
42
+ def self.revision
43
+ Deployment.revision
44
+ end
45
+
46
+ def self.revision_description
47
+ Deployment.description
48
+ end
49
+
50
+ def self.to_h
51
+ @to_h ||= {os: os, user: user, host: name, ruby: ruby, rails: rails, pid: pid, cwd: cwd, revision: revision}.compact
52
+ end
53
+ end
54
+ end
@@ -77,9 +77,9 @@ RorVsWild.Local.prototype.goToHistory = function(event) {
77
77
  this.render()
78
78
  }
79
79
 
80
- RorVsWild.Local.prototype.containerStyle = function() {
80
+ RorVsWild.Local.prototype.containerClass = function() {
81
81
  if (!this.active)
82
- return 'display: none !important;'
82
+ return "is-hidden"
83
83
  }
84
84
 
85
85
  RorVsWild.Local.kindToLanguage = function(kind) {
@@ -4,7 +4,7 @@
4
4
  </div>
5
5
 
6
6
  <script type="x-tmpl-mustache" data-partial="RorVsWild.Local">
7
- <div id="rorvswild-local-requests" class="rorvswild-local-panel" style="{{containerStyle}}">
7
+ <div id="rorvswild-local-requests" class="rorvswild-local-panel {{containerClass}}">
8
8
 
9
9
  <div class="rorvswild-local-panel__header">
10
10
  <a href="https://www.rorvswild.com" class="rorvswild-local-panel__logo">
@@ -76,6 +76,10 @@
76
76
  flex-direction: column !important;
77
77
  }
78
78
 
79
+ .rorvswild-local-panel.is-hidden {
80
+ display: none !important;
81
+ }
82
+
79
83
  .rorvswild-local-panel * {
80
84
  font-family: inherit !important;
81
85
  font-size: inherit !important;
@@ -1,30 +1,61 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RorVsWild
2
4
  class Metrics
3
5
  class Cpu
4
6
  attr_reader :user, :system, :idle, :waiting, :stolen
5
7
  attr_reader :load_average, :count
6
8
 
9
+ def initialize
10
+ @old_stat = Stat.read
11
+ end
12
+
7
13
  def update
8
- if vmstat = execute(:vmstat)
9
- vmstat = vmstat.split("\n").last.split
10
- @user = vmstat[12].to_i
11
- @system = vmstat[13].to_i
12
- @idle = vmstat[14].to_i
13
- @waiting = vmstat[15].to_i
14
- @stolen = vmstat[16].to_i
14
+ if @old_stat && (new_stat = Stat.read)
15
+ if (total = new_stat.total - @old_stat.total) > 0
16
+ @user = (new_stat.user - @old_stat.user) * 100 / total
17
+ @system = (new_stat.system - @old_stat.system) * 100 / total
18
+ @idle = (new_stat.idle - @old_stat.idle) * 100 / total
19
+ @waiting = (new_stat.iowait - @old_stat.iowait) * 100 / total
20
+ @stolen = (new_stat.steal - @old_stat.steal) * 100 / total
21
+ @old_stat = new_stat
22
+ end
15
23
  end
16
- if uptime = execute(:uptime)
17
- @load_average = uptime.split[-3].to_f
24
+ @load_average = File.read("/proc/loadavg").to_f if File.readable?("/proc/loadavg")
25
+ @count = `nproc`.to_i rescue nil
26
+ end
27
+
28
+ class Stat
29
+ attr_reader :user, :nice, :system, :idle, :iowait, :irq, :softirq, :steal, :guest, :guest_nice, :total
30
+
31
+ def initialize(user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice)
32
+ @user = user
33
+ @nice = nice
34
+ @system = system
35
+ @idle = idle
36
+ @iowait = iowait
37
+ @irq = irq
38
+ @softirq = softirq
39
+ @steal = steal
40
+ @guest = guest
41
+ @guest_nice = guest_nice
42
+ @total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice
18
43
  end
19
- if nproc = execute(:nproc)
20
- @count = nproc.to_i
44
+
45
+ def self.parse(string)
46
+ for row in string.lines
47
+ if row.start_with?("cpu ")
48
+ array = row.split[1..-1].map(&:to_i)[0,10]
49
+ array.fill(0, array.size, 10 - array.size) if array.size < 10
50
+ return new(*array)
51
+ end
52
+ end
53
+ nil
21
54
  end
22
- end
23
55
 
24
- def execute(command)
25
- `#{command}`
26
- rescue => ex
27
- nil
56
+ def self.read
57
+ parse(File.read("/proc/stat")) if File.readable?("/proc/stat")
58
+ end
28
59
  end
29
60
  end
30
61
  end
@@ -23,7 +23,7 @@ module RorVsWild
23
23
  SWAP_FREE = "SwapFree" # Amount of swap space that is currently unused.
24
24
 
25
25
  def update
26
- info = read_meminfo
26
+ return unless info = read_meminfo
27
27
  @ram_total = convert_to_bytes(info[MEM_TOTAL])
28
28
  @ram_free = convert_to_bytes(info[MEM_FREE])
29
29
  @ram_available = convert_to_bytes(info[MEM_AVAILABLE])
@@ -1,7 +1,5 @@
1
1
  module RorVsWild
2
2
  class Metrics
3
- UPDATE_INTERVAL_MS = 60_000 # One metric every minute
4
-
5
3
  attr_reader :cpu, :memory, :storage, :updated_at
6
4
 
7
5
  def initialize
@@ -11,22 +9,23 @@ module RorVsWild
11
9
  end
12
10
 
13
11
  def update
14
- if staled?
15
- cpu.update
16
- memory.update
17
- storage.update
18
- @updated_at = RorVsWild.clock_milliseconds
19
- end
12
+ cpu.update
13
+ memory.update
14
+ storage.update
20
15
  end
21
16
 
22
- def staled?
23
- !updated_at || RorVsWild.clock_milliseconds - updated_at > UPDATE_INTERVAL_MS
17
+ def update_every_minute
18
+ return unless Host.os.include?("Linux")
19
+ if !@updated_at || @updated_at.min != Time.now.min
20
+ @updated_at = Time.now
21
+ update
22
+ end
24
23
  end
25
24
 
26
25
  def to_h
27
26
  {
28
- hostname: RorVsWild.agent.hostname,
29
- os: RorVsWild.agent.os_description,
27
+ hostname: Host.name,
28
+ os: Host.os,
30
29
  cpu_user: cpu.user,
31
30
  cpu_system: cpu.system,
32
31
  cpu_idle: cpu.idle,
@@ -19,7 +19,7 @@ module RorVsWild
19
19
  end
20
20
 
21
21
  def request_with_rorvswild(req, body = nil, &block)
22
- return request_without_rorvswild(req, body, &block) if request_called_twice?
22
+ return request_without_rorvswild(req, body, &block) if !RorVsWild.agent || request_called_twice?
23
23
  RorVsWild.agent.measure_section("#{req.method} #{address}", kind: HTTP) do
24
24
  request_without_rorvswild(req, body, &block)
25
25
  end
@@ -1,31 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RorVsWild
2
4
  module Plugin
3
5
  class Redis
4
6
  def self.setup
5
7
  return if !defined?(::Redis)
6
- return if ::Redis::Client.method_defined?(:process_without_rorvswild)
7
- ::Redis::Client.class_eval do
8
- alias_method :process_without_rorvswild, :process
8
+ if ::Redis::Client.method_defined?(:process)
9
+ ::Redis::Client.prepend(V4)
10
+ else
11
+ ::Redis.prepend(V5)
12
+ end
13
+ end
9
14
 
10
- def process(commands, &block)
11
- string = RorVsWild::Plugin::Redis.commands_to_string(commands)
12
- appendable = RorVsWild::Plugin::Redis.appendable_commands?(commands)
13
- RorVsWild.agent.measure_section(string, appendable_command: appendable, kind: "redis".freeze) do
14
- process_without_rorvswild(commands, &block)
15
- end
15
+ module V4
16
+ def process(commands, &block)
17
+ string = commands.map(&:first).join("\n")
18
+ appendable = APPENDABLE_COMMANDS.include?(commands[0][0])
19
+ RorVsWild.agent.measure_section(string, appendable_command: appendable, kind: "redis") do
20
+ super(commands, &block)
16
21
  end
17
22
  end
18
23
  end
19
24
 
20
- def self.commands_to_string(commands)
21
- commands.map { |c| c[0] }.join("\n".freeze)
22
- end
25
+ module V5
26
+ def send_command(command, &block)
27
+ appendable = APPENDABLE_COMMANDS.include?(command)
28
+ RorVsWild.agent.measure_section(command[0], appendable_command: appendable, kind: "redis") do
29
+ super(command, &block)
30
+ end
31
+ end
23
32
 
24
- APPENDABLE_COMMANDS = [:auth, :select]
33
+ def pipelined
34
+ RorVsWild.agent.measure_section("pipeline", kind: "redis") { super }
35
+ end
25
36
 
26
- def self.appendable_commands?(commands)
27
- commands.size == 1 && APPENDABLE_COMMANDS.include?(commands.first.first)
37
+ def multi
38
+ RorVsWild.agent.measure_section("multi", kind: "redis") { super }
39
+ end
28
40
  end
41
+
42
+ APPENDABLE_COMMANDS = [:auth, :select]
29
43
  end
30
44
  end
31
45
  end
@@ -1,6 +1,6 @@
1
1
  module RorVsWild
2
2
  class Queue
3
- SLEEP_TIME = 30
3
+ SLEEP_TIME = 10
4
4
  FLUSH_TRESHOLD = 10
5
5
 
6
6
  attr_reader :mutex, :thread, :client
@@ -52,7 +52,7 @@ module RorVsWild
52
52
  end
53
53
 
54
54
  def pull_server_metrics
55
- @metrics && @metrics.update && @metrics.to_h
55
+ @metrics && @metrics.update_every_minute && @metrics.to_h
56
56
  end
57
57
 
58
58
  def flush_indefinetely
@@ -1,3 +1,3 @@
1
1
  module RorVsWild
2
- VERSION = "1.5.16".freeze
2
+ VERSION = "1.6.0".freeze
3
3
  end
data/lib/rorvswild.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  require "rorvswild/version"
2
+ require "rorvswild/host"
3
+ require "rorvswild/metrics"
4
+ require "rorvswild/deployment"
2
5
  require "rorvswild/locator"
3
6
  require "rorvswild/section"
4
7
  require "rorvswild/client"
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rorvswild
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.16
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Bernard
8
8
  - Antoine Marguerie
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-10-03 00:00:00.000000000 Z
12
+ date: 2023-01-27 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Performances and errors insights for rails developers.
15
15
  email:
@@ -27,6 +27,8 @@ files:
27
27
  - lib/rorvswild.rb
28
28
  - lib/rorvswild/agent.rb
29
29
  - lib/rorvswild/client.rb
30
+ - lib/rorvswild/deployment.rb
31
+ - lib/rorvswild/host.rb
30
32
  - lib/rorvswild/installer.rb
31
33
  - lib/rorvswild/local.rb
32
34
  - lib/rorvswild/local/javascript/application.js
@@ -69,7 +71,7 @@ licenses:
69
71
  metadata:
70
72
  source_code_uri: https://github.com/BaseSecrete/rorvswild
71
73
  changelog_uri: https://github.com/BaseSecrete/rorvswild/blob/master/CHANGELOG.md
72
- post_install_message:
74
+ post_install_message:
73
75
  rdoc_options: []
74
76
  require_paths:
75
77
  - lib
@@ -85,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  version: '0'
86
88
  requirements: []
87
89
  rubygems_version: 3.2.22
88
- signing_key:
90
+ signing_key:
89
91
  specification_version: 4
90
92
  summary: Ruby on Rails applications monitoring
91
93
  test_files: []