mirror of
https://github.com/openziti/zrok.git
synced 2024-12-22 14:50:55 +01:00
environment metrics wired in and working (#324)
This commit is contained in:
parent
0f6d05f449
commit
43e6c56ec1
@ -94,13 +94,9 @@ func (h *getEnvironmentMetricsHandler) Handle(params metadata.GetEnvironmentMetr
|
|||||||
return metadata.NewGetEnvironmentMetricsInternalServerError()
|
return metadata.NewGetEnvironmentMetricsInternalServerError()
|
||||||
}
|
}
|
||||||
defer func() { _ = trx.Rollback() }()
|
defer func() { _ = trx.Rollback() }()
|
||||||
env, err := str.GetEnvironment(int(params.EnvID), trx)
|
env, err := str.FindEnvironmentForAccount(params.EnvID, int(principal.ID), trx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("error finding environment '%d': %v", int(params.EnvID), err)
|
logrus.Errorf("error finding environment '%s' for '%s': %v", params.EnvID, principal.Email, err)
|
||||||
return metadata.NewGetEnvironmentMetricsUnauthorized()
|
|
||||||
}
|
|
||||||
if int64(env.Id) != principal.ID {
|
|
||||||
logrus.Errorf("unauthorized environemnt '%d' for '%v'", int(params.EnvID), principal.Email)
|
|
||||||
return metadata.NewGetEnvironmentMetricsUnauthorized()
|
return metadata.NewGetEnvironmentMetricsUnauthorized()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/go-openapi/runtime"
|
"github.com/go-openapi/runtime"
|
||||||
cr "github.com/go-openapi/runtime/client"
|
cr "github.com/go-openapi/runtime/client"
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
"github.com/go-openapi/swag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGetEnvironmentMetricsParams creates a new GetEnvironmentMetricsParams object,
|
// NewGetEnvironmentMetricsParams creates a new GetEnvironmentMetricsParams object,
|
||||||
@ -66,7 +65,7 @@ type GetEnvironmentMetricsParams struct {
|
|||||||
Duration *string
|
Duration *string
|
||||||
|
|
||||||
// EnvID.
|
// EnvID.
|
||||||
EnvID float64
|
EnvID string
|
||||||
|
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
Context context.Context
|
Context context.Context
|
||||||
@ -133,13 +132,13 @@ func (o *GetEnvironmentMetricsParams) SetDuration(duration *string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithEnvID adds the envID to the get environment metrics params
|
// WithEnvID adds the envID to the get environment metrics params
|
||||||
func (o *GetEnvironmentMetricsParams) WithEnvID(envID float64) *GetEnvironmentMetricsParams {
|
func (o *GetEnvironmentMetricsParams) WithEnvID(envID string) *GetEnvironmentMetricsParams {
|
||||||
o.SetEnvID(envID)
|
o.SetEnvID(envID)
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEnvID adds the envId to the get environment metrics params
|
// SetEnvID adds the envId to the get environment metrics params
|
||||||
func (o *GetEnvironmentMetricsParams) SetEnvID(envID float64) {
|
func (o *GetEnvironmentMetricsParams) SetEnvID(envID string) {
|
||||||
o.EnvID = envID
|
o.EnvID = envID
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +168,7 @@ func (o *GetEnvironmentMetricsParams) WriteToRequest(r runtime.ClientRequest, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// path param envId
|
// path param envId
|
||||||
if err := r.SetPathParam("envId", swag.FormatFloat64(o.EnvID)); err != nil {
|
if err := r.SetPathParam("envId", o.EnvID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ func init() {
|
|||||||
"operationId": "getEnvironmentMetrics",
|
"operationId": "getEnvironmentMetrics",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "string",
|
||||||
"name": "envId",
|
"name": "envId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
@ -2003,7 +2003,7 @@ func init() {
|
|||||||
"operationId": "getEnvironmentMetrics",
|
"operationId": "getEnvironmentMetrics",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "number",
|
"type": "string",
|
||||||
"name": "envId",
|
"name": "envId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/go-openapi/runtime"
|
"github.com/go-openapi/runtime"
|
||||||
"github.com/go-openapi/runtime/middleware"
|
"github.com/go-openapi/runtime/middleware"
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
"github.com/go-openapi/swag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGetEnvironmentMetricsParams creates a new GetEnvironmentMetricsParams object
|
// NewGetEnvironmentMetricsParams creates a new GetEnvironmentMetricsParams object
|
||||||
@ -40,7 +39,7 @@ type GetEnvironmentMetricsParams struct {
|
|||||||
Required: true
|
Required: true
|
||||||
In: path
|
In: path
|
||||||
*/
|
*/
|
||||||
EnvID float64
|
EnvID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||||
@ -96,12 +95,7 @@ func (o *GetEnvironmentMetricsParams) bindEnvID(rawData []string, hasKey bool, f
|
|||||||
|
|
||||||
// Required: true
|
// Required: true
|
||||||
// Parameter is provided by construction from the route
|
// Parameter is provided by construction from the route
|
||||||
|
o.EnvID = raw
|
||||||
value, err := swag.ConvertFloat64(raw)
|
|
||||||
if err != nil {
|
|
||||||
return errors.InvalidType("envId", "path", "float64", raw)
|
|
||||||
}
|
|
||||||
o.EnvID = value
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,11 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
golangswaggerpaths "path"
|
golangswaggerpaths "path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-openapi/swag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetEnvironmentMetricsURL generates an URL for the get environment metrics operation
|
// GetEnvironmentMetricsURL generates an URL for the get environment metrics operation
|
||||||
type GetEnvironmentMetricsURL struct {
|
type GetEnvironmentMetricsURL struct {
|
||||||
EnvID float64
|
EnvID string
|
||||||
|
|
||||||
Duration *string
|
Duration *string
|
||||||
|
|
||||||
@ -46,7 +44,7 @@ func (o *GetEnvironmentMetricsURL) Build() (*url.URL, error) {
|
|||||||
|
|
||||||
var _path = "/metrics/environment/{envId}"
|
var _path = "/metrics/environment/{envId}"
|
||||||
|
|
||||||
envID := swag.FormatFloat64(o.EnvID)
|
envID := o.EnvID
|
||||||
if envID != "" {
|
if envID != "" {
|
||||||
_path = strings.Replace(_path, "{envId}", envID, -1)
|
_path = strings.Replace(_path, "{envId}", envID, -1)
|
||||||
} else {
|
} else {
|
||||||
|
@ -425,7 +425,7 @@ paths:
|
|||||||
parameters:
|
parameters:
|
||||||
- name: envId
|
- name: envId
|
||||||
in: path
|
in: path
|
||||||
type: number
|
type: string
|
||||||
required: true
|
required: true
|
||||||
- name: duration
|
- name: duration
|
||||||
in: query
|
in: query
|
||||||
|
@ -56,7 +56,7 @@ export function getAccountMetrics(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} envId
|
* @param {string} envId
|
||||||
* @param {object} options Optional options
|
* @param {object} options Optional options
|
||||||
* @param {string} [options.duration]
|
* @param {string} [options.duration]
|
||||||
* @return {Promise<module:types.metrics>} environment metrics
|
* @return {Promise<module:types.metrics>} environment metrics
|
||||||
|
@ -7,6 +7,7 @@ import React, {useEffect, useState} from "react";
|
|||||||
import * as metadata from "../../../api/metadata";
|
import * as metadata from "../../../api/metadata";
|
||||||
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from "recharts";
|
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from "recharts";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import {buildMetrics, bytesToSize} from "../../metrics";
|
||||||
|
|
||||||
const AccountDetail = (props) => {
|
const AccountDetail = (props) => {
|
||||||
const customProperties = {
|
const customProperties = {
|
||||||
@ -28,7 +29,7 @@ const AccountDetail = (props) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MetricsTab = (props) => {
|
const MetricsTab = () => {
|
||||||
const [metrics30, setMetrics30] = useState(buildMetrics([]));
|
const [metrics30, setMetrics30] = useState(buildMetrics([]));
|
||||||
const [metrics7, setMetrics7] = useState(buildMetrics([]));
|
const [metrics7, setMetrics7] = useState(buildMetrics([]));
|
||||||
const [metrics1, setMetrics1] = useState(buildMetrics([]));
|
const [metrics1, setMetrics1] = useState(buildMetrics([]));
|
||||||
@ -147,38 +148,4 @@ const MetricsTab = (props) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildMetrics = (m) => {
|
|
||||||
let metrics = {
|
|
||||||
data: m.samples,
|
|
||||||
rx: 0,
|
|
||||||
tx: 0
|
|
||||||
}
|
|
||||||
if(m.samples) {
|
|
||||||
m.samples.forEach(s => {
|
|
||||||
metrics.rx += s.rx;
|
|
||||||
metrics.tx += s.tx;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return metrics;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bytesToSize = (sz) => {
|
|
||||||
let absSz = sz;
|
|
||||||
if(absSz < 0) {
|
|
||||||
absSz *= -1;
|
|
||||||
}
|
|
||||||
const unit = 1000
|
|
||||||
if(absSz < unit) {
|
|
||||||
return '' + absSz + ' B';
|
|
||||||
}
|
|
||||||
let div = unit
|
|
||||||
let exp = 0
|
|
||||||
for(let n = absSz / unit; n >= unit; n /= unit) {
|
|
||||||
div *= unit;
|
|
||||||
exp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '' + (sz / div).toFixed(1) + ' ' + "kMGTPE"[exp] + 'B';
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccountDetail;
|
export default AccountDetail;
|
@ -6,6 +6,7 @@ import {mdiConsoleNetwork} from "@mdi/js";
|
|||||||
import {getEnvironmentDetail} from "../../../api/metadata";
|
import {getEnvironmentDetail} from "../../../api/metadata";
|
||||||
import DetailTab from "./DetailTab";
|
import DetailTab from "./DetailTab";
|
||||||
import ActionsTab from "./ActionsTab";
|
import ActionsTab from "./ActionsTab";
|
||||||
|
import MetricsTab from "./MetricsTab";
|
||||||
|
|
||||||
const EnvironmentDetail = (props) => {
|
const EnvironmentDetail = (props) => {
|
||||||
const [detail, setDetail] = useState({});
|
const [detail, setDetail] = useState({});
|
||||||
@ -25,6 +26,9 @@ const EnvironmentDetail = (props) => {
|
|||||||
<Tab eventKey={"shares"} title={"Shares"}>
|
<Tab eventKey={"shares"} title={"Shares"}>
|
||||||
<SharesTab selection={props.selection} />
|
<SharesTab selection={props.selection} />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
<Tab eventKey={"metrics"} title={"Metrics"}>
|
||||||
|
<MetricsTab selection={props.selection} />
|
||||||
|
</Tab>
|
||||||
<Tab eventKey={"detail"} title={"Detail"}>
|
<Tab eventKey={"detail"} title={"Detail"}>
|
||||||
<DetailTab environment={detail.environment} />
|
<DetailTab environment={detail.environment} />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
129
ui/src/console/detail/environment/MetricsTab.js
Normal file
129
ui/src/console/detail/environment/MetricsTab.js
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {buildMetrics, bytesToSize} from "../../metrics";
|
||||||
|
import * as metadata from "../../../api/metadata";
|
||||||
|
import {Col, Container, Row, Tooltip} from "react-bootstrap";
|
||||||
|
import {Bar, BarChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis} from "recharts";
|
||||||
|
import moment from "moment/moment";
|
||||||
|
|
||||||
|
const MetricsTab = (props) => {
|
||||||
|
const [metrics30, setMetrics30] = useState(buildMetrics([]));
|
||||||
|
const [metrics7, setMetrics7] = useState(buildMetrics([]));
|
||||||
|
const [metrics1, setMetrics1] = useState(buildMetrics([]));
|
||||||
|
|
||||||
|
console.log("selection", props.selection);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
metadata.getEnvironmentMetrics(props.selection.id)
|
||||||
|
.then(resp => {
|
||||||
|
setMetrics30(buildMetrics(resp.data));
|
||||||
|
});
|
||||||
|
metadata.getEnvironmentMetrics(props.selection.id, {duration: "168h"})
|
||||||
|
.then(resp => {
|
||||||
|
setMetrics7(buildMetrics(resp.data));
|
||||||
|
});
|
||||||
|
metadata.getEnvironmentMetrics(props.selection.id, {duration: "24h"})
|
||||||
|
.then(resp => {
|
||||||
|
setMetrics1(buildMetrics(resp.data));
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let mounted = true;
|
||||||
|
let interval = setInterval(() => {
|
||||||
|
metadata.getEnvironmentMetrics(props.selection.id)
|
||||||
|
.then(resp => {
|
||||||
|
if(mounted) {
|
||||||
|
setMetrics30(buildMetrics(resp.data));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
metadata.getEnvironmentMetrics(props.selection.id, {duration: "168h"})
|
||||||
|
.then(resp => {
|
||||||
|
setMetrics7(buildMetrics(resp.data));
|
||||||
|
});
|
||||||
|
metadata.getEnvironmentMetrics(props.selection.id, {duration: "24h"})
|
||||||
|
.then(resp => {
|
||||||
|
setMetrics1(buildMetrics(resp.data));
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
return () => {
|
||||||
|
mounted = false;
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<h3>Last 30 Days:</h3>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col><p>Received: {bytesToSize(metrics30.rx)}</p></Col>
|
||||||
|
<Col><p>Sent: {bytesToSize(metrics30.tx)}</p></Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<ResponsiveContainer width={"100%"} height={150}>
|
||||||
|
<BarChart data={metrics30.data}>
|
||||||
|
<CartesianGrid strokeDasharay={"3 3"} />
|
||||||
|
<XAxis dataKey={(v) => v.timestamp} scale={"time"} tickFormatter={(v) => moment(v).format("MMM DD") } style={{ fontSize: '75%'}}/>
|
||||||
|
<YAxis tickFormatter={(v) => bytesToSize(v)} style={{ fontSize: '75%' }}/>
|
||||||
|
<Bar stroke={"#231069"} fill={"#04adef"} dataKey={"rx"} legendType={"circle"}/>
|
||||||
|
<Bar stroke={"#231069"} fill={"#9BF316"} dataKey={"tx"} />
|
||||||
|
<Tooltip />
|
||||||
|
</BarChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<h3>Last 7 Days:</h3>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col><p>Received: {bytesToSize(metrics7.rx)}</p></Col>
|
||||||
|
<Col><p>Sent: {bytesToSize(metrics7.tx)}</p></Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<ResponsiveContainer width={"100%"} height={150}>
|
||||||
|
<BarChart data={metrics7.data}>
|
||||||
|
<CartesianGrid strokeDasharay={"3 3"} />
|
||||||
|
<XAxis dataKey={(v) => v.timestamp} scale={"time"} tickFormatter={(v) => moment(v).format("MMM DD") } style={{ fontSize: '75%'}}/>
|
||||||
|
<YAxis tickFormatter={(v) => bytesToSize(v)} style={{ fontSize: '75%' }}/>
|
||||||
|
<Bar stroke={"#231069"} fill={"#04adef"} dataKey={"rx"} legendType={"circle"}/>
|
||||||
|
<Bar stroke={"#231069"} fill={"#9BF316"} dataKey={"tx"} />
|
||||||
|
<Tooltip />
|
||||||
|
</BarChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<h3>Last 24 Hours:</h3>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col><p>Received: {bytesToSize(metrics1.rx)}</p></Col>
|
||||||
|
<Col><p>Sent: {bytesToSize(metrics1.tx)}</p></Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<ResponsiveContainer width={"100%"} height={150}>
|
||||||
|
<BarChart data={metrics1.data}>
|
||||||
|
<CartesianGrid strokeDasharay={"3 3"} />
|
||||||
|
<XAxis dataKey={(v) => v.timestamp} scale={"time"} tickFormatter={(v) => moment(v).format("MMM DD") } style={{ fontSize: '75%'}}/>
|
||||||
|
<YAxis tickFormatter={(v) => bytesToSize(v)} style={{ fontSize: '75%' }}/>
|
||||||
|
<Bar stroke={"#231069"} fill={"#04adef"} dataKey={"rx"} legendType={"circle"}/>
|
||||||
|
<Bar stroke={"#231069"} fill={"#9BF316"} dataKey={"tx"} />
|
||||||
|
<Tooltip />
|
||||||
|
</BarChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MetricsTab;
|
33
ui/src/console/metrics.js
Normal file
33
ui/src/console/metrics.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export const buildMetrics = (m) => {
|
||||||
|
let metrics = {
|
||||||
|
data: m.samples,
|
||||||
|
rx: 0,
|
||||||
|
tx: 0
|
||||||
|
}
|
||||||
|
if(m.samples) {
|
||||||
|
m.samples.forEach(s => {
|
||||||
|
metrics.rx += s.rx;
|
||||||
|
metrics.tx += s.tx;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return metrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const bytesToSize = (sz) => {
|
||||||
|
let absSz = sz;
|
||||||
|
if(absSz < 0) {
|
||||||
|
absSz *= -1;
|
||||||
|
}
|
||||||
|
const unit = 1000
|
||||||
|
if(absSz < unit) {
|
||||||
|
return '' + absSz + ' B';
|
||||||
|
}
|
||||||
|
let div = unit
|
||||||
|
let exp = 0
|
||||||
|
for(let n = absSz / unit; n >= unit; n /= unit) {
|
||||||
|
div *= unit;
|
||||||
|
exp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '' + (sz / div).toFixed(1) + ' ' + "kMGTPE"[exp] + 'B';
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user