mission_control-servers 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![ScreenShot-2024-02-06-08-50-39](https://github.com/kobaltz/mission_control-servers/assets/635114/78f96ff6-ac14-4798-96a5-59a59eff574c)
|
24
82
|
|
25
|
-
|
83
|
+
View all of your projects
|
26
84
|
|
27
|
-
|
85
|
+
![ScreenShot-2024-02-06-21-34-07](https://github.com/kobaltz/mission_control-servers/assets/635114/6f524e6e-1d4d-4587-9949-f1f3c57724c8)
|
28
86
|
|
29
|
-
|
87
|
+
Detailed Dashboard updates automatically
|
30
88
|
|
31
|
-
![
|
89
|
+
![ScreenShot-2024-02-06-22-21-15](https://github.com/kobaltz/mission_control-servers/assets/635114/320c57ad-64bf-4582-a680-c79c91e62b60)
|
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
|