forked from phc/cluster-dashboard
aggiunti grafici e cambiato temperatura in voltaggio
This commit is contained in:
@@ -13,9 +13,10 @@ type Database interface {
|
|||||||
AllNodes() ([]*model.Node, error)
|
AllNodes() ([]*model.Node, error)
|
||||||
AllJobs() ([]*model.Job, error)
|
AllJobs() ([]*model.Job, error)
|
||||||
|
|
||||||
QueryTemperatureSamples(from, to time.Time) ([]model.Sample[float64], error)
|
QueryVoltageSamples(from, to time.Time) ([]model.Sample[float64], error)
|
||||||
QueryMemorySamples(from, to time.Time) ([]model.Sample[int64], error)
|
QueryMemorySamples(from, to time.Time) ([]model.Sample[int64], error)
|
||||||
QueryStorageSamples(from, to time.Time) ([]model.Sample[int64], error)
|
QueryStorageSamples(from, to time.Time) ([]model.Sample[int64], error)
|
||||||
|
QueryCPUSamples(from, to time.Time) ([]model.Sample[float64], error)
|
||||||
QueryNetworkUploadSamples(from, to time.Time) ([]model.Sample[int64], error)
|
QueryNetworkUploadSamples(from, to time.Time) ([]model.Sample[int64], error)
|
||||||
QueryNetworkDownloadSamples(from, to time.Time) ([]model.Sample[int64], error)
|
QueryNetworkDownloadSamples(from, to time.Time) ([]model.Sample[int64], error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ func (s *simpleDB) AllJobs() ([]*model.Job, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *simpleDB) QueryTemperatureSamples(from, to time.Time) ([]model.Sample[float64], error) {
|
func (s *simpleDB) QueryVoltageSamples(from, to time.Time) ([]model.Sample[float64], error) {
|
||||||
return generateFakeFloat64Samples(100), nil
|
return generateFakeFloat64Samples(100), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,6 +122,10 @@ func (s *simpleDB) QueryStorageSamples(from, to time.Time) ([]model.Sample[int64
|
|||||||
return generateFakeInt64Samples(100), nil
|
return generateFakeInt64Samples(100), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *simpleDB) QueryCPUSamples(from, to time.Time) ([]model.Sample[float64], error) {
|
||||||
|
return generateFakeFloat64Samples(100), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *simpleDB) QueryNetworkUploadSamples(from, to time.Time) ([]model.Sample[int64], error) {
|
func (s *simpleDB) QueryNetworkUploadSamples(from, to time.Time) ([]model.Sample[int64], error) {
|
||||||
return generateFakeInt64Samples(100), nil
|
return generateFakeInt64Samples(100), nil
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-3
@@ -62,9 +62,9 @@ func (r *Service) Api(api fiber.Router) {
|
|||||||
return c.JSON(jobs)
|
return c.JSON(jobs)
|
||||||
})
|
})
|
||||||
|
|
||||||
// QueryTemperatureSamples
|
// QueryVoltageSamples
|
||||||
api.Get("/stats/temperature", QueryTimeRangeMiddleware(func(c *fiber.Ctx, from, to time.Time) error {
|
api.Get("/stats/voltage", QueryTimeRangeMiddleware(func(c *fiber.Ctx, from, to time.Time) error {
|
||||||
samples, err := r.Database.QueryTemperatureSamples(from, to)
|
samples, err := r.Database.QueryVoltageSamples(from, to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -92,6 +92,16 @@ func (r *Service) Api(api fiber.Router) {
|
|||||||
return c.JSON(samples)
|
return c.JSON(samples)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// QueryCPUSamples
|
||||||
|
api.Get("/stats/cpu", QueryTimeRangeMiddleware(func(c *fiber.Ctx, from, to time.Time) error {
|
||||||
|
samples, err := r.Database.QueryCPUSamples(from, to)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(samples)
|
||||||
|
}))
|
||||||
|
|
||||||
// QueryNetworkUploadSamples
|
// QueryNetworkUploadSamples
|
||||||
api.Get("/stats/network-upload", QueryTimeRangeMiddleware(func(c *fiber.Ctx, from, to time.Time) error {
|
api.Get("/stats/network-upload", QueryTimeRangeMiddleware(func(c *fiber.Ctx, from, to time.Time) error {
|
||||||
samples, err := r.Database.QueryNetworkUploadSamples(from, to)
|
samples, err := r.Database.QueryNetworkUploadSamples(from, to)
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { useEffect, useState } from 'preact/hooks'
|
||||||
|
import { server } from '../utils.js'
|
||||||
|
import { PlotDouble } from './PlotDouble.jsx'
|
||||||
|
|
||||||
|
export const GraphCardDouble = ({ label, url1, url2 }) => {
|
||||||
|
const [samples1, setSamples1] = useState([])
|
||||||
|
const [samples2, setSamples2] = useState([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (url1) {
|
||||||
|
server.get(url1).then(data => setSamples1(data))
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (url2) {
|
||||||
|
server.get(url2).then(data => setSamples2(data))
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="card">
|
||||||
|
<div class="label">{label}</div>
|
||||||
|
<div class="graph">{url1 && url2 && <PlotDouble samples1={samples1} samples2={samples2} />}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import * as d3 from 'd3'
|
||||||
|
import { useEffect, useRef } from 'preact/hooks'
|
||||||
|
|
||||||
|
// set the dimensions and margins of the graph
|
||||||
|
const margin = { top: 10, right: 10, bottom: 30, left: 30 }
|
||||||
|
|
||||||
|
export const PlotDouble = ({ samples1, samples2 }) => {
|
||||||
|
if (samples1.length === 0 || samples2.length === 0) {
|
||||||
|
return <>Loading...</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const data1 = samples1.map(({ timestamp, value }) => ({
|
||||||
|
timestamp: d3.isoParse(timestamp),
|
||||||
|
value: value,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const data2 = samples2.map(({ timestamp, value }) => ({
|
||||||
|
timestamp: d3.isoParse(timestamp),
|
||||||
|
value: value,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const plotRef = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (plotRef.current) {
|
||||||
|
const el = plotRef.current
|
||||||
|
|
||||||
|
const width = el.offsetWidth - margin.left - margin.right
|
||||||
|
const height = el.offsetHeight - margin.top - margin.bottom
|
||||||
|
|
||||||
|
const svg = d3
|
||||||
|
.select(el)
|
||||||
|
.append('svg')
|
||||||
|
.attr('width', el.offsetWidth)
|
||||||
|
.attr('height', el.offsetHeight)
|
||||||
|
.append('g')
|
||||||
|
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
||||||
|
|
||||||
|
const x = d3
|
||||||
|
.scaleTime()
|
||||||
|
.domain(
|
||||||
|
d3.extent([...data1, ...data2], function (d) {
|
||||||
|
return d.timestamp
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.range([0, width])
|
||||||
|
|
||||||
|
const y = d3
|
||||||
|
.scaleLinear()
|
||||||
|
.domain([
|
||||||
|
0,
|
||||||
|
d3.max([...data1, ...data2], function (d) {
|
||||||
|
return +d.value
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
.range([height, 0])
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.attr('transform', 'translate(0,' + height + ')')
|
||||||
|
.call(d3.axisBottom(x))
|
||||||
|
|
||||||
|
svg.append('g').call(d3.axisLeft(y))
|
||||||
|
|
||||||
|
const line1 = svg.append('g')
|
||||||
|
const line2 = svg.append('g')
|
||||||
|
|
||||||
|
line1.append('path')
|
||||||
|
.datum(data1)
|
||||||
|
.attr('fill', 'none')
|
||||||
|
.attr('stroke', 'steelblue')
|
||||||
|
.attr('stroke-width', 2)
|
||||||
|
.attr(
|
||||||
|
'd',
|
||||||
|
d3
|
||||||
|
.line()
|
||||||
|
.x(d => x(d.timestamp))
|
||||||
|
.y(d => y(d.value))
|
||||||
|
)
|
||||||
|
|
||||||
|
line2.append('path')
|
||||||
|
.datum(data2)
|
||||||
|
.attr('fill', 'none')
|
||||||
|
.attr('stroke', 'darkgreen')
|
||||||
|
.attr('stroke-width', 2)
|
||||||
|
.attr(
|
||||||
|
'd',
|
||||||
|
d3
|
||||||
|
.line()
|
||||||
|
.x(d => x(d.timestamp))
|
||||||
|
.y(d => y(d.value))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (plotRef.current) {
|
||||||
|
plotRef.current.firstChild.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [plotRef])
|
||||||
|
|
||||||
|
return <div class="d3-plot" ref={plotRef}></div>
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { GraphCard } from './components/Graph.jsx'
|
import { GraphCard } from './components/Graph.jsx'
|
||||||
|
import { GraphCardDouble } from './components/GraphDouble.jsx'
|
||||||
|
|
||||||
const LOGO = String.raw`
|
const LOGO = String.raw`
|
||||||
_______________________ _______ _______ _______ _
|
_______________________ _______ _______ _______ _
|
||||||
@@ -85,11 +86,11 @@ export const DashboardPage = ({}) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<GraphCard label="Uptime" />
|
<GraphCard label="Uptime" />
|
||||||
<GraphCard label="CPU" />
|
<GraphCard label="CPU" url="/api/stats/cpu"/>
|
||||||
<GraphCard label="Storage" />
|
<GraphCard label="Storage" url="/api/stats/storage"/>
|
||||||
<GraphCard label="Memory" />
|
<GraphCard label="Memory" url="/api/stats/memory"/>
|
||||||
<GraphCard label="Network" />
|
<GraphCardDouble label="Network" url1="/api/stats/network-upload" url2="/api/stats/network-download"/>
|
||||||
<GraphCard label="Temperature" url="/api/stats/temperature" />
|
<GraphCard label="Voltage" url="/api/stats/voltage" />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user