rails-server-monitor 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +7 -0
  5. data/app/components/rails_server_monitor/leftbar_component.html.erb +20 -0
  6. data/app/components/rails_server_monitor/leftbar_component.rb +18 -0
  7. data/app/components/rails_server_monitor/server_table_row.html.erb +6 -0
  8. data/app/components/rails_server_monitor/server_table_row.rb +11 -0
  9. data/app/components/rails_server_monitor/warnings/high_cpu_usage_component.html.erb +18 -0
  10. data/app/components/rails_server_monitor/warnings/high_cpu_usage_component.rb +24 -0
  11. data/app/components/rails_server_monitor/warnings/low_disk_space_component.html.erb +17 -0
  12. data/app/components/rails_server_monitor/warnings/low_disk_space_component.rb +28 -0
  13. data/app/components/rails_server_monitor/warnings/low_memory_component.html.erb +17 -0
  14. data/app/components/rails_server_monitor/warnings/low_memory_component.rb +28 -0
  15. data/app/components/rails_server_monitor/warnings/warning_component.html.erb +13 -0
  16. data/app/components/rails_server_monitor/warnings/warning_component.rb +14 -0
  17. data/app/controllers/rails_server_monitor/application_controller.rb +6 -0
  18. data/app/controllers/rails_server_monitor/home_controller.rb +9 -0
  19. data/app/controllers/rails_server_monitor/servers_controller.rb +22 -0
  20. data/app/controllers/rails_server_monitor/snapshots_controller.rb +21 -0
  21. data/app/helpers/rails_server_monitor/application_helper.rb +29 -0
  22. data/app/javascript/controllers/index.js +9 -0
  23. data/app/javascript/packs/rails-server-application.js +17 -0
  24. data/app/javascript/stylesheets/main.scss +1 -0
  25. data/app/javascript/stylesheets/tailwind.scss +3 -0
  26. data/app/middlewares/rails_server_monitor/rack_middleware.rb +44 -0
  27. data/app/middlewares/rails_server_monitor/sidekiq_middleware.rb +29 -0
  28. data/app/models/rails_server_monitor/application_record.rb +7 -0
  29. data/app/models/rails_server_monitor/server.rb +27 -0
  30. data/app/models/rails_server_monitor/server_group.rb +10 -0
  31. data/app/models/rails_server_monitor/server_snapshot.rb +12 -0
  32. data/app/services/rails_server_monitor/chart_for_server.rb +51 -0
  33. data/app/services/rails_server_monitor/cleanup.rb +14 -0
  34. data/app/services/rails_server_monitor/server_setup.rb +90 -0
  35. data/app/services/rails_server_monitor/take_snapshot.rb +85 -0
  36. data/app/views/layouts/rails_server_monitor/application.html.erb +25 -0
  37. data/app/views/layouts/rails_server_monitor/application_record.rb +7 -0
  38. data/app/views/rails_server_monitor/home/index.html.erb +18 -0
  39. data/app/views/rails_server_monitor/servers/show.html.erb +133 -0
  40. data/app/views/rails_server_monitor/snapshots/show.html.erb +18 -0
  41. data/config/routes.rb +8 -0
  42. data/config/webpack/base.js +3 -0
  43. data/config/webpack/development.js +23 -0
  44. data/config/webpack/production.js +5 -0
  45. data/config/webpack/test.js +5 -0
  46. data/config/webpacker.yml +92 -0
  47. data/lib/generators/rails_server_monitor/install_generator.rb +20 -0
  48. data/lib/generators/rails_server_monitor/templates/install.rb.tt +29 -0
  49. data/lib/rails/server/monitor/engine.rb +3 -0
  50. data/lib/rails_server_monitor.rb +35 -0
  51. data/lib/rails_server_monitor/configuration.rb +41 -0
  52. data/lib/rails_server_monitor/engine.rb +12 -0
  53. data/lib/rails_server_monitor/version.rb +5 -0
  54. data/lib/tasks/rails_server_monitor_tasks.rake +24 -0
  55. metadata +292 -0
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class SidekiqMiddleware
5
+ def call(worker, *opts)
6
+ return if ignore_worker?(worker)
7
+
8
+ server = RailsServerMonitor::ServerSetup.new.call
9
+ snapshot = RailsServerMonitor::TakeSnapshot.new(server)
10
+
11
+ if snapshot.can_take_snapshot?
12
+ snapshot.call
13
+
14
+ RailsServerMonitor::Cleanup.new.call
15
+ end
16
+ end
17
+
18
+ def ignore_worker?(worker)
19
+ return false if config.ignore_workers.blank?
20
+ klass_name = worker.class.name
21
+
22
+ config.ignore_workers.include?(klass_name)
23
+ end
24
+
25
+ def config
26
+ RailsServerMonitor.config
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class Server < ApplicationRecord
5
+ self.table_name = "rails_server_monitor_servers"
6
+ store :system_information, accessors: %i(
7
+ system_os
8
+ system_os_language
9
+ system_os_timezone
10
+ system_kernel_version
11
+ system_cpu_name
12
+ system_cpu_cores
13
+ system_cpu_frequency
14
+ system_ram_available_in_mb
15
+ system_hdd_available_in_gb
16
+ ), coder: JSON
17
+
18
+ belongs_to :group, class_name: "RailsServerMonitor::ServerGroup", counter_cache: true, optional: true
19
+ has_many :server_snapshots, class_name: "RailsServerMonitor::ServerSnapshot",
20
+ foreign_key: :rails_server_monitor_server_id,
21
+ dependent: :delete_all
22
+
23
+ def display_name
24
+ @display_name ||= custom_name.present? ? custom_name : hostname
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class ServerGroup < ApplicationRecord
5
+ self.table_name = "rails_server_monitor_server_groups"
6
+
7
+ has_many :servers, class_name: "RailsServerMonitor::Server", dependent: :nullify
8
+ validates :name, presence: true, uniqueness: true
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class ServerSnapshot < ApplicationRecord
5
+ self.table_name = "rails_server_monitor_server_snapshots"
6
+
7
+ belongs_to :rails_server_monitor_server, class_name: "RailsServerMonitor::Server"
8
+
9
+ serialize :ram_stats, JSON
10
+ serialize :hdd_stats, JSON
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class ChartForServer
5
+ attr_reader :server, :timeline
6
+ def initialize(server, timeline: :today)
7
+ @server = server
8
+ @timeline = timeline
9
+ end
10
+
11
+ def render_chart
12
+ [
13
+ {
14
+ name: "% CPU usage", data: fill_hash_for_attribute(:cpu_usage_percentage),
15
+ },
16
+ {
17
+ name: "% RAM usage", data: fill_hash_for_attribute(:ram_usage_percentage)
18
+ },
19
+ {
20
+ name: "% HDD usage", data: fill_hash_for_attribute(:hdd_usage_percentage)
21
+ }
22
+ ]
23
+ end
24
+
25
+ def today?
26
+ timeline == :today
27
+ end
28
+
29
+
30
+ def last_record
31
+ @last_record = scope.last
32
+ end
33
+
34
+ def scope
35
+ return @scope if defined? @scope
36
+ query = server.server_snapshots.order(id: :asc)
37
+ if today?
38
+ query = query.where("created_at > ?", 1.day.ago)
39
+ end
40
+ @scope = query.to_a
41
+ end
42
+
43
+ def fill_hash_for_attribute(attr)
44
+ {}.tap do |h|
45
+ scope.each do |snapshot|
46
+ h[snapshot.created_at] = snapshot.send(attr)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class Cleanup
5
+ def call
6
+ RailsServerMonitor::ServerSnapshot.where("created_at < ?", Time.zone.now - config.cleanup_snapshots_after)
7
+ .delete_all
8
+ end
9
+
10
+ def config
11
+ RailsServerMonitor.config
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class ServerSetup
5
+ attr_reader :server
6
+
7
+ def initialize
8
+ @server = RailsServerMonitor::Server.find_or_initialize_by(hostname: hostname)
9
+ end
10
+
11
+ def call
12
+ server.tap do
13
+ next update_server if server.updated_at.blank?
14
+
15
+ needs_update = (Time.zone.now - server.updated_at) >= config.update_server_interval
16
+ update_server if needs_update
17
+ end
18
+ end
19
+
20
+ private
21
+ def hostname
22
+ @hostname ||= `hostname`.squish
23
+ end
24
+
25
+ def update_server
26
+ server.assign_attributes({
27
+ last_seen_at: Time.zone.now,
28
+ system_os: system_os,
29
+ system_os_language: system_os_language,
30
+ system_os_timezone: system_os_timezone,
31
+ system_kernel_version: system_kernel_version,
32
+ system_cpu_name: system_cpu_name,
33
+ system_cpu_cores: system_cpu_cores,
34
+ system_cpu_frequency: system_cpu_frequency,
35
+ system_ram_available_in_mb: system_ram_available_in_mb,
36
+ system_hdd_available_in_gb: system_hdd_available_in_gb
37
+ })
38
+
39
+ server.save!
40
+ end
41
+
42
+ def system_os
43
+ File.read("/etc/lsb-release") if File.exist?("/etc/lsb-release")
44
+ end
45
+
46
+ def system_os_language
47
+ ENV["LANG"]
48
+ end
49
+
50
+ def system_os_timezone
51
+ File.read("/etc/timezone")
52
+ end
53
+
54
+ def system_kernel_version
55
+ `uname -r`.squish
56
+ end
57
+
58
+ def system_cpu_name
59
+ Sys::CPU.model
60
+ end
61
+
62
+ def system_cpu_cores
63
+ Sys::CPU.num_cpu
64
+ end
65
+
66
+ def system_cpu_frequency
67
+ Sys::CPU.freq
68
+ end
69
+
70
+ def system_ram_available_in_mb
71
+ ram_helper[:total]
72
+ end
73
+
74
+ def system_hdd_available_in_gb
75
+ storage_helper[:total]
76
+ end
77
+
78
+ def config
79
+ RailsServerMonitor.config
80
+ end
81
+
82
+ def storage_helper
83
+ @store ||= Vidibus::Sysinfo.storage.to_h
84
+ end
85
+
86
+ def ram_helper
87
+ @ram_helper ||= Vidibus::Sysinfo.memory.to_h
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class TakeSnapshot
5
+ attr_reader :server
6
+
7
+ def initialize(server)
8
+ @server = server
9
+ end
10
+
11
+ def call
12
+ return unless can_take_snapshot?
13
+ create_snapshot!
14
+ end
15
+
16
+ def can_take_snapshot?
17
+ return @can_take_snapshot if defined? @can_take_snapshot
18
+ latest_snapshot = server.server_snapshots.order(id: :desc).first
19
+ if latest_snapshot.blank?
20
+ return @can_take_snapshot = true
21
+ end
22
+ if (Time.zone.now - latest_snapshot.created_at) >= config.snapshot_server_interval
23
+ return @can_take_snapshot = true
24
+ end
25
+
26
+ @can_take_snapshot = false
27
+ end
28
+
29
+ private
30
+ def create_snapshot!
31
+ RailsServerMonitor::ServerSnapshot.create!(
32
+ cpu_usage_percentage: cpu_usage_percentage,
33
+ ram_usage_percentage: ram_usage_percentage,
34
+ hdd_usage_percentage: hdd_usage_percentage,
35
+ ram_stats: ram_stats,
36
+ hdd_stats: hdd_stats,
37
+ network_stats: network_stats,
38
+ rails_server_monitor_server: server
39
+ )
40
+ end
41
+
42
+ def cpu_usage_percentage
43
+ psm_helper.uw_cpuused.round
44
+ end
45
+
46
+ def ram_usage_percentage
47
+ percentage_off(ram_helper[:total], ram_helper[:used])
48
+ end
49
+
50
+ def hdd_usage_percentage
51
+ percentage_off(storage_helper[:total], storage_helper[:used])
52
+ end
53
+
54
+ def ram_stats
55
+ ram_helper.slice(:used, :free)
56
+ end
57
+
58
+ def hdd_stats
59
+ storage_helper.slice(:used, :free)
60
+ end
61
+
62
+ def network_stats
63
+ end
64
+
65
+ def psm_helper
66
+ RubyStatsPsm
67
+ end
68
+
69
+ def config
70
+ RailsServerMonitor.config
71
+ end
72
+
73
+ def storage_helper
74
+ @store ||= Vidibus::Sysinfo.storage.to_h
75
+ end
76
+
77
+ def ram_helper
78
+ @ram_helper ||= Vidibus::Sysinfo.memory.to_h
79
+ end
80
+
81
+ def percentage_off(total, current)
82
+ ((current / total.to_f) * 100).round
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= @title ? "#{@title} - " : "" %>Rails Server Monitor Engine</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= safe_render_js "rails-server-application", 'data-turbolinks-track': "reload" %>
9
+ <%= safe_render_css "rails-server-application", 'data-turbolinks-track': "reload" %>
10
+ </head>
11
+ <body>
12
+
13
+ <div class="flex">
14
+ <div class="overflow-y-auto fixed top-0 left-0 bottom-0 bg-white w-1/5">
15
+ <%= render RailsServerMonitor::LeftbarComponent.new(ctx: self) %>
16
+ </div>
17
+ <div class="w-1/5 mr-4"></div>
18
+
19
+ <div class="flex-1">
20
+ <%= yield %>
21
+ </div>
22
+ </div>
23
+
24
+ </body>
25
+ </html>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsServerMonitor
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ <div class="p-2">
2
+ <div class="bg-red-300 text-3xl p-2 text-gray-800">
3
+ Warnings
4
+ </div>
5
+
6
+ <div>
7
+ <%= render RailsServerMonitor::Warnings::HighCpuUsageComponent.new(ctx: self) %>
8
+ </div>
9
+
10
+ <div>
11
+ <%= render RailsServerMonitor::Warnings::LowMemoryComponent.new(ctx: self) %>
12
+ </div>
13
+
14
+
15
+ <div>
16
+ <%= render RailsServerMonitor::Warnings::LowDiskSpaceComponent.new(ctx: self) %>
17
+ </div>
18
+ </div>
@@ -0,0 +1,133 @@
1
+ <div class="p-2">
2
+ <div class="text-center text-2xl font-bold">
3
+ <%= @server.display_name %>
4
+ </div>
5
+
6
+
7
+ <div class="flex mt-4">
8
+ <%= content_tag :div, class: "#{@chart.today? ? "w-1/2" : "w-full"}" do %>
9
+ <%= line_chart @chart.render_chart %>
10
+ <% end %>
11
+
12
+ <% if @chart.today? && @chart.last_record.present? %>
13
+ <div class="w-1/2 p-2">
14
+ <div class="mb-2 text-xl">
15
+ Current server stats information:
16
+ </div>
17
+
18
+ <div class="flex">
19
+ <div class="grid grid-cols-2 gap-4 w-1/2">
20
+ <%= render(RailsServerMonitor::ServerTableRow.new(
21
+ title: "CPU Usage",
22
+ value: "#{@chart.last_record.cpu_usage_percentage} %"
23
+ )) %>
24
+
25
+
26
+ <%= render(RailsServerMonitor::ServerTableRow.new(
27
+ title: "Ram Used",
28
+ value: "#{@chart.last_record.ram_stats["used"]} MB"
29
+ )) %>
30
+
31
+ <%= render(RailsServerMonitor::ServerTableRow.new(
32
+ title: "Ram Free",
33
+ value: "#{@chart.last_record.ram_stats["free"]} MB"
34
+ )) %>
35
+ </div>
36
+ <div class="grid grid-cols-2 gap-4 w-1/2">
37
+ <%= render(RailsServerMonitor::ServerTableRow.new(
38
+ title: "HDD Used",
39
+ value: "#{@chart.last_record.hdd_stats["used"]} GB"
40
+ )) %>
41
+
42
+ <%= render(RailsServerMonitor::ServerTableRow.new(
43
+ title: "HDD Free",
44
+ value: "#{@chart.last_record.hdd_stats["free"]} GB"
45
+ )) %>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <% end %>
50
+ </div>
51
+
52
+ <div class="mt-20">
53
+ <div class="mb-2 text-xl">
54
+ Sever information:
55
+ </div>
56
+
57
+ <div class="grid grid-cols-2 gap-4 w-1/2">
58
+ <%= render(RailsServerMonitor::ServerTableRow.new(
59
+ title: "Hostname",
60
+ value: @server.hostname
61
+ )) %>
62
+
63
+ <div class="bg-blue-300 text-gray-800 p-1">
64
+ Custom name:
65
+ </div>
66
+ <div class="p-1">
67
+ <%= @server.custom_name %>
68
+ </div>
69
+ <div class="bg-blue-300 text-gray-800 p-1">
70
+ Custom description:
71
+ </div>
72
+ <div class="p-1">
73
+ <%= @server.custom_description %>
74
+ </div>
75
+ <div class="mb-2 text-xl">
76
+ OS information
77
+ </div>
78
+ <div></div>
79
+
80
+ <div class="bg-blue-300 text-gray-800 p-1">
81
+ Operating system:
82
+ </div>
83
+ <div class="p-1">
84
+ <%= simple_format @server.system_os %>
85
+ </div>
86
+
87
+ <%= render(RailsServerMonitor::ServerTableRow.new(
88
+ title: "Kernel version",
89
+ value: @server.system_kernel_version
90
+ )) %>
91
+
92
+ <%= render(RailsServerMonitor::ServerTableRow.new(
93
+ title: "OS language",
94
+ value: @server.system_os_language
95
+ )) %>
96
+
97
+ <%= render(RailsServerMonitor::ServerTableRow.new(
98
+ title: "OS Time zone",
99
+ value: @server.system_os_timezone
100
+ )) %>
101
+
102
+ <div class="mb-2 text-xl">
103
+ CPU information
104
+ </div>
105
+ <div></div>
106
+
107
+ <%= render(RailsServerMonitor::ServerTableRow.new(
108
+ title: "CPU Model",
109
+ value: @server.system_cpu_name
110
+ )) %>
111
+
112
+ <%= render(RailsServerMonitor::ServerTableRow.new(
113
+ title: "CPU Codes",
114
+ value: @server.system_cpu_cores
115
+ )) %>
116
+
117
+ <%= render(RailsServerMonitor::ServerTableRow.new(
118
+ title: "CPU Frequency",
119
+ value: "#{@server.system_cpu_frequency} Mhz"
120
+ )) %>
121
+
122
+ <%= render(RailsServerMonitor::ServerTableRow.new(
123
+ title: "RAM",
124
+ value: "#{@server.system_ram_available_in_mb} MB"
125
+ )) %>
126
+
127
+ <%= render(RailsServerMonitor::ServerTableRow.new(
128
+ title: "Storage",
129
+ value: "#{@server.system_hdd_available_in_gb} GB"
130
+ )) %>
131
+ </div>
132
+ </div>
133
+ </div>