rorvswild 1.5.14 → 1.5.15

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: 46b5f40b58c450a91d4ccef20ecca01087c6a91ab5914fc15dacf98f759ba2ef
4
- data.tar.gz: '094aaa9bccc0c1ba609407de5f253875ef86a537392cc740d5daea3b35b6b294'
3
+ metadata.gz: 29d23fa806fe2d9547169a35795b4b313bf7510264aba4d0f8f3471ae7acf047
4
+ data.tar.gz: 681d88bef1fb76ede952387ef1d8ffbdf4bfa4cbf08f990f7964624401ff71a9
5
5
  SHA512:
6
- metadata.gz: d3f133b046fe451a3f2614a56db5b4581e74f1679ee1a5678f4e03ad070c1e57c14ae344d59126efe217aedaac9f27b9e09c19501bb5c1a64c395e5199352c74
7
- data.tar.gz: ebf70177f6200fd0f2103e4cd2f2a3fe8378a6a02871c5d66de5299c2228c4906d17c23fc3185b6b0a3f7385abc3b28dd248f6554864ec93bbb21911a5499624
6
+ metadata.gz: e54dba0143bdb8e94677519698857c7ddc62f91ecb0a876ecc9e0e2fb402e4d11055a59f03cca1c2ca5a2e73b82cf5380574d9e3e4c73d1a66e21c7ea54cfe6c
7
+ data.tar.gz: 92d4cb2e15015929ccc609b6b81837fb1a78ea12ebe4538555e0a023266fc852001d1aa17d7e620b50dd6ac3f856cbf08bba1d3cb9e4f24f10333b1faa26064d
data/README.md CHANGED
@@ -218,6 +218,30 @@ In the case you want a custom logger such as Syslog, you can only do it by initi
218
218
  RorVsWild.start(api_key: "API_KEY", logger: Logger::Syslog.new)
219
219
  ```
220
220
 
221
+ #### Server metrics monitoring
222
+
223
+ We are adding server metrics as a beta feature.
224
+ It monitors load average, CPU, memory, swap and disk space.
225
+ For now, only Linux is supported.
226
+ It has to be explicitly enabled with a feature flag :
227
+
228
+ ```yaml
229
+ # config/rorvswild.yml
230
+ production:
231
+ api_key: API_KEY
232
+ features:
233
+ - server_metrics
234
+ ```
235
+
236
+ Here is the equivalent if you prefer initialising RorVsWild manually :
237
+
238
+ ```ruby
239
+ # config/initializers/rorvswild.rb
240
+ RorVsWild.start(api_key: "API_KEY", features: ["server_metrics"])
241
+ ```
242
+
243
+ The data are available in a server tab beside requests and jobs.
244
+
221
245
  ## Contributing
222
246
 
223
247
  1. Fork it ( https://github.com/[my-github-username]/rorvswild/fork )
@@ -26,6 +26,7 @@ module RorVsWild
26
26
 
27
27
  def initialize(config)
28
28
  @config = self.class.default_config.merge(config)
29
+ load_features
29
30
  @client = Client.new(@config)
30
31
  @queue = config[:queue] || Queue.new(client)
31
32
  @locator = RorVsWild::Locator.new
@@ -35,6 +36,12 @@ module RorVsWild
35
36
  cleanup_data
36
37
  end
37
38
 
39
+ def load_features
40
+ features = config[:features] || []
41
+ features.include?("server_metrics")
42
+ require "rorvswild/metrics" if features.include?("server_metrics")
43
+ end
44
+
38
45
  def setup_plugins
39
46
  for name in RorVsWild::Plugin.constants
40
47
  next if config[:ignore_plugins] && config[:ignore_plugins].include?(name.to_s)
@@ -146,6 +153,12 @@ module RorVsWild
146
153
  config[:ignore_jobs].include?(name)
147
154
  end
148
155
 
156
+ def os_description
157
+ @os_description ||= `uname -sr`
158
+ rescue Exception => ex
159
+ @os_description = RbConfig::CONFIG["host_os"]
160
+ end
161
+
149
162
  #######################
150
163
  ### Private methods ###
151
164
  #######################
@@ -199,11 +212,5 @@ module RorVsWild
199
212
  def ignored_exception?(exception)
200
213
  (config[:ignored_exceptions] || config[:ignore_exceptions]).include?(exception.class.to_s)
201
214
  end
202
-
203
- def os_description
204
- @os_description ||= `uname -a`
205
- rescue Exception => ex
206
- @os_description = RUBY_PLATFORM
207
- end
208
215
  end
209
216
  end
@@ -0,0 +1,31 @@
1
+ module RorVsWild
2
+ class Metrics
3
+ class Cpu
4
+ attr_reader :user, :system, :idle, :waiting, :stolen
5
+ attr_reader :load_average, :count
6
+
7
+ 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
15
+ end
16
+ if uptime = execute(:uptime)
17
+ @load_average = uptime.split[-3].to_f
18
+ end
19
+ if nproc = execute(:nproc)
20
+ @count = nproc.to_i
21
+ end
22
+ end
23
+
24
+ def execute(command)
25
+ `#{command}`
26
+ rescue => ex
27
+ nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,57 @@
1
+ module RorVsWild
2
+ class Metrics
3
+ class Memory
4
+ attr_reader :ram_total, :ram_free, :ram_available, :ram_buffers, :ram_cached
5
+ attr_reader :swap_total, :swap_free
6
+ attr_reader :storage_total, :storage_used
7
+
8
+ def ram_used
9
+ ram_total - ram_available
10
+ end
11
+
12
+ def swap_used
13
+ swap_total - swap_free
14
+ end
15
+
16
+ PROC_MEMINFO = "/proc/meminfo".freeze
17
+ MEM_TOTAL = "MemTotal" # Total usable RAM (i.e., physical RAM minus a few reserved bits and the kernel binary code).
18
+ MEM_FREE = "MemFree" # The sum of LowFree+HighFree.
19
+ MEM_AVAILABLE = "MemAvailable" # An estimate of how much memory is available for starting new applications, without swapping.
20
+ BUFFERS = "Buffers" # Relatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so).
21
+ CACHED = "Cached" # In-memory cache for files read from the disk (the page cache). Doesn't include SwapCached.
22
+ SWAP_TOTAL = "SwapTotal" # Total amount of swap space available.
23
+ SWAP_FREE = "SwapFree" # Amount of swap space that is currently unused.
24
+
25
+ def update
26
+ info = read_meminfo
27
+ @ram_total = convert_to_bytes(info[MEM_TOTAL])
28
+ @ram_free = convert_to_bytes(info[MEM_FREE])
29
+ @ram_available = convert_to_bytes(info[MEM_AVAILABLE])
30
+ @ram_buffers = convert_to_bytes(info[BUFFERS])
31
+ @ram_cached = convert_to_bytes(info[CACHED])
32
+ @swap_total = convert_to_bytes(info[SWAP_TOTAL])
33
+ @swap_free = convert_to_bytes(info[SWAP_FREE])
34
+ end
35
+
36
+ private
37
+
38
+ def units
39
+ @units ||= {"kb" => 1000, "mb" => 1000 * 1000, "gb" => 1000 * 1000 * 1000}.freeze
40
+ end
41
+
42
+ def read_meminfo
43
+ return unless File.readable?(PROC_MEMINFO)
44
+ File.read(PROC_MEMINFO).split("\n").reduce({}) do |hash, line|
45
+ name, value = line.split(":")
46
+ hash[name] = value.strip
47
+ hash
48
+ end
49
+ end
50
+
51
+ def convert_to_bytes(string)
52
+ value, unit = string.split
53
+ value.to_i * units[unit.downcase]
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,17 @@
1
+ module RorVsWild
2
+ class Metrics
3
+ class Storage
4
+ attr_reader :used, :free
5
+
6
+ def update
7
+ array = `df -k | grep " /$"`.split
8
+ @used = array[2].to_i * 1000
9
+ @free = array[3].to_i * 1000
10
+ end
11
+
12
+ def total
13
+ used + free
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ module RorVsWild
2
+ class Metrics
3
+ UPDATE_INTERVAL_MS = 60_000 # One metric every minute
4
+
5
+ attr_reader :cpu, :memory, :storage, :updated_at
6
+
7
+ def initialize
8
+ @cpu = RorVsWild::Metrics::Cpu.new
9
+ @memory = RorVsWild::Metrics::Memory.new
10
+ @storage = RorVsWild::Metrics::Storage.new
11
+ end
12
+
13
+ def update
14
+ if staled?
15
+ cpu.update
16
+ memory.update
17
+ storage.update
18
+ @updated_at = RorVsWild.clock_milliseconds
19
+ end
20
+ end
21
+
22
+ def staled?
23
+ !updated_at || RorVsWild.clock_milliseconds - updated_at > UPDATE_INTERVAL_MS
24
+ end
25
+
26
+ def to_h
27
+ {
28
+ hostname: Socket.gethostname,
29
+ os: RorVsWild.agent.os_description,
30
+ cpu_user: cpu.user,
31
+ cpu_system: cpu.system,
32
+ cpu_idle: cpu.idle,
33
+ cpu_waiting: cpu.waiting,
34
+ cpu_stolen: cpu.stolen,
35
+ cpu_count: cpu.count,
36
+ load_average: cpu.load_average,
37
+ ram_total: memory.ram_total,
38
+ ram_free: memory.ram_free,
39
+ ram_used: memory.ram_used,
40
+ ram_cached: memory.ram_cached,
41
+ swap_total: memory.swap_total,
42
+ swap_used: memory.swap_used,
43
+ swap_free: memory.swap_free,
44
+ storage_total: storage.total,
45
+ storage_used: storage.used,
46
+ storage_free: storage.free,
47
+ }
48
+ end
49
+ end
50
+ end
51
+
52
+ require "rorvswild/metrics/cpu"
53
+ require "rorvswild/metrics/memory"
54
+ require "rorvswild/metrics/storage"
@@ -1,6 +1,6 @@
1
1
  module RorVsWild
2
2
  class Queue
3
- SLEEP_TIME = 10
3
+ SLEEP_TIME = 30
4
4
  FLUSH_TRESHOLD = 10
5
5
 
6
6
  attr_reader :mutex, :thread, :client
@@ -11,6 +11,7 @@ module RorVsWild
11
11
  @requests = []
12
12
  @client = client
13
13
  @mutex = Mutex.new
14
+ @metrics = RorVsWild::Metrics.new if defined?(Metrics)
14
15
  Kernel.at_exit { flush }
15
16
  end
16
17
 
@@ -50,6 +51,10 @@ module RorVsWild
50
51
  result
51
52
  end
52
53
 
54
+ def pull_server_metrics
55
+ @metrics && @metrics.update && @metrics.to_h
56
+ end
57
+
53
58
  def flush_indefinetely
54
59
  sleep(SLEEP_TIME) and flush while true
55
60
  rescue Exception => ex
@@ -60,6 +65,7 @@ module RorVsWild
60
65
  def flush
61
66
  data = pull_jobs and client.post("/jobs", jobs: data)
62
67
  data = pull_requests and client.post("/requests", requests: data)
68
+ data = pull_server_metrics and client.post("/metrics", metrics: data)
63
69
  end
64
70
 
65
71
  def start_thread
@@ -1,3 +1,3 @@
1
1
  module RorVsWild
2
- VERSION = "1.5.14".freeze
2
+ VERSION = "1.5.15".freeze
3
3
  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.5.14
4
+ version: 1.5.15
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: 2022-07-15 00:00:00.000000000 Z
12
+ date: 2022-08-17 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Performances and errors insights for rails developers.
15
15
  email:
@@ -40,6 +40,10 @@ files:
40
40
  - lib/rorvswild/local/stylesheet/local.css
41
41
  - lib/rorvswild/local/stylesheet/vendor/prism.css
42
42
  - lib/rorvswild/locator.rb
43
+ - lib/rorvswild/metrics.rb
44
+ - lib/rorvswild/metrics/cpu.rb
45
+ - lib/rorvswild/metrics/memory.rb
46
+ - lib/rorvswild/metrics/storage.rb
43
47
  - lib/rorvswild/plugin/action_controller.rb
44
48
  - lib/rorvswild/plugin/action_mailer.rb
45
49
  - lib/rorvswild/plugin/action_view.rb