Added some monitoring widgets and scripts
parent
d4b9dee6d9
commit
8e86943b83
@ -0,0 +1,52 @@
|
||||
import { byteSizeToString, useRemoteState } from '../../util.jsx'
|
||||
import { PieChart } from '../charts/PieChart.jsx'
|
||||
import { Icon } from '../Icon.jsx'
|
||||
import { ToastMessage, useToasts } from '../Toasts.jsx'
|
||||
|
||||
export const DiskUsage = ({ disk }) => {
|
||||
const [showToast] = useToasts()
|
||||
const [output, err, refreshOutput] = useRemoteState(
|
||||
`/api/monitor/status?script=${encodeURIComponent(`disk-usage ${disk}`)}`,
|
||||
'100\n0'
|
||||
)
|
||||
|
||||
const [total, used] = output.split('\n').map(s => parseInt(s))
|
||||
|
||||
const title = (
|
||||
<>
|
||||
Spazio Utilizzato • <code>{disk}</code>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="title">
|
||||
<div class="row">
|
||||
<div class="row-group">
|
||||
<p>{title}</p>
|
||||
</div>
|
||||
<div class="row-group">
|
||||
<button
|
||||
class="icon"
|
||||
onClick={() => {
|
||||
refreshOutput()
|
||||
showToast(
|
||||
<ToastMessage icon="info">Aggiornato "{title}"</ToastMessage>
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
{err ? (
|
||||
<p>Errore "{err}"</p>
|
||||
) : (
|
||||
<PieChart parts={[used]} labels={[byteSizeToString(used)]} total={total} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { PieChart } from '../charts/PieChart.jsx'
|
||||
|
||||
export const PieChartWidget = ({ title, ...chart }) => {
|
||||
title = title || 'Grafico a torta'
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="title">{title}</div>
|
||||
<div class="content">
|
||||
<PieChart {...chart} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
import { useRemoteState } from '../../util.jsx'
|
||||
import { Icon } from '../Icon.jsx'
|
||||
import { ToastMessage, useToasts } from '../Toasts.jsx'
|
||||
|
||||
export const ScriptStatus = ({ title, script }) => {
|
||||
const [showToast] = useToasts()
|
||||
const [output, err, refreshOutput] = useRemoteState(
|
||||
`/api/monitor/status?script=${encodeURIComponent(script)}`,
|
||||
''
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="title">
|
||||
<div class="row">
|
||||
<div class="row-group">{title}</div>
|
||||
<div class="row-group">
|
||||
<button
|
||||
class="icon"
|
||||
onClick={() => {
|
||||
refreshOutput()
|
||||
showToast(
|
||||
<ToastMessage icon="info">Aggiornato "{title}"</ToastMessage>
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
{err ? (
|
||||
<p>Errore "{err}"</p>
|
||||
) : (
|
||||
<pre>
|
||||
<code>{output}</code>
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ScriptsDir string `json:"scriptsDir"`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
Config Config
|
||||
|
||||
scriptPaths []string
|
||||
}
|
||||
|
||||
func New(config Config) *Service {
|
||||
return &Service{
|
||||
Config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) LoadScripts() error {
|
||||
entries, err := os.ReadDir(s.Config.ScriptsDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.scriptPaths = []string{}
|
||||
|
||||
for _, entry := range entries {
|
||||
s.scriptPaths = append(s.scriptPaths,
|
||||
path.Join(s.Config.ScriptsDir, entry.Name()),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ScriptsDir string `json:"scriptsDir"`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
Config *Config
|
||||
|
||||
scriptPaths map[string]string
|
||||
}
|
||||
|
||||
func NewService(config *Config) *Service {
|
||||
return &Service{
|
||||
Config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) LoadScripts() error {
|
||||
entries, err := os.ReadDir(s.Config.ScriptsDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.scriptPaths = map[string]string{}
|
||||
|
||||
for _, entry := range entries {
|
||||
newScriptPath := path.Join(s.Config.ScriptsDir, entry.Name())
|
||||
s.scriptPaths[entry.Name()] = newScriptPath
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Add caching
|
||||
func (s *Service) GetLastOutput(command string) (string, error) {
|
||||
args := strings.Fields(command)
|
||||
|
||||
scriptPath := s.scriptPaths[args[0]]
|
||||
|
||||
cmd := exec.Command(scriptPath, args[1:]...)
|
||||
var b bytes.Buffer
|
||||
cmd.Stdout = &b
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return b.String(), nil
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func (r *Router) ApiMonitor(api fiber.Router) {
|
||||
// Respond to requests like
|
||||
// - "/api/monitor/status?script=SCRIPT_NAME" where SCRIPT_NAME is the name of a file inside "./scripts"
|
||||
api.Get("/status", func(c *fiber.Ctx) error {
|
||||
if qScript := c.Query("script"); qScript != "" {
|
||||
log.Printf("Script %q", qScript)
|
||||
|
||||
output, err := r.Monitor.GetLastOutput(qScript)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(output)
|
||||
}
|
||||
|
||||
return fmt.Errorf("no script, device or entity provided")
|
||||
})
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
package routes
|
||||
|
||||
import "git.phc.dm.unipi.it/phc/storage/database"
|
||||
import (
|
||||
"git.phc.dm.unipi.it/phc/storage/database"
|
||||
"git.phc.dm.unipi.it/phc/storage/monitor"
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
Database database.Database
|
||||
Monitor *monitor.Service
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEVICE="$1"
|
||||
|
||||
df | grep "$DEVICE" | tr -s ' ' | cut -d' ' -f 2-3 | tr ' ' '\n'
|
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo 'active'
|
||||
echo 'active'
|
||||
echo 'active'
|
||||
echo 'failing'
|
||||
echo 'missing'
|
Loading…
Reference in New Issue