mission_control-servers 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +68 -10
- data/app/controllers/mission_control/servers/dashboards/cpu_histories_controller.rb +10 -0
- data/app/controllers/mission_control/servers/dashboards/cpu_usages_controller.rb +9 -0
- data/app/controllers/mission_control/servers/dashboards/disk_frees_controller.rb +9 -0
- data/app/controllers/mission_control/servers/dashboards/memory_histories_controller.rb +10 -0
- data/app/controllers/mission_control/servers/dashboards/memory_usages_controller.rb +9 -0
- data/app/controllers/mission_control/servers/dashboards/project_tables_controller.rb +7 -0
- data/app/controllers/mission_control/servers/ingresses_controller.rb +3 -2
- data/app/controllers/mission_control/servers/projects_controller.rb +12 -0
- data/app/controllers/mission_control/servers/scripts_controller.rb +52 -0
- data/app/helpers/mission_control/servers/application_helper.rb +4 -0
- data/app/helpers/mission_control/servers/dashboards/cpu_histories_helper.rb +4 -0
- data/app/helpers/mission_control/servers/dashboards/cpu_usages_helper.rb +4 -0
- data/app/helpers/mission_control/servers/dashboards/disk_frees_helper.rb +4 -0
- data/app/helpers/mission_control/servers/dashboards/memory_histories_helper.rb +4 -0
- data/app/helpers/mission_control/servers/dashboards/memory_usages_helper.rb +4 -0
- data/app/helpers/mission_control/servers/dashboards/project_tables_helper.rb +4 -0
- data/app/javascript/mission_control/servers/controllers/copy_controller.js +14 -0
- data/app/javascript/mission_control/servers/controllers/dialog_controller.js +13 -0
- data/app/javascript/mission_control/servers/controllers/line_chart_controller.js +29 -0
- data/app/javascript/mission_control/servers/controllers/pie_chart_controller.js +32 -0
- data/app/javascript/mission_control/servers/controllers/refresh_controller.js +66 -0
- data/app/models/mission_control/servers/service.rb +47 -0
- data/app/views/mission_control/servers/dashboards/cpu_histories/show.html.erb +15 -0
- data/app/views/mission_control/servers/dashboards/cpu_usages/show.html.erb +18 -0
- data/app/views/mission_control/servers/dashboards/disk_frees/show.html.erb +11 -0
- data/app/views/mission_control/servers/dashboards/memory_histories/show.html.erb +15 -0
- data/app/views/mission_control/servers/dashboards/memory_usages/show.html.erb +18 -0
- data/app/views/mission_control/servers/dashboards/project_tables/show.html.erb +39 -0
- data/app/views/mission_control/servers/projects/_form.html.erb +12 -13
- data/app/views/mission_control/servers/projects/index.html.erb +39 -13
- data/app/views/mission_control/servers/projects/new.html.erb +6 -6
- data/app/views/mission_control/servers/projects/show.html.erb +70 -109
- data/config/routes.rb +9 -0
- data/db/migrate/20240205020304_create_mission_control_servers_projects.rb +1 -1
- data/db/migrate/20240205031009_create_mission_control_servers_services.rb +2 -2
- data/lib/mission_control/servers/configuration.rb +13 -0
- data/lib/mission_control/servers/version.rb +1 -1
- data/lib/mission_control/servers.rb +12 -1
- metadata +27 -3
- data/app/views/mission_control/servers/projects/_project.html.erb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7f4ae5c47c0164182ee1d8ecf4e3745dbb360abeb2d6edf9aaf18a82600c004
|
4
|
+
data.tar.gz: 4762f538171344931546cb95a284fe7bd5bb9f6c804f3b0a42d63b2f2d1df302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97e1618b50e48d513fd32d1fe98c33a84fbf9f9b1b7a3976ee2961b3eb34ffdc95391aee835da1f59cb13925f2938cfdb51d2b42c8ff8b6e26dda375c2727224
|
7
|
+
data.tar.gz: f0479dc129ab3266c591d13d040b0a8d8a6427d88eff466f72c14ddaf1ef9000c94190c8379d972ffca7b96eeb5d9f4f679e82123744b5eba5251893528364a4
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# MissionControl::Servers
|
2
|
-
|
2
|
+
The goal of MissionControl::Servers is to provide a simple monitoring of the resources
|
3
|
+
on your Ruby on Rails application. You can either use this directly on the projects or create a separate Ruby on
|
4
|
+
Rails application to mount this in.
|
3
5
|
|
4
6
|
## Installation
|
5
7
|
Add this line to your application's Gemfile:
|
@@ -9,26 +11,82 @@ bundle add "mission_control-servers"
|
|
9
11
|
bin/rails mission_control_servers:install:migrations
|
10
12
|
```
|
11
13
|
|
14
|
+
Add a mount to your `config/routes.rb`
|
12
15
|
|
13
|
-
|
16
|
+
```ruby
|
17
|
+
mount MissionControl::Servers::Engine => "/mission_control-servers"
|
18
|
+
```
|
19
|
+
|
20
|
+
## Configuration
|
14
21
|
|
15
|
-
|
22
|
+
Within your application, you can make some configuration changes in how the gem operates. Below are the default
|
23
|
+
configuration options. You can override these options by creating an initializer file.
|
16
24
|
|
17
|
-
|
25
|
+
For example, if you're wanting to use MissionControl::Servers in a single project, then there is no need to have
|
26
|
+
the ability to create multiple projects. You can set the `single_project_mode` to true which will hide the ability
|
27
|
+
to create new projects.
|
18
28
|
|
29
|
+
```ruby
|
30
|
+
# config/initializers/mission_control_servers.rb
|
31
|
+
MissionControl::Servers.configure do |config|
|
32
|
+
config.single_project_mode = true
|
33
|
+
end
|
19
34
|
```
|
20
|
-
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
Create a project. Once you create a project, you can easily copy the script specific to that project.
|
39
|
+
|
40
|
+
Install a script which captures:
|
41
|
+
|
42
|
+
- Hostname
|
43
|
+
- CPU Usage
|
44
|
+
- Memory Usage
|
45
|
+
- Free Memory
|
46
|
+
- Free Disk Space
|
47
|
+
|
48
|
+
The data will be retained for 7 days automatically. After 7 days, the data will start truncating itself
|
49
|
+
so that it doesn't take up much disk space within the database.
|
50
|
+
|
51
|
+
## Protecting the Dashboard
|
52
|
+
|
53
|
+
You can protect the dashboard by using a constraint. This will allow you to only allow certain users to access
|
54
|
+
the dashboard. However, the ingress still needs to be accessible by the servers which are being monitored.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
Rails.application.routes.draw do
|
58
|
+
constraints AdminConstraint do
|
59
|
+
mount MissionControl::Servers::Engine => "/mission_control-servers"
|
60
|
+
end
|
61
|
+
post '/mission_control-servers/projects/:project_id/ingress', to: 'mission_control/servers/ingresses#create'
|
62
|
+
end
|
21
63
|
```
|
22
64
|
|
23
|
-
|
65
|
+
In this example, we have directly given a path to the ingress, but locked down everything else to the AdminConstraint.
|
66
|
+
The AdminConstraint takes in the request and calls the `matches?` method. If the method returns true,
|
67
|
+
then the routes will be defined for that request.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
class AdminConstraint
|
71
|
+
def self.matches?(request)
|
72
|
+
true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
## Screenshots
|
78
|
+
|
79
|
+
Simple Installation
|
80
|
+
|
81
|
+

|
24
82
|
|
25
|
-
|
83
|
+
View all of your projects
|
26
84
|
|
27
|
-
|
85
|
+

|
28
86
|
|
29
|
-
|
87
|
+
Detailed Dashboard updates automatically
|
30
88
|
|
31
|
-

|
32
90
|
|
33
91
|
## License
|
34
92
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module MissionControl::Servers
|
2
|
+
class Dashboards::CpuHistoriesController < ApplicationController
|
3
|
+
def show
|
4
|
+
@project = MissionControl::Servers::Project.find_by(token: params[:project_id])
|
5
|
+
@hostname = params[:hostname]
|
6
|
+
services = @project.services.where(hostname: @hostname).ordered
|
7
|
+
@cpu_history_data = MissionControl::Servers::Service.cpu_usage_history(services)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module MissionControl::Servers
|
2
|
+
class Dashboards::CpuUsagesController < ApplicationController
|
3
|
+
def show
|
4
|
+
@project = MissionControl::Servers::Project.find_by(token: params[:project_id])
|
5
|
+
@hostname = params[:hostname]
|
6
|
+
@service = @project.services.where(hostname: @hostname).last
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module MissionControl::Servers
|
2
|
+
class Dashboards::DiskFreesController < ApplicationController
|
3
|
+
def show
|
4
|
+
@project = MissionControl::Servers::Project.find_by(token: params[:project_id])
|
5
|
+
@hostname = params[:hostname]
|
6
|
+
@service = @project.services.where(hostname: @hostname).last
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module MissionControl::Servers
|
2
|
+
class Dashboards::MemoryHistoriesController < ApplicationController
|
3
|
+
def show
|
4
|
+
@project = MissionControl::Servers::Project.find_by(token: params[:project_id])
|
5
|
+
@hostname = params[:hostname]
|
6
|
+
services = @project.services.where(hostname: @hostname).ordered
|
7
|
+
@memory_history_data = MissionControl::Servers::Service.memory_usage_history(services)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module MissionControl::Servers
|
2
|
+
class Dashboards::MemoryUsagesController < ApplicationController
|
3
|
+
def show
|
4
|
+
@project = MissionControl::Servers::Project.find_by(token: params[:project_id])
|
5
|
+
@hostname = params[:hostname]
|
6
|
+
@service = @project.services.where(hostname: @hostname).last
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -4,9 +4,10 @@ module MissionControl::Servers
|
|
4
4
|
before_action :set_project
|
5
5
|
|
6
6
|
def create
|
7
|
-
|
7
|
+
head :unprocessable_entity and return unless @project
|
8
|
+
ingress = @project.services.new(ingress_params)
|
8
9
|
|
9
|
-
if
|
10
|
+
if ingress.save!
|
10
11
|
head :ok
|
11
12
|
else
|
12
13
|
head :unprocessable_entity
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module MissionControl::Servers
|
2
2
|
class ProjectsController < ApplicationController
|
3
3
|
before_action :set_project, only: %i[ show edit update destroy ]
|
4
|
+
before_action :verify_single_project_mode, only: %i[ new create ]
|
4
5
|
|
5
6
|
# GET /projects
|
6
7
|
def index
|
@@ -9,6 +10,11 @@ module MissionControl::Servers
|
|
9
10
|
|
10
11
|
# GET /projects/1
|
11
12
|
def show
|
13
|
+
@services = if params[:hostname]
|
14
|
+
@project.services.where(hostname: params[:hostname]).group_by(&:hostname)
|
15
|
+
else
|
16
|
+
@project.services.group_by(&:hostname)
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
14
20
|
# GET /projects/new
|
@@ -47,6 +53,12 @@ module MissionControl::Servers
|
|
47
53
|
end
|
48
54
|
|
49
55
|
private
|
56
|
+
def verify_single_project_mode
|
57
|
+
if MissionControl::Servers.configuration.single_project_mode && Project.any?
|
58
|
+
redirect_to projects_url, notice: "Single project mode is enabled. You can only have one project at a time."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
50
62
|
# Use callbacks to share common setup or constraints between actions.
|
51
63
|
def set_project
|
52
64
|
@project = Project.find(params[:id])
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module MissionControl::Servers
|
2
|
+
class ScriptsController < ApplicationController
|
3
|
+
before_action :set_project
|
4
|
+
|
5
|
+
def show
|
6
|
+
head :not_found and return unless @project
|
7
|
+
response.content_type = 'text/plain'
|
8
|
+
|
9
|
+
# Render the script directly or from a file
|
10
|
+
render plain: script_content
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
# Use callbacks to share common setup or constraints between actions.
|
15
|
+
def set_project
|
16
|
+
@project = Project.find_by(token: params[:project_id])
|
17
|
+
end
|
18
|
+
|
19
|
+
def script_content
|
20
|
+
<<~SCRIPT
|
21
|
+
cat <<'EOF' > metrics.sh
|
22
|
+
#!/bin/bash
|
23
|
+
|
24
|
+
endpoint="#{project_ingress_url(@project.token)}"
|
25
|
+
cpu_usage=$(
|
26
|
+
top -bn1 | \
|
27
|
+
grep "Cpu(s)" | \
|
28
|
+
sed "s/.*, *\\([0-9.]*\\)%* id.*/\\1/" | \
|
29
|
+
awk '{print 100 - $1}'
|
30
|
+
)
|
31
|
+
mem_used=$(free -m | awk '/^Mem:/ {print $3}')
|
32
|
+
mem_free=$(free -m | awk '/^Mem:/ {print $7}')
|
33
|
+
disk_free=$(df -h | awk '\$NF=="/"{print $4}')
|
34
|
+
hostname=$(hostname)
|
35
|
+
|
36
|
+
data="service[cpu]=$cpu_usage"
|
37
|
+
data+="&service[mem_used]=$mem_used"
|
38
|
+
data+="&service[mem_free]=$mem_free"
|
39
|
+
data+="&service[disk_free]=$disk_free"
|
40
|
+
data+="&service[hostname]=$hostname"
|
41
|
+
|
42
|
+
curl -X POST $endpoint -d $data
|
43
|
+
EOF
|
44
|
+
|
45
|
+
chmod +x metrics.sh
|
46
|
+
|
47
|
+
cron_job="* * * * * $(pwd)/metrics.sh"
|
48
|
+
(crontab -l 2>/dev/null | grep -v -F "$cron_job"; echo "$cron_job") | crontab -
|
49
|
+
SCRIPT
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module MissionControl
|
2
2
|
module Servers
|
3
3
|
module ApplicationHelper
|
4
|
+
def allowed_to_create_project?
|
5
|
+
!MissionControl::Servers.configuration.single_project_mode ||
|
6
|
+
(MissionControl::Servers.configuration.single_project_mode && !@projects.present?)
|
7
|
+
end
|
4
8
|
end
|
5
9
|
end
|
6
10
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["source"];
|
5
|
+
|
6
|
+
copy(event) {
|
7
|
+
const text = this.sourceTarget.textContent;
|
8
|
+
navigator.clipboard.writeText(text).then(() => {
|
9
|
+
event.target.textContent = "Copied!";
|
10
|
+
}).catch(err => {
|
11
|
+
console.error('Failed to copy text: ', err);
|
12
|
+
});
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["modal"]
|
5
|
+
|
6
|
+
show() {
|
7
|
+
this.modalTarget.classList.remove("hidden");
|
8
|
+
}
|
9
|
+
|
10
|
+
hide() {
|
11
|
+
this.modalTarget.classList.add("hidden");
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static values = {
|
5
|
+
label: "Chart",
|
6
|
+
labelArray: Array,
|
7
|
+
dataArray: Array,
|
8
|
+
color: "rgb(54, 162, 235)"
|
9
|
+
}
|
10
|
+
connect() {
|
11
|
+
new Chart(this.element, {
|
12
|
+
type: 'line',
|
13
|
+
data: {
|
14
|
+
labels: this.labelArrayValue,
|
15
|
+
datasets: [{
|
16
|
+
label: this.labelValue,
|
17
|
+
data: this.dataArrayValue,
|
18
|
+
fill: true,
|
19
|
+
borderColor: this.colorValue,
|
20
|
+
tension: 0.25
|
21
|
+
}]
|
22
|
+
},
|
23
|
+
options: {
|
24
|
+
animation: false
|
25
|
+
}
|
26
|
+
});
|
27
|
+
}
|
28
|
+
|
29
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static values = {
|
5
|
+
label: "Chart",
|
6
|
+
idle: Number,
|
7
|
+
used: Number,
|
8
|
+
idleLabel: String,
|
9
|
+
usedLabel: String,
|
10
|
+
idleColor: "rgb(235, 235, 235)",
|
11
|
+
usedColor: "rgb(54, 162, 235)"
|
12
|
+
}
|
13
|
+
connect() {
|
14
|
+
const ctx = this.element
|
15
|
+
new Chart(ctx, {
|
16
|
+
type: 'doughnut',
|
17
|
+
data: {
|
18
|
+
labels: [this.usedLabelValue, this.idleLabelValue],
|
19
|
+
datasets: [
|
20
|
+
{
|
21
|
+
label: this.labelValue,
|
22
|
+
data: [this.usedValue, this.idleValue],
|
23
|
+
backgroundColor: [this.usedColorValue,this.idleColorValue],
|
24
|
+
hoverOffset: 4
|
25
|
+
}
|
26
|
+
]
|
27
|
+
},
|
28
|
+
options: { animation: false }
|
29
|
+
});
|
30
|
+
}
|
31
|
+
|
32
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static values = {
|
5
|
+
src: String,
|
6
|
+
interval: 60000
|
7
|
+
}
|
8
|
+
|
9
|
+
static targets = ["progressBar"]
|
10
|
+
|
11
|
+
connect() {
|
12
|
+
this.startRefreshProcess()
|
13
|
+
if (this.hasProgressBarTarget) {
|
14
|
+
this.resetProgressBar()
|
15
|
+
} else {
|
16
|
+
setTimeout(() => {
|
17
|
+
this.resetProgressBar()
|
18
|
+
}, 500)
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
disconnect() {
|
23
|
+
this.stopRefreshProcess()
|
24
|
+
}
|
25
|
+
|
26
|
+
startRefreshProcess() {
|
27
|
+
this.intervalId = setInterval(() => {
|
28
|
+
this.refreshContent()
|
29
|
+
}, this.intervalValue)
|
30
|
+
}
|
31
|
+
|
32
|
+
stopRefreshProcess() {
|
33
|
+
clearInterval(this.intervalId)
|
34
|
+
clearInterval(this.countdownId)
|
35
|
+
}
|
36
|
+
|
37
|
+
refreshContent() {
|
38
|
+
if (this.element.src) {
|
39
|
+
this.element.reload()
|
40
|
+
} else {
|
41
|
+
this.element.setAttribute('src', this.srcValue)
|
42
|
+
}
|
43
|
+
this.resetProgressBar()
|
44
|
+
}
|
45
|
+
|
46
|
+
startProgressBar() {
|
47
|
+
let percentage = 100
|
48
|
+
this.progressBarTarget.style.width = `${percentage}%`
|
49
|
+
|
50
|
+
const countdown = () => {
|
51
|
+
percentage -= 100 / (this.intervalValue / 500)
|
52
|
+
this.progressBarTarget.style.width = `${percentage}%`
|
53
|
+
|
54
|
+
if (percentage <= 0) {
|
55
|
+
clearInterval(this.countdownId)
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
this.countdownId = setInterval(countdown, 500)
|
60
|
+
}
|
61
|
+
|
62
|
+
resetProgressBar() {
|
63
|
+
clearInterval(this.countdownId)
|
64
|
+
this.startProgressBar()
|
65
|
+
}
|
66
|
+
}
|
@@ -1,5 +1,52 @@
|
|
1
1
|
module MissionControl::Servers
|
2
2
|
class Service < ApplicationRecord
|
3
3
|
belongs_to :project
|
4
|
+
after_create :trim_old_records
|
5
|
+
|
6
|
+
scope :ordered, -> { order(created_at: :desc) }
|
7
|
+
|
8
|
+
def self.cpu_usage_history(services, start_time: 1.hour.ago, end_time: Time.now.utc)
|
9
|
+
timestamps = (start_time.to_i..end_time.to_i).step(60).map { |t| Time.at(t).utc.change(sec: 0).to_i }
|
10
|
+
grouped_services = services.group_by { |service| service.created_at.utc.change(sec: 0).to_i }
|
11
|
+
|
12
|
+
cpu_usages = []
|
13
|
+
created_at_times = []
|
14
|
+
|
15
|
+
timestamps.each do |timestamp|
|
16
|
+
relevant_services = grouped_services[timestamp] || []
|
17
|
+
max_cpu_service = relevant_services.max_by(&:cpu)
|
18
|
+
cpu_usages << (max_cpu_service&.cpu || 0).to_f
|
19
|
+
created_at_times << Time.at(timestamp).utc.strftime('%H:%M%p')
|
20
|
+
end
|
21
|
+
|
22
|
+
{ cpu_usages: cpu_usages, created_at_times: created_at_times }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.memory_usage_history(services, start_time: 1.hour.ago, end_time: Time.now.utc)
|
26
|
+
timestamps = (start_time.to_i..end_time.to_i).step(60).map { |t| Time.at(t).utc.change(sec: 0).to_i }
|
27
|
+
grouped_services = services.group_by { |service| service.created_at.utc.change(sec: 0).to_i }
|
28
|
+
|
29
|
+
memory_usages = []
|
30
|
+
created_at_times = []
|
31
|
+
|
32
|
+
timestamps.each do |timestamp|
|
33
|
+
relevant_services = grouped_services[timestamp] || []
|
34
|
+
max_memory_service = relevant_services.max_by(&:mem_used)
|
35
|
+
memory_usages << (max_memory_service&.mem_used || 0).to_f
|
36
|
+
created_at_times << Time.at(timestamp).utc.strftime('%H:%M%p')
|
37
|
+
end
|
38
|
+
|
39
|
+
{ memory_usages: memory_usages, created_at_times: created_at_times }
|
40
|
+
end
|
41
|
+
|
42
|
+
def mem_percent
|
43
|
+
(mem_used.to_f / (mem_used.to_f + mem_free.to_f) * 100).to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def trim_old_records
|
49
|
+
project.services.where(hostname: hostname).where(created_at: ..1.week.ago).delete_all
|
50
|
+
end
|
4
51
|
end
|
5
52
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(@project, [@hostname, :cpu_history].join('-')) do %>
|
2
|
+
<div class="progress-bar bg-gray-300" style="height: 5px; width: 100%;">
|
3
|
+
<div class="progress bg-blue-500" data-refresh-target="progressBar" style="height: 100%; width: 100%;"></div>
|
4
|
+
</div>
|
5
|
+
<div class="flex flex-col bg-gray-400/5 p-8">
|
6
|
+
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
7
|
+
<canvas data-controller="line-chart"
|
8
|
+
data-line-chart-label-value="CPU History"
|
9
|
+
data-line-chart-label-array-value="<%= @cpu_history_data[:created_at_times] %>"
|
10
|
+
data-line-chart-data-array-value="<%= @cpu_history_data[:cpu_usages] %>"
|
11
|
+
data-line-chart-color-value="rgb(54, 162, 235)"></canvas>
|
12
|
+
</dt>
|
13
|
+
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">CPU History</dd>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(@project, [@hostname, :cpu_usage].join('-')) do %>
|
2
|
+
<div class="progress-bar bg-gray-300" style="height: 5px; width: 100%;">
|
3
|
+
<div class="progress bg-blue-500" data-refresh-target="progressBar" style="height: 100%; width: 100%;"></div>
|
4
|
+
</div>
|
5
|
+
<div class="flex flex-col bg-gray-400/5 p-8">
|
6
|
+
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
7
|
+
<canvas data-controller="pie-chart"
|
8
|
+
data-pie-chart-label-value="CPU Usage"
|
9
|
+
data-pie-chart-idle-value="<%= 100.0 - @service.cpu %>"
|
10
|
+
data-pie-chart-idle-label-value="Idle"
|
11
|
+
data-pie-chart-idle-color-value="rgb(235, 235, 235)"
|
12
|
+
data-pie-chart-used-value="<%= @service.cpu %>"
|
13
|
+
data-pie-chart-used-label-value="Active"
|
14
|
+
data-pie-chart-used-color-value="rgb(54, 162, 235)"></canvas>
|
15
|
+
</dt>
|
16
|
+
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">CPU Usage</dd>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(@project, [@hostname, :disk_free].join('-')) do %>
|
2
|
+
<div class="progress-bar bg-gray-300" style="height: 5px; width: 100%;">
|
3
|
+
<div class="progress bg-blue-500" data-refresh-target="progressBar" style="height: 100%; width: 100%;"></div>
|
4
|
+
</div>
|
5
|
+
<div class="flex flex-col bg-gray-400/5 p-8">
|
6
|
+
<dt class="text-6xl font-semibold leading-6 mt-5 text-gray-600">
|
7
|
+
<%= @service.disk_free %>
|
8
|
+
</dt>
|
9
|
+
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">Disk Free</dd>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(@project, [@hostname, :memory_history].join('-')) do %>
|
2
|
+
<div class="progress-bar bg-gray-300" style="height: 5px; width: 100%;">
|
3
|
+
<div class="progress bg-blue-500" data-refresh-target="progressBar" style="height: 100%; width: 100%;"></div>
|
4
|
+
</div>
|
5
|
+
<div class="flex flex-col bg-gray-400/5 p-8">
|
6
|
+
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
7
|
+
<canvas data-controller="line-chart"
|
8
|
+
data-line-chart-label-value="Memory Used History"
|
9
|
+
data-line-chart-label-array-value="<%= @memory_history_data[:created_at_times] %>"
|
10
|
+
data-line-chart-data-array-value="<%= @memory_history_data[:memory_usages] %>"
|
11
|
+
data-line-chart-color-value="rgb(54, 162, 235)"></canvas>
|
12
|
+
</dt>
|
13
|
+
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">Memory Used History</dd>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(@project, [@hostname, :memory_usage].join('-')) do %>
|
2
|
+
<div class="progress-bar bg-gray-300" style="height: 5px; width: 100%;">
|
3
|
+
<div class="progress bg-blue-500" data-refresh-target="progressBar" style="height: 100%; width: 100%;"></div>
|
4
|
+
</div>
|
5
|
+
<div class="flex flex-col bg-gray-400/5 p-8">
|
6
|
+
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
7
|
+
<canvas data-controller="pie-chart"
|
8
|
+
data-pie-chart-label-value="Memory Usage"
|
9
|
+
data-pie-chart-idle-value="<%= @service.mem_free %>"
|
10
|
+
data-pie-chart-idle-label-value="Idle"
|
11
|
+
data-pie-chart-idle-color-value="rgb(235, 235, 235)"
|
12
|
+
data-pie-chart-used-value="<%= @service.mem_used %>"
|
13
|
+
data-pie-chart-used-label-value="Active"
|
14
|
+
data-pie-chart-used-color-value="rgb(54, 162, 235)"></canvas>
|
15
|
+
</dt>
|
16
|
+
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">Memory Usage</dd>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(@project, "table") do %>
|
2
|
+
<div class="mx-4 my-4 ring-1 ring-gray-300 sm:mx-0 sm:rounded-lg">
|
3
|
+
<div class="progress-bar ring-1 ring-gray-300 sm:mx-0 sm:rounded-lg bg-gray-300" style="height: 5px; width: 100%;">
|
4
|
+
<div class="progress bg-blue-500 ring-1 ring-gray-300 sm:mx-0 sm:rounded-lg" data-refresh-target="progressBar" style="height: 100%; width: 100%;"></div>
|
5
|
+
</div>
|
6
|
+
<table class="min-w-full divide-y divide-gray-300">
|
7
|
+
<thead>
|
8
|
+
<tr>
|
9
|
+
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Hostname</th>
|
10
|
+
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">CPU Usage</th>
|
11
|
+
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">Memory Used</th>
|
12
|
+
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">Memory Used %</th>
|
13
|
+
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">Memory Free</th>
|
14
|
+
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">Disk Free</th>
|
15
|
+
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
|
16
|
+
<span class="sr-only">Select</span>
|
17
|
+
</th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<% @project.services.group_by(&:hostname).each do |hostname, services| %>
|
22
|
+
<tr>
|
23
|
+
<td class="relative py-4 pl-4 pr-3 text-sm sm:pl-6">
|
24
|
+
<div class="font-medium text-gray-900"><%= hostname%></div>
|
25
|
+
</td>
|
26
|
+
<td class="px-3 py-3.5 text-sm text-gray-500 lg:table-cell"><%= services.last.cpu %>%</td>
|
27
|
+
<td class="hidden px-3 py-3.5 text-sm text-gray-500 lg:table-cell"><%= number_to_human_size(services.last.mem_used * 1.megabyte) %></td>
|
28
|
+
<td class="hidden px-3 py-3.5 text-sm text-gray-500 lg:table-cell"><%= services.last.mem_percent %>%</td>
|
29
|
+
<td class="hidden px-3 py-3.5 text-sm text-gray-500 lg:table-cell"><%= number_to_human_size(services.last.mem_free * 1.megabyte) %></td>
|
30
|
+
<td class="hidden px-3 py-3.5 text-sm text-gray-500 lg:table-cell"><%= services.last.disk_free %></td>
|
31
|
+
<td class="relative py-3.5 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
|
32
|
+
<%= link_to "Dashboard", project_path(@project, hostname: hostname), class: "inline-flex items-center rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-white" %>
|
33
|
+
</td>
|
34
|
+
</tr>
|
35
|
+
<% end %>
|
36
|
+
</tbody>
|
37
|
+
</table>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
<%= form_with(model: project) do |form| %>
|
1
|
+
<%= form_with(model: project, class: "max-w-lg mx-auto my-10") do |form| %>
|
2
2
|
<% if project.errors.any? %>
|
3
|
-
<div
|
4
|
-
<
|
5
|
-
|
6
|
-
<ul>
|
3
|
+
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
4
|
+
<strong class="font-bold">Oops!</strong>
|
5
|
+
<span class="block sm:inline"><%= pluralize(project.errors.count, "error") %> prohibited this project from being saved:</span>
|
6
|
+
<ul class="list-disc list-inside mt-2">
|
7
7
|
<% project.errors.each do |error| %>
|
8
8
|
<li><%= error.full_message %></li>
|
9
9
|
<% end %>
|
@@ -11,17 +11,16 @@
|
|
11
11
|
</div>
|
12
12
|
<% end %>
|
13
13
|
|
14
|
-
<div>
|
15
|
-
<%= form.label :title,
|
16
|
-
<%= form.text_field :title %>
|
14
|
+
<div class="mb-4">
|
15
|
+
<%= form.label :title, class: "block text-gray-700 text-sm font-bold mb-2" %>
|
16
|
+
<%= form.text_field :title, class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" %>
|
17
17
|
</div>
|
18
18
|
|
19
|
-
<div>
|
20
|
-
<%= form.
|
21
|
-
<%= form.text_field :token %>
|
19
|
+
<div class="mb-6">
|
20
|
+
<%= form.hidden_field :token %>
|
22
21
|
</div>
|
23
22
|
|
24
|
-
<div>
|
25
|
-
<%= form.submit %>
|
23
|
+
<div class="flex items-center justify-between">
|
24
|
+
<%= form.submit class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" %>
|
26
25
|
</div>
|
27
26
|
<% end %>
|
@@ -1,14 +1,40 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
<
|
4
|
-
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
1
|
+
<div class="px-4 sm:px-6 lg:px-8">
|
2
|
+
<div class="sm:flex sm:items-center">
|
3
|
+
<div class="sm:flex-auto">
|
4
|
+
<h1 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Projects</h1>
|
5
|
+
<p class="mt-2 text-sm text-gray-700">Resource monitor for your Ruby on Rails applications.</p>
|
6
|
+
</div>
|
7
|
+
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
8
|
+
<% if allowed_to_create_project? %>
|
9
|
+
<%= link_to "New project", new_project_path, class: "block rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" %>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
<div class="mt-8 flow-root">
|
14
|
+
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
15
|
+
<div class="inline-block min-w-full py-2 align-middle">
|
16
|
+
<table class="min-w-full divide-y divide-gray-300">
|
17
|
+
<tbody class="divide-y divide-gray-200 bg-white">
|
18
|
+
<% @projects.each do |project| %>
|
19
|
+
<tr>
|
20
|
+
<td class="whitespace-nowrap text-2xl font-bold tracking-tight text-gray-900 sm:text-3xl"><%= project.title %></td>
|
21
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
22
|
+
<%= link_to "Dashboards", project, class: "rounded-md bg-indigo-50 px-2.5 py-1.5 text-sm font-semibold text-indigo-600 shadow-sm hover:bg-indigo-100" %>
|
23
|
+
</td>
|
24
|
+
</tr>
|
25
|
+
<tr>
|
26
|
+
<td colspan=2>
|
27
|
+
<%= turbo_frame_tag dom_id(project, "table"),
|
28
|
+
src: project_dashboards_project_table_path(project.token),
|
29
|
+
"data-controller": "refresh",
|
30
|
+
"data-refresh-src-value": project_dashboards_project_table_path(project.token),
|
31
|
+
"data-refresh-interval-value": 60000 %>
|
32
|
+
</td>
|
33
|
+
</tr>
|
34
|
+
<% end %>
|
35
|
+
</tbody>
|
36
|
+
</table>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</div>
|
12
40
|
</div>
|
13
|
-
|
14
|
-
<%= link_to "New project", new_project_path %>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
<
|
1
|
+
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 my-10">
|
2
|
+
<h1 class="text-2xl text-center font-semibold text-gray-900 mb-8">New Project</h1>
|
2
3
|
|
3
|
-
<%= render "form", project: @project %>
|
4
|
+
<%= render "form", project: @project %>
|
4
5
|
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
<%= link_to "Back to projects", projects_path %>
|
6
|
+
<div class="text-center mt-6">
|
7
|
+
<%= link_to "Back to projects", projects_path, class: "text-blue-600 hover:text-blue-800 transition duration-150 ease-in-out" %>
|
8
|
+
</div>
|
9
9
|
</div>
|
@@ -1,128 +1,89 @@
|
|
1
1
|
<div class="lg:flex lg:items-center lg:justify-between">
|
2
2
|
<div class="min-w-0 flex-1">
|
3
3
|
<h2 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight"><%= @project.title %></h2>
|
4
|
-
<div class="mt-1 flex flex-col sm:mt-0 sm:flex-row sm:flex-wrap sm:space-x-6">
|
5
|
-
<div class="mt-2 flex items-center text-sm text-gray-500">
|
6
|
-
<svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
7
|
-
<path fill-rule="evenodd" d="M9.69 18.933l.003.001C9.89 19.02 10 19 10 19s.11.02.308-.066l.002-.001.006-.003.018-.008a5.741 5.741 0 00.281-.14c.186-.096.446-.24.757-.433.62-.384 1.445-.966 2.274-1.765C15.302 14.988 17 12.493 17 9A7 7 0 103 9c0 3.492 1.698 5.988 3.355 7.584a13.731 13.731 0 002.273 1.765 11.842 11.842 0 00.976.544l.062.029.018.008.006.003zM10 11.25a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5z" clip-rule="evenodd" />
|
8
|
-
</svg>
|
9
|
-
<%= link_to project_ingress_url(@project), project_ingress_url(@project) %>
|
10
|
-
</div>
|
11
|
-
</div>
|
12
4
|
</div>
|
13
5
|
|
14
6
|
<div class="mt-5 flex lg:ml-4 lg:mt-0">
|
15
7
|
<span class="hidden sm:block">
|
16
8
|
<%= link_to edit_project_path(@project), class: "inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" do %>
|
17
|
-
<svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
18
|
-
<path d="M2.695 14.763l-1.262 3.154a.5.5 0 00.65.65l3.155-1.262a4 4 0 001.343-.885L17.5 5.5a2.121 2.121 0 00-3-3L3.58 13.42a4 4 0 00-.885 1.343z" />
|
19
|
-
</svg>
|
20
9
|
Edit
|
21
10
|
<% end %>
|
11
|
+
<%= link_to projects_path, class: "inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" do %>
|
12
|
+
Projects
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<span data-controller="dialog copy">
|
16
|
+
<button data-action="click->dialog#show" class="rounded-md bg-indigo-50 px-2.5 py-1.5 text-sm font-semibold text-indigo-600 shadow-sm hover:bg-indigo-100">
|
17
|
+
Deploy
|
18
|
+
</button>
|
19
|
+
<div data-dialog-target="modal" class="hidden fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
20
|
+
<div data-action="click->dialog#hide" class="fixed inset-0 bg-gray-500 bg-opacity-75"></div>
|
21
|
+
<div class="flex items-end justify-center min-h-full p-4 text-center sm:items-center">
|
22
|
+
<div class="relative bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 md:max-w-3xl sm:w-full">
|
23
|
+
<div class="px-4 pt-5 pb-4 sm:p-6">
|
24
|
+
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">Installation Instructions</h3>
|
25
|
+
<div class="mt-2">
|
26
|
+
<p class="text-sm text-gray-500">
|
27
|
+
You'll make a cURL request from each server that you want to monitor.
|
28
|
+
Copy and paste the script below to each server to start sending metrics to your dashboard.
|
29
|
+
</p>
|
30
|
+
<button data-action="click->copy#copy" class="rounded-md bg-blue-500 mt-4 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-blue-600">
|
31
|
+
Copy
|
32
|
+
</button>
|
33
|
+
<pre data-copy-target="source" class="bg-gray-700 text-white p-4 mt-4 text-sm overflow-x-auto">curl -sSL <%= project_script_url(@project.token) %> | sh</pre>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</span>
|
40
|
+
|
22
41
|
</span>
|
23
42
|
</div>
|
24
43
|
</div>
|
25
44
|
|
45
|
+
<% @services.each do |hostname, services| %>
|
46
|
+
<div class="bg-white py-4 sm:py-8">
|
47
|
+
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
48
|
+
<div class="mx-auto max-w-2xl lg:max-w-none">
|
49
|
+
<div class="text-center">
|
50
|
+
<h2 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl"><%= hostname %></h2>
|
51
|
+
</div>
|
52
|
+
<dl class="mt-8 grid grid-cols-1 gap-0.5 overflow-hidden rounded-2xl text-center sm:grid-cols-2 lg:grid-cols-3">
|
53
|
+
<%= turbo_frame_tag dom_id(@project, [hostname, :cpu_usage].join('-')),
|
54
|
+
src: project_dashboards_cpu_usage_path(project_id: @project.token, hostname: hostname),
|
55
|
+
"data-controller": "refresh",
|
56
|
+
"data-refresh-src-value": project_dashboards_cpu_usage_path(project_id: @project.token, hostname: hostname),
|
57
|
+
"data-refresh-interval-value": 30000 %>
|
58
|
+
|
59
|
+
<%= turbo_frame_tag dom_id(@project, [hostname, :memory_usage].join('-')),
|
60
|
+
src: project_dashboards_memory_usage_path(project_id: @project.token, hostname: hostname),
|
61
|
+
"data-controller": "refresh",
|
62
|
+
"data-refresh-src-value": project_dashboards_memory_usage_path(project_id: @project.token, hostname: hostname),
|
63
|
+
"data-refresh-interval-value": 30000 %>
|
26
64
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
65
|
+
<%= turbo_frame_tag dom_id(@project, [hostname, :disk_free].join('-')),
|
66
|
+
src: project_dashboards_disk_free_path(project_id: @project.token, hostname: hostname),
|
67
|
+
"data-controller": "refresh",
|
68
|
+
"data-refresh-src-value": project_dashboards_disk_free_path(project_id: @project.token, hostname: hostname),
|
69
|
+
"data-refresh-interval-value": 60000 %>
|
70
|
+
</dl>
|
71
|
+
<dl class="mt-8 grid grid-cols-1 gap-0.5 overflow-hidden rounded-2xl text-center sm:grid-cols-1 lg:grid-cols-1">
|
72
|
+
<%= turbo_frame_tag dom_id(@project, [hostname, :cpu_history].join('-')),
|
73
|
+
src: project_dashboards_cpu_history_path(project_id: @project.token, hostname: hostname),
|
74
|
+
"data-controller": "refresh",
|
75
|
+
"data-refresh-src-value": project_dashboards_cpu_history_path(project_id: @project.token, hostname: hostname),
|
76
|
+
"data-refresh-interval-value": 60000 %>
|
77
|
+
</dl>
|
78
|
+
<dl class="mt-8 grid grid-cols-1 gap-0.5 overflow-hidden rounded-2xl text-center sm:grid-cols-1 lg:grid-cols-1">
|
79
|
+
<%= turbo_frame_tag dom_id(@project, [hostname, :memory_history].join('-')),
|
80
|
+
src: project_dashboards_memory_history_path(project_id: @project.token, hostname: hostname),
|
81
|
+
"data-controller": "refresh",
|
82
|
+
"data-refresh-src-value": project_dashboards_memory_history_path(project_id: @project.token, hostname: hostname),
|
83
|
+
"data-refresh-interval-value": 60000 %>
|
84
|
+
</dl>
|
32
85
|
</div>
|
33
|
-
<dl class="mt-8 grid grid-cols-1 gap-0.5 overflow-hidden rounded-2xl text-center sm:grid-cols-2 lg:grid-cols-3">
|
34
|
-
<div class="flex flex-col bg-gray-400/5 p-8">
|
35
|
-
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
36
|
-
<canvas id="cpuUsage"></canvas>
|
37
|
-
</dt>
|
38
|
-
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">CPU Usage</dd>
|
39
|
-
</div>
|
40
|
-
<div class="flex flex-col bg-gray-400/5 p-8">
|
41
|
-
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
42
|
-
<canvas id="freeMemory"></canvas>
|
43
|
-
</dt>
|
44
|
-
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">Memory Usage</dd>
|
45
|
-
</div>
|
46
|
-
<div class="flex flex-col bg-gray-400/5 p-8">
|
47
|
-
<dt class="text-6xl font-semibold leading-6 mt-5 text-gray-600">
|
48
|
-
918Gi
|
49
|
-
</dt>
|
50
|
-
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">Disk Free</dd>
|
51
|
-
</div>
|
52
|
-
</dl>
|
53
|
-
<dl class="mt-8 grid grid-cols-1 gap-0.5 overflow-hidden rounded-2xl text-center sm:grid-cols-1 lg:grid-cols-1">
|
54
|
-
<div class="flex flex-col bg-gray-400/5 p-8">
|
55
|
-
<dt class="text-sm font-semibold leading-6 text-gray-600">
|
56
|
-
<canvas id="cpuHistory"></canvas>
|
57
|
-
</dt>
|
58
|
-
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900">CPU History</dd>
|
59
|
-
</div>
|
60
|
-
</dl>
|
61
86
|
</div>
|
62
87
|
</div>
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
<script>
|
67
|
-
var ctx = document.getElementById('cpuHistory');
|
68
|
-
|
69
|
-
new Chart(ctx, {
|
70
|
-
type: 'line',
|
71
|
-
data: {
|
72
|
-
labels: ['9:01pm', '9:02pm', '9:03pm', '9:04pm', '9:05pm', '9:06pm', '9:07pm'],
|
73
|
-
datasets: [{
|
74
|
-
label: 'CPU Usage',
|
75
|
-
data: [65, 59, 80, 81, 56, 55, 40],
|
76
|
-
fill: true,
|
77
|
-
borderColor: 'rgb(75, 192, 192)',
|
78
|
-
tension: 0.1
|
79
|
-
}]
|
80
|
-
}
|
81
|
-
});
|
82
|
-
</script>
|
83
|
-
|
84
|
-
<script>
|
85
|
-
var ctx = document.getElementById('freeMemory');
|
86
|
-
|
87
|
-
new Chart(ctx, {
|
88
|
-
type: 'doughnut',
|
89
|
-
data: {
|
90
|
-
labels: [
|
91
|
-
'Used',
|
92
|
-
'Free'
|
93
|
-
],
|
94
|
-
datasets: [{
|
95
|
-
label: 'Memory',
|
96
|
-
data: [300, 100],
|
97
|
-
backgroundColor: [
|
98
|
-
'rgb(255, 99, 132)',
|
99
|
-
'rgb(54, 162, 235)'
|
100
|
-
],
|
101
|
-
hoverOffset: 4
|
102
|
-
}]
|
103
|
-
}
|
104
|
-
});
|
105
|
-
</script>
|
106
|
-
|
107
|
-
<script>
|
108
|
-
var ctx = document.getElementById('cpuUsage');
|
88
|
+
<% end %>
|
109
89
|
|
110
|
-
new Chart(ctx, {
|
111
|
-
type: 'doughnut',
|
112
|
-
data: {
|
113
|
-
labels: [
|
114
|
-
'Active',
|
115
|
-
'Idle'
|
116
|
-
],
|
117
|
-
datasets: [{
|
118
|
-
label: 'CPU Usage',
|
119
|
-
data: [300, 100],
|
120
|
-
backgroundColor: [
|
121
|
-
'rgb(54, 162, 235)',
|
122
|
-
'rgb(235, 235, 235)'
|
123
|
-
],
|
124
|
-
hoverOffset: 4
|
125
|
-
}]
|
126
|
-
}
|
127
|
-
});
|
128
|
-
</script>
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
MissionControl::Servers::Engine.routes.draw do
|
2
2
|
resources :projects do
|
3
3
|
resource :ingress, only: :create
|
4
|
+
resource :script, only: :show
|
5
|
+
namespace :dashboards do
|
6
|
+
resource :project_table, only: :show
|
7
|
+
resource :cpu_usage, only: :show
|
8
|
+
resource :memory_usage, only: :show
|
9
|
+
resource :disk_free, only: :show
|
10
|
+
resource :cpu_history, only: :show
|
11
|
+
resource :memory_history, only: :show
|
12
|
+
end
|
4
13
|
end
|
5
14
|
root to: "projects#index"
|
6
15
|
end
|
@@ -2,11 +2,11 @@ class CreateMissionControlServersServices < ActiveRecord::Migration[7.1]
|
|
2
2
|
def change
|
3
3
|
create_table :mission_control_servers_services do |t|
|
4
4
|
t.belongs_to :project, null: false, foreign_key: { to_table: :mission_control_servers_projects }
|
5
|
-
t.string :hostname
|
5
|
+
t.string :hostname, index: true, null: false
|
6
6
|
t.decimal :cpu, precision: 8, scale: 2
|
7
7
|
t.decimal :mem_used, precision: 8, scale: 2
|
8
8
|
t.decimal :mem_free, precision: 8, scale: 2
|
9
|
-
t.
|
9
|
+
t.string :disk_free
|
10
10
|
|
11
11
|
t.timestamps
|
12
12
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "mission_control/servers/version"
|
2
2
|
require "mission_control/servers/engine"
|
3
|
+
require "mission_control/servers/configuration"
|
3
4
|
|
4
5
|
require "zeitwerk"
|
5
6
|
|
@@ -10,6 +11,16 @@ loader.setup
|
|
10
11
|
|
11
12
|
module MissionControl
|
12
13
|
module Servers
|
13
|
-
|
14
|
+
class << self
|
15
|
+
attr_writer :configuration
|
16
|
+
|
17
|
+
def configuration
|
18
|
+
@configuration ||= Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure
|
22
|
+
yield(configuration) if block_given?
|
23
|
+
end
|
24
|
+
end
|
14
25
|
end
|
15
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mission_control-servers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dave Kimura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -79,21 +79,44 @@ files:
|
|
79
79
|
- app/assets/config/mission_control_servers_manifest.js
|
80
80
|
- app/assets/stylesheets/mission_control/servers/application.css
|
81
81
|
- app/controllers/mission_control/servers/application_controller.rb
|
82
|
+
- app/controllers/mission_control/servers/dashboards/cpu_histories_controller.rb
|
83
|
+
- app/controllers/mission_control/servers/dashboards/cpu_usages_controller.rb
|
84
|
+
- app/controllers/mission_control/servers/dashboards/disk_frees_controller.rb
|
85
|
+
- app/controllers/mission_control/servers/dashboards/memory_histories_controller.rb
|
86
|
+
- app/controllers/mission_control/servers/dashboards/memory_usages_controller.rb
|
87
|
+
- app/controllers/mission_control/servers/dashboards/project_tables_controller.rb
|
82
88
|
- app/controllers/mission_control/servers/ingresses_controller.rb
|
83
89
|
- app/controllers/mission_control/servers/projects_controller.rb
|
90
|
+
- app/controllers/mission_control/servers/scripts_controller.rb
|
84
91
|
- app/helpers/mission_control/servers/application_helper.rb
|
92
|
+
- app/helpers/mission_control/servers/dashboards/cpu_histories_helper.rb
|
93
|
+
- app/helpers/mission_control/servers/dashboards/cpu_usages_helper.rb
|
94
|
+
- app/helpers/mission_control/servers/dashboards/disk_frees_helper.rb
|
95
|
+
- app/helpers/mission_control/servers/dashboards/memory_histories_helper.rb
|
96
|
+
- app/helpers/mission_control/servers/dashboards/memory_usages_helper.rb
|
97
|
+
- app/helpers/mission_control/servers/dashboards/project_tables_helper.rb
|
85
98
|
- app/helpers/mission_control/servers/projects_helper.rb
|
86
99
|
- app/javascript/mission_control/servers/application.js
|
87
100
|
- app/javascript/mission_control/servers/controllers/application.js
|
101
|
+
- app/javascript/mission_control/servers/controllers/copy_controller.js
|
102
|
+
- app/javascript/mission_control/servers/controllers/dialog_controller.js
|
88
103
|
- app/javascript/mission_control/servers/controllers/index.js
|
104
|
+
- app/javascript/mission_control/servers/controllers/line_chart_controller.js
|
105
|
+
- app/javascript/mission_control/servers/controllers/pie_chart_controller.js
|
106
|
+
- app/javascript/mission_control/servers/controllers/refresh_controller.js
|
89
107
|
- app/jobs/mission_control/servers/application_job.rb
|
90
108
|
- app/mailers/mission_control/servers/application_mailer.rb
|
91
109
|
- app/models/mission_control/servers/application_record.rb
|
92
110
|
- app/models/mission_control/servers/project.rb
|
93
111
|
- app/models/mission_control/servers/service.rb
|
94
112
|
- app/views/layouts/mission_control/servers/application.html.erb
|
113
|
+
- app/views/mission_control/servers/dashboards/cpu_histories/show.html.erb
|
114
|
+
- app/views/mission_control/servers/dashboards/cpu_usages/show.html.erb
|
115
|
+
- app/views/mission_control/servers/dashboards/disk_frees/show.html.erb
|
116
|
+
- app/views/mission_control/servers/dashboards/memory_histories/show.html.erb
|
117
|
+
- app/views/mission_control/servers/dashboards/memory_usages/show.html.erb
|
118
|
+
- app/views/mission_control/servers/dashboards/project_tables/show.html.erb
|
95
119
|
- app/views/mission_control/servers/projects/_form.html.erb
|
96
|
-
- app/views/mission_control/servers/projects/_project.html.erb
|
97
120
|
- app/views/mission_control/servers/projects/edit.html.erb
|
98
121
|
- app/views/mission_control/servers/projects/index.html.erb
|
99
122
|
- app/views/mission_control/servers/projects/new.html.erb
|
@@ -103,6 +126,7 @@ files:
|
|
103
126
|
- db/migrate/20240205020304_create_mission_control_servers_projects.rb
|
104
127
|
- db/migrate/20240205031009_create_mission_control_servers_services.rb
|
105
128
|
- lib/mission_control/servers.rb
|
129
|
+
- lib/mission_control/servers/configuration.rb
|
106
130
|
- lib/mission_control/servers/engine.rb
|
107
131
|
- lib/mission_control/servers/version.rb
|
108
132
|
- lib/tasks/mission_control/servers_tasks.rake
|