From 29e4a2cbf42287b74f51ac6f37508b280c8844dc Mon Sep 17 00:00:00 2001 From: snmatus Date: Mon, 6 Jan 2025 20:57:42 +0000 Subject: [PATCH] improve gui for aurora limitless --- conf/update.sh | 5 + frontend/public/version.json | 4 +- frontend/src/components/ChartArea03.js | 141 ++ frontend/src/components/ChartBar01.js | 6 +- frontend/src/components/ChartBar05.js | 150 ++ frontend/src/components/ChartLine04.js | 5 +- frontend/src/components/ChartLine05.js | 93 - frontend/src/components/ChartPolar-01.js | 24 +- frontend/src/components/ChartPolar-02.js | 93 + frontend/src/components/ChartSparkline01.js | 2 +- frontend/src/components/Functions.js | 6 + frontend/src/components/Metric01.js | 4 +- frontend/src/pages/Sm-aurora-postgresql-02.js | 1733 +++++++++++------ server/api.core.js | 26 + server/class.engine.js | 340 +++- 15 files changed, 1943 insertions(+), 689 deletions(-) create mode 100644 frontend/src/components/ChartArea03.js create mode 100644 frontend/src/components/ChartBar05.js create mode 100644 frontend/src/components/ChartPolar-02.js diff --git a/conf/update.sh b/conf/update.sh index 248a9bd..f2878a7 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -9,6 +9,11 @@ git clone https://github.com/GitHubRepository/db-top-monitoring.git cd db-top-monitoring sudo cp -r server frontend /aws/apps +#Copy aws-exports.json +cp /aws/apps/conf/aws-exports.json /aws/apps/frontend/public/ +cp /aws/apps/conf/aws-exports.json /aws/apps/server/ + + #React Application Installation cd /aws/apps/frontend/; npm install; npm run build; diff --git a/frontend/public/version.json b/frontend/public/version.json index 499baa2..479c175 100644 --- a/frontend/public/version.json +++ b/frontend/public/version.json @@ -1,4 +1,4 @@ { - "release": "0.1.1", - "date":"2023-09-01" + "release": "0.1.5", + "date":"2025-01-06" } diff --git a/frontend/src/components/ChartArea03.js b/frontend/src/components/ChartArea03.js new file mode 100644 index 0000000..2d5c4f6 --- /dev/null +++ b/frontend/src/components/ChartArea03.js @@ -0,0 +1,141 @@ +import {memo} from 'react'; +import Chart from 'react-apexcharts'; + +const ChartLine = memo(({series, categories,history, height, width="100%", title, border=2, stacked=false }) => { + + var options = { + chart: { + height: height, + type: 'area', + foreColor: '#9e9b9a', + stacked : stacked, + zoom: { + enabled: false + }, + animations: { + enabled: true, + }, + dynamicAnimation : + { + enabled: true, + }, + toolbar: { + show: false, + }, + dropShadow: { + enabled: false, + top: 2, + left: 2, + blur: 4, + opacity: 1, + } + + }, + markers: { + size: 5, + radius: 0, + strokeWidth: 2, + fillOpacity: 1, + shape: "circle", + }, + dataLabels: { + enabled: false + }, + legend: { + show: true, + showForSingleSeries: true, + fontSize: '11px', + fontFamily: 'Lato', + }, + theme: { + palette : "palette2", + monochrome: { + enabled: true + } + }, + stroke: { + curve: 'straight', + width: border + }, + title: { + text : title, + align: "center", + show: false, + style: { + fontSize: '14px', + fontWeight: 'bold', + fontFamily: 'Lato', + } + + }, + grid: { + show: false, + yaxis: { + lines: { + show: false + } + }, + xaxis: { + lines: { + show: false + } + } + }, + tooltip: { + theme: "dark", + x : { + format: 'HH:mm', + } + }, + xaxis: { + type: 'datetime', + labels: { + format: 'HH:mm', + style: { + fontSize: '11px', + fontFamily: 'Lato', + }, + } + }, + yaxis: { + tickAmount: 5, + axisTicks: { + show: true, + }, + axisBorder: { + show: true, + color: '#78909C', + offsetX: 0, + offsetY: 0 + }, + min : 0, + labels : { + formatter: function(val, index) { + + if(val === 0) return '0'; + if(val < 1000) return parseFloat(val).toFixed(1); + + var k = 1000, + sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'], + i = Math.floor(Math.log(val) / Math.log(k)); + return parseFloat((val / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; + + }, + style: { + fontSize: '11px', + fontFamily: 'Lato', + }, + }, + + } + }; + + + return ( +
+ +
+ ); +}); + +export default ChartLine; diff --git a/frontend/src/components/ChartBar01.js b/frontend/src/components/ChartBar01.js index f585b39..bd037cc 100644 --- a/frontend/src/components/ChartBar01.js +++ b/frontend/src/components/ChartBar01.js @@ -2,12 +2,13 @@ import {memo} from 'react'; import Chart from 'react-apexcharts'; -const ChartBar = memo(({series,history, height, width="100%", title, colors=[], border=2, timestamp }) => { +const ChartBar = memo(({series,history, height, width="100%", title, colors=[], border=2, timestamp, stacked=false }) => { var options = { chart: { height: height, type: 'bar', + stacked : stacked, foreColor: '#2ea597', zoom: { enabled: false @@ -33,6 +34,9 @@ const ChartBar = memo(({series,history, height, width="100%", title, colors=[], curve: 'smooth', width: 1 }, + theme: { + palette : "palette2" + }, markers: { size: 3, strokeWidth: 0, diff --git a/frontend/src/components/ChartBar05.js b/frontend/src/components/ChartBar05.js new file mode 100644 index 0000000..646a0e7 --- /dev/null +++ b/frontend/src/components/ChartBar05.js @@ -0,0 +1,150 @@ +import {memo} from 'react'; +import Chart from 'react-apexcharts'; + + +const ChartBar = memo(({series,history, height, width="100%", title, colors=[], border=2, timestamp, maximum=100 }) => { + + var options = { + chart: { + height: height, + type: 'bar', + foreColor: '#2ea597', + zoom: { + enabled: false + }, + animations: { + enabled: true, + easing: 'easeinout', + }, + dynamicAnimation : + { + enabled: true, + }, + toolbar: { + show: false, + } + + }, + dataLabels: { + enabled: false + }, + colors : colors, + stroke: { + curve: 'smooth', + width: 1 + }, + markers: { + size: 3, + strokeWidth: 0, + hover: { + size: 9 + } + }, + plotOptions: { + bar: { + borderRadius: 2, + + } + }, + tooltip: { + theme: "dark", + x : { + format: 'HH:mm', + } + }, + title: { + text : title, + align: "center", + show: false, + style: { + fontSize: '14px', + fontWeight: 'bold', + fontFamily: "Lato", + color : "#2ea597" + } + + }, + grid: { + show: false, + yaxis: { + lines: { + show: false + } + }, + xaxis: { + lines: { + show: false + } + } + }, + xaxis: { + type: 'datetime', + labels: { + format: 'HH:mm', + style: { + fontSize: '11px', + fontFamily: 'Lato', + }, + } + }, + yaxis: { + tickAmount: 5, + axisTicks: { + show: true, + }, + axisBorder: { + show: true, + color: '#78909C', + offsetX: 0, + offsetY: 0 + }, + min : 0, + max : maximum, + labels : { + formatter: function(val, index) { + + if(val === 0) return '0'; + if(val < 1000) return parseFloat(val).toFixed(0); + + var k = 1000, + sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'], + i = Math.floor(Math.log(val) / Math.log(k)); + return parseFloat((val / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; + + }, + style: { + fontSize: '11px', + fontFamily: 'Lato', + }, + }, + + }, + annotations: { + yaxis: [ + { + y: maximum, + strokeDashArray: 10, + borderColor: 'gray' + }, + ], + }, + }; + + function CustomFormatNumberData(value,decimalLength) { + if(value == 0) return '0'; + if(value < 1024) return parseFloat(value).toFixed(decimalLength); + + var k = 1024, + sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'], + i = Math.floor(Math.log(value) / Math.log(k)); + return parseFloat((value / Math.pow(k, i)).toFixed(decimalLength)) + ' ' + sizes[i]; + } + + return ( +
+ +
+ ); +}); + +export default ChartBar; diff --git a/frontend/src/components/ChartLine04.js b/frontend/src/components/ChartLine04.js index 8c42335..854cf62 100644 --- a/frontend/src/components/ChartLine04.js +++ b/frontend/src/components/ChartLine04.js @@ -1,13 +1,14 @@ import {memo} from 'react'; import Chart from 'react-apexcharts'; -const ChartLine = memo(({series, categories,history, height, width="100%", title, border=2 }) => { +const ChartLine = memo(({series, categories,history, height, width="100%", title, border=2, stacked = false }) => { var options = { chart: { height: height, type: 'line', - foreColor: '#9e9b9a', + foreColor: '#9e9b9a', + stacked : stacked, zoom: { enabled: false }, diff --git a/frontend/src/components/ChartLine05.js b/frontend/src/components/ChartLine05.js index ef9b130..90085af 100644 --- a/frontend/src/components/ChartLine05.js +++ b/frontend/src/components/ChartLine05.js @@ -206,96 +206,3 @@ const ChartLine = memo(({ series, p50, p90, p95, avg, max, height, width="100%", export default ChartLine; - -/* - -annotations: { - yaxis: [{ - y: 8200, - borderColor: '#00E396', - label: { - borderColor: '#00E396', - style: { - color: '#fff', - background: '#00E396', - }, - text: 'Support', - } - }, { - y: 8600, - y2: 9000, - borderColor: '#000', - fillColor: '#FEB019', - opacity: 0.2, - label: { - borderColor: '#333', - style: { - fontSize: '10px', - color: '#333', - background: '#FEB019', - }, - text: 'Y-axis range', - } - }], - xaxis: [{ - x: new Date('23 Nov 2017').getTime(), - strokeDashArray: 0, - borderColor: '#775DD0', - label: { - borderColor: '#775DD0', - style: { - color: '#fff', - background: '#775DD0', - }, - text: 'Anno Test', - } - }, { - x: new Date('26 Nov 2017').getTime(), - x2: new Date('28 Nov 2017').getTime(), - fillColor: '#B3F7CA', - opacity: 0.4, - label: { - borderColor: '#B3F7CA', - style: { - fontSize: '10px', - color: '#fff', - background: '#00E396', - }, - offsetY: -10, - text: 'X-axis range', - } - }], - points: [{ - x: new Date('01 Dec 2017').getTime(), - y: 8607.55, - marker: { - size: 8, - fillColor: '#fff', - strokeColor: 'red', - radius: 2, - cssClass: 'apexcharts-custom-class' - }, - label: { - borderColor: '#FF4560', - offsetY: 0, - style: { - color: '#fff', - background: '#FF4560', - }, - - text: 'Point Annotation', - } - }, { - x: new Date('08 Dec 2017').getTime(), - y: 9340.85, - marker: { - size: 0 - }, - image: { - path: '../../assets/images/ico-instagram.png' - } - }] - }, - - -*/ diff --git a/frontend/src/components/ChartPolar-01.js b/frontend/src/components/ChartPolar-01.js index b674538..7bb5d0f 100644 --- a/frontend/src/components/ChartPolar-01.js +++ b/frontend/src/components/ChartPolar-01.js @@ -1,7 +1,7 @@ import {memo} from 'react'; import Chart from 'react-apexcharts'; -const ChartComponent = memo(({ series, labels, title, height="350px", width="100%", onClickEvent }) => { +const ChartComponent = memo(({ series, labels, title="", height="350px", width="100%", onClickEvent }) => { function onClickChart(object){ onClickEvent(object); @@ -21,8 +21,23 @@ const ChartComponent = memo(({ series, labels, title, height="350px", width="100 }, }, + title: { + text : title, + align: "right", + show: false, + style: { + fontSize: '14px', + fontWeight: 'bold', + fontFamily: "Lato", + color : "#2ea597" + } + + }, theme: { - palette : "palette2" + palette : "palette2", + monochrome: { + enabled: true + } }, labels: labels, stroke: { @@ -40,16 +55,13 @@ const ChartComponent = memo(({ series, labels, title, height="350px", width="100 responsive: [{ breakpoint: 480, options: { - chart: { - width: 200 - }, legend: { position: 'bottom' } } }], yaxis: { - tickAmount: 5, + tickAmount: 3, axisTicks: { show: true, }, diff --git a/frontend/src/components/ChartPolar-02.js b/frontend/src/components/ChartPolar-02.js new file mode 100644 index 0000000..48ce52c --- /dev/null +++ b/frontend/src/components/ChartPolar-02.js @@ -0,0 +1,93 @@ +import {memo} from 'react'; +import Chart from 'react-apexcharts'; + +const ChartComponent = memo(({ series, labels, title="", height="350px", width="100%"}) => { + + var options = { + chart: { + type: 'polarArea', + foreColor: '#9e9b9a', + zoom: { + enabled: true, + }, + }, + title: { + text : title, + align: "right", + show: false, + style: { + fontSize: '14px', + fontWeight: 'bold', + fontFamily: "Lato", + color : "#2ea597" + } + + }, + theme: { + palette : "palette2", + monochrome: { + enabled: true + } + }, + labels: JSON.parse(labels), + stroke: { + colors: ['#fff'] + }, + fill: { + opacity: 0.8 + }, + legend: { + show: true, + showForSingleSeries: true, + fontSize: '11px', + fontFamily: 'Lato', + }, + responsive: [{ + breakpoint: 480, + options: { + legend: { + position: 'bottom' + } + } + }], + yaxis: { + tickAmount: 3, + axisTicks: { + show: true, + }, + axisBorder: { + show: true, + color: '#78909C', + offsetX: 0, + offsetY: 0 + }, + min : 0, + labels : { + formatter: function(val, index) { + + if(val === 0) return '0'; + if(val < 1000) return parseFloat(val).toFixed(1); + + var k = 1000, + sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'], + i = Math.floor(Math.log(val) / Math.log(k)); + return parseFloat((val / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; + + }, + style: { + fontSize: '11px', + fontFamily: 'Lato', + }, + }, + } + }; + + + return ( +
+ +
+ ); +}); + +export default ChartComponent; diff --git a/frontend/src/components/ChartSparkline01.js b/frontend/src/components/ChartSparkline01.js index 7eb93db..9947c44 100644 --- a/frontend/src/components/ChartSparkline01.js +++ b/frontend/src/components/ChartSparkline01.js @@ -1,7 +1,7 @@ import {memo} from 'react'; import Chart from 'react-apexcharts'; -const ChartLine = memo(({series,history, height="60px", width="100%", title, border=2, type="line" }) => { +const ChartLine = memo(({series, height="60px", width="100%", title, border=2, type="line" }) => { var options = { chart: { diff --git a/frontend/src/components/Functions.js b/frontend/src/components/Functions.js index 094383a..fc8b958 100644 --- a/frontend/src/components/Functions.js +++ b/frontend/src/components/Functions.js @@ -79,6 +79,12 @@ export function customFormatNumberShort(value,decimalLength) { } + export function customFormatNumberInteger(value) { + + return value.toLocaleString('en-US', {minimumFractionDigits:0, maximumFractionDigits:0}); + + } + export class classMetric { diff --git a/frontend/src/components/Metric01.js b/frontend/src/components/Metric01.js index b925d04..22a3b91 100644 --- a/frontend/src/components/Metric01.js +++ b/frontend/src/components/Metric01.js @@ -1,6 +1,6 @@ import {memo} from 'react'; -const Metric = memo(({ value, title, precision, format=1, fontSizeTitle = "11px", fontSizeValue = "22px", fontColorTitle = "#2ea597", fontColorValue = "orange" }) => { +const Metric = memo(({ value, title, precision, format=1, fontSizeTitle = "11px", fontSizeValue = "22px", fontColorTitle = "#2ea597", fontColorValue = "orange", postFix="" }) => { var counterValue = 0; @@ -71,7 +71,7 @@ const Metric = memo(({ value, title, precision, format=1, fontSizeTitle = "11px" return (
- {counterValue} + {counterValue}{postFix}
diff --git a/frontend/src/pages/Sm-aurora-postgresql-02.js b/frontend/src/pages/Sm-aurora-postgresql-02.js index 3c861da..2b48989 100644 --- a/frontend/src/pages/Sm-aurora-postgresql-02.js +++ b/frontend/src/pages/Sm-aurora-postgresql-02.js @@ -6,9 +6,11 @@ import CustomHeader from "../components/Header"; import AppLayout from "@cloudscape-design/components/app-layout"; import Box from "@cloudscape-design/components/box"; import Tabs from "@cloudscape-design/components/tabs"; -import ColumnLayout from "@cloudscape-design/components/column-layout"; import { SplitPanel } from '@cloudscape-design/components'; +import ProgressBar from "@cloudscape-design/components/progress-bar"; + +import Icon from "@cloudscape-design/components/icon"; import FormField from "@cloudscape-design/components/form-field"; import Select from "@cloudscape-design/components/select"; import Flashbar from "@cloudscape-design/components/flashbar"; @@ -17,21 +19,22 @@ import Spinner from "@cloudscape-design/components/spinner"; import SpaceBetween from "@cloudscape-design/components/space-between"; import Header from "@cloudscape-design/components/header"; import Container from "@cloudscape-design/components/container"; +import Toggle from "@cloudscape-design/components/toggle"; import CompMetric01 from '../components/Metric01'; import ChartLine02 from '../components/ChartLine02'; -import ChartColumn02 from '../components/ChartColumn02'; +import ChartSparkline01 from '../components/ChartSparkline01'; import Animation01 from '../components/Animation01'; import ChartLine04 from '../components/ChartLine04'; -import AuroraLimitlessNode from '../components/CompAuroraLimitlessNode01'; import ChartBar01 from '../components/ChartBar01'; import ChartBar03 from '../components/ChartBar03'; -import ChartPie01 from '../components/ChartPie-01'; +import ChartBar05 from '../components/ChartBar05'; import ChartRadialBar01 from '../components/ChartRadialBar01'; +import ChartPolar01 from '../components/ChartPolar-01'; +import ChartPolar02 from '../components/ChartPolar-02'; -import { createLabelFunction, customFormatNumberLong, customFormatNumber, customFormatNumberShort } from '../components/Functions'; +import { createLabelFunction, customFormatNumberLong, customFormatNumber, customFormatNumberShort, customFormatNumberInteger } from '../components/Functions'; import CustomTable02 from "../components/Table02"; - export const splitPanelI18nStrings: SplitPanelProps.I18nStrings = { preferencesTitle: 'Split panel preferences', preferencesPositionLabel: 'Split panel position', @@ -49,14 +52,13 @@ var CryptoJS = require("crypto-js"); function App() { + //--######## Global Settings //-- Connection Usage const [connectionMessage, setConnectionMessage] = useState([]); //-- Gather Parameters - const [params]=useSearchParams(); - - //--######## Global Settings + const [params]=useSearchParams(); //-- Variable for Active Tabs const [activeTabId, setActiveTabId] = useState("tab01"); @@ -91,8 +93,10 @@ function App() { //-- Variable for Split Panels const [splitPanelShow,setsplitPanelShow] = useState(false); - const [splitPanelSize, setSplitPanelSize] = useState(400); + const [splitPanelSize, setSplitPanelSize] = useState(500); var splitPanelIsShow = useRef(false); + const [stackedChart, setStackedChart] = useState(true); + @@ -162,7 +166,8 @@ function App() { }, }); - + + const currentNode = useRef({ nodeId : 0, nodeType : 'routers' } ); const metricCurrent = useRef({ nodeId : '', metricId : '', metricDescription : '', format : 3 } ); const [clusterStatsDetails,setClusterStatsDetails] = useState({ value : 0, history : []}); const [shardCloudwatchMetric,setShardCloudwatchMetric] = useState({ @@ -193,44 +198,77 @@ function App() { }); - //--Cloudwatch Metrics + //-- Storage Usage + const [storageUsage,setStorageUsage] = useState({ + chart : { categories : [], series : []} , + table : [] + }); + + + + //-- Cloudwatch Metrics const [selectedOptionInterval,setSelectedOptionInterval] = useState({label: "1 Hour",value: 1}); const optionInterval = useRef(1); - const [selectedOptionType,setSelectedOptionType] = useState({label: "All",value: "ALL"}); + const [selectedOptionType,setSelectedOptionType] = useState({label: "Shards + Routers",value: "ALL"}); const optionType = useRef("ALL"); + + const [selectedOptionTypeStorage,setSelectedOptionTypeStorage] = useState({label: "Shards + Routers",value: "ALL"}); + const optionTypeStorage = useRef("ALL"); + + + const cloudwatchMetrics = [ + { + label: "Cluster", + options: [ + { type : "3", label : "VolumeReadIops", value : "VolumeReadIops", descriptions : "The number of billed read I/O operations from a cluster volume, reported at 5-minute intervals.", unit : "Count", format : 3 }, + { type : "3", label : "VolumeWriteIops", value : "VolumeWriteIops", descriptions : "The number of write disk I/O operations to the cluster volume, reported at 5-minute intervals.", unit : "Count", format : 3 }, + { type : "3", label : "VolumeBytesUsed", value : "VolumeBytesUsed", descriptions : "The amount of storage used by your Aurora PostgreSQL Limitless Database cluster, reported at 5-minute intervals.", unit : "Count", format : 2 }, + ] + }, { label: "DBShard Group Instance", options: [ - { type : "1", label : "BufferCacheHitRatio", value : "BufferCacheHitRatio", descriptions : "The percentage of data and indexes served from an instance’s memory cache (as opposed to the storage volume).", unit : "Percentage" }, - { type : "1", label : "CommitLatency", value : "CommitLatency", descriptions : "The average duration for the engine and storage to complete the commit operations for a particular node (router or shard).", unit : "ms" }, - { type : "1", label : "CommitThroughput", value : "CommitThroughput", descriptions : "The average number of commit operations per second.", unit : "Count/sec" }, - { type : "1", label : "MaximumUsedTransactionIDs", value : "MaximumUsedTransactionIDs", descriptions : "The age of the oldest unvacuumed transaction ID, in transactions. If this value reaches 2,146,483,648 (2^31 - 1,000,000), the database is forced into read-only mode, to avoid transaction ID wraparound.", unit : "Count" }, - { type : "1", label : "NetworkReceiveThroughput", value : "NetworkReceiveThroughput", descriptions : "The amount of network throughput received from clients by each instance in the DB shard group. This throughput doesn't include network traffic between instances in the DB shard group and the cluster volume", unit : "Bytes/sec" }, - { type : "1", label : "NetworkThroughput", value : "NetworkThroughput", descriptions : "The aggregated network throughput (both transmitted and received) between clients and routers, and routers and shards in the DB shard group. This throughput doesn't include network traffic between instances in the DB shard group and the cluster volume.", unit : "Bytes/sec" }, - { type : "1", label : "NetworkTransmitThroughput", value : "NetworkTransmitThroughput", descriptions : "The amount of network throughput sent to clients by each instance in the DB shard group. This throughput doesn't include network traffic between instances in the DB shard group and the cluster volume.", unit : "COUNT" }, - { type : "1", label : "ReadIOPS", value : "ReadIOPS", descriptions : " The average number of disk read input/output operations per second (IOPS).", unit : "Count/sec" }, - { type : "1", label : "ReadLatency", value : "ReadLatency", descriptions : " The average amount time taken per disk read input/output (I/O) operation.", unit : "ms" }, - { type : "1", label : "ReadThroughput", value : "ReadThroughput", descriptions : "The average number of bytes read from disk per second.", unit : "Bytes/sec" }, - { type : "1", label : "StorageNetworkReceiveThroughput", value : "StorageNetworkReceiveThroughput", descriptions : "The amount of network throughput received from the Aurora storage subsystem by each instance in the DB shard group.", unit : "Bytes/sec" }, - { type : "1", label : "StorageNetworkThroughput", value : "StorageNetworkThroughput", descriptions : "The aggregated network throughput both transmitted to and received from the Aurora storage subsystem by each instance in the DB shard group.", unit : "Bytes/sec" }, - { type : "1", label : "StorageNetworkTransmitThroughput", value : "StorageNetworkTransmitThroughput", descriptions : "The amount of network throughput sent to the Aurora storage subsystem by each instance in the DB shard group.", unit : "Bytes/sec" }, - { type : "1", label : "TempStorageIOPS", value : "TempStorageIOPS", descriptions : "The average number of I/O operations performed on local storage attached to the DB instance. It includes both read and write I/O operations.", unit : "Count/sec" }, - { type : "1", label : "TempStorageThroughput", value : "TempStorageThroughput", descriptions : "The amount of data transferred to and from local storage associated with either a router or a shard.", unit : "Bytes/sec" }, - { type : "1", label : "WriteIOPS", value : "WriteIOPS", descriptions : "The average number of disk write IOPS.", unit : "Count/sec" }, - { type : "1", label : "WriteLatency", value : "WriteLatency", descriptions : " The average amount time taken per disk write I/O operation.", unit : "ms" }, - { type : "1", label : "WriteThroughput", value : "WriteThroughput", descriptions : "The average number of bytes written to disk per second.", unit : "Bytes/sec" }, + { type : "1", label : "BufferCacheHitRatio", value : "BufferCacheHitRatio", descriptions : "The percentage of data and indexes served from an instance’s memory cache (as opposed to the storage volume).", unit : "Percentage", format : 3 }, + { type : "1", label : "CommitLatency", value : "CommitLatency", descriptions : "The average duration for the engine and storage to complete the commit operations for a particular node (router or shard).", unit : "ms", format : 3 }, + { type : "1", label : "CommitThroughput", value : "CommitThroughput", descriptions : "The average number of commit operations per second.", unit : "Count/sec", format : 3 }, + { type : "1", label : "DBLoad", value : "DBLoad", descriptions : "The number of active sessions for the database.", unit : "Count", format : 3 }, + { type : "1", label : "DBLoadCPU", value : "DBLoadCPU", descriptions : "The number of active sessions where the wait event type is CPU.", unit : "Count", format : 3 }, + { type : "1", label : "DBLoadNonCPU", value : "DBLoadNonCPU", descriptions : "The number of active sessions where the wait event type is not CPU.", unit : "Count", format : 3 }, + { type : "1", label : "DBLoadRelativeToNumVCPUs", value : "DBLoadRelativeToNumVCPUs", descriptions : "The ratio of the DB load to the number of virtual CPUs for the database.", unit : "Count", format : 3 }, + { type : "1", label : "MaximumUsedTransactionIDs", value : "MaximumUsedTransactionIDs", descriptions : "The age of the oldest unvacuumed transaction ID, in transactions. If this value reaches 2,146,483,648 (2^31 - 1,000,000), the database is forced into read-only mode, to avoid transaction ID wraparound.", unit : "Count", format : 3 }, + { type : "1", label : "NetworkReceiveThroughput", value : "NetworkReceiveThroughput", descriptions : "The amount of network throughput received from clients by each instance in the DB shard group. This throughput doesn't include network traffic between instances in the DB shard group and the cluster volume", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "NetworkThroughput", value : "NetworkThroughput", descriptions : "The aggregated network throughput (both transmitted and received) between clients and routers, and routers and shards in the DB shard group. This throughput doesn't include network traffic between instances in the DB shard group and the cluster volume.", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "NetworkTransmitThroughput", value : "NetworkTransmitThroughput", descriptions : "The amount of network throughput sent to clients by each instance in the DB shard group. This throughput doesn't include network traffic between instances in the DB shard group and the cluster volume.", unit : "Count", format : 2 }, + { type : "1", label : "ReadIOPS", value : "ReadIOPS", descriptions : " The average number of disk read input/output operations per second (IOPS).", unit : "Count/sec", format : 3 }, + { type : "1", label : "ReadLatency", value : "ReadLatency", descriptions : " The average amount time taken per disk read input/output (I/O) operation.", unit : "ms", format : 3 }, + { type : "1", label : "ReadThroughput", value : "ReadThroughput", descriptions : "The average number of bytes read from disk per second.", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "StorageNetworkReceiveThroughput", value : "StorageNetworkReceiveThroughput", descriptions : "The amount of network throughput received from the Aurora storage subsystem by each instance in the DB shard group.", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "StorageNetworkThroughput", value : "StorageNetworkThroughput", descriptions : "The aggregated network throughput both transmitted to and received from the Aurora storage subsystem by each instance in the DB shard group.", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "StorageNetworkTransmitThroughput", value : "StorageNetworkTransmitThroughput", descriptions : "The amount of network throughput sent to the Aurora storage subsystem by each instance in the DB shard group.", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "TempStorageIOPS", value : "TempStorageIOPS", descriptions : "The average number of I/O operations performed on local storage attached to the DB instance. It includes both read and write I/O operations.", unit : "Count/sec", format : 3 }, + { type : "1", label : "TempStorageThroughput", value : "TempStorageThroughput", descriptions : "The amount of data transferred to and from local storage associated with either a router or a shard.", unit : "Bytes/sec", format : 2 }, + { type : "1", label : "WriteIOPS", value : "WriteIOPS", descriptions : "The average number of disk write IOPS.", unit : "Count/sec", format : 3 }, + { type : "1", label : "WriteLatency", value : "WriteLatency", descriptions : " The average amount time taken per disk write I/O operation.", unit : "ms", format : 3 }, + { type : "1", label : "WriteThroughput", value : "WriteThroughput", descriptions : "The average number of bytes written to disk per second.", unit : "Bytes/sec", format : 2 }, ] }, { label: "DBShard Group", options: [ - { type : "2", label : "DBShardGroupACUUtilization", value : "DBShardGroupACUUtilization", descriptions : "Aurora capacity unit (ACU) usage as a percentage calculated from DBShardGroupCapacity divided by DBShardGroupMaxACU.", unit : "Percentage" }, - { type : "2", label : "DBShardGroupCapacity", value : "DBShardGroupCapacity", descriptions : "Number of ACUs consumed by the DB shard group.The average duration for the engine and storage to complete the commit operations for a particular node (router or shard).", unit : "Count" }, - { type : "2", label : "DBShardGroupMaxACU", value : "DBShardGroupMaxACU", descriptions : "Maximum number of ACUs configured for the DB shard group.", unit : "Count" }, - { type : "2", label : "DBShardGroupMinACU", value : "DBShardGroupMinACU", descriptions : "Minimum number of ACUs required by the DB shard group.", unit : "Count" }, + { type : "2", label : "DBShardGroupACUUtilization", value : "DBShardGroupACUUtilization", descriptions : "Aurora capacity unit (ACU) usage as a percentage calculated from DBShardGroupCapacity divided by DBShardGroupMaxACU.", unit : "Percentage", format : 3 }, + { type : "2", label : "DBShardGroupCapacity", value : "DBShardGroupCapacity", descriptions : "Number of ACUs consumed by the DB shard group.The average duration for the engine and storage to complete the commit operations for a particular node (router or shard).", unit : "Count", format : 3 }, + { type : "2", label : "DBShardGroupMaxACU", value : "DBShardGroupMaxACU", descriptions : "Maximum number of ACUs configured for the DB shard group.", unit : "Count", format : 3 }, + { type : "2", label : "DBShardGroupMinACU", value : "DBShardGroupMinACU", descriptions : "Minimum number of ACUs required by the DB shard group.", unit : "Count", format : 3 }, + ] + }, + { + label: "DBShard Group Router", + options: [ + { type : "4", label : "CommitThroughput", value : "CommitThroughput", descriptions : "The average number of commit operations per second across all of the router nodes in the DB shard group.", unit : "Count", format : 3 }, + { type : "4", label : "DatabaseConnections", value : "DatabaseConnections", descriptions : "The sum of all connections across all of the router nodes in the DB shard group.", unit : "Count", format : 3 }, ] } ]; @@ -239,7 +277,7 @@ function App() { label: "CommitThroughput", value: "CommitThroughput" }); - const cloudwatchMetric = useRef({ type : "1", name : "CommitThroughput", descriptions : "The average number of commit operations per second.", unit : "Count/sec" }); + const cloudwatchMetric = useRef({ type : "1", name : "CommitThroughput", descriptions : "The average number of commit operations per second.", unit : "Count/sec", format : 2 }); var metricName = useRef(""); @@ -250,6 +288,10 @@ function App() { {id: 'BufferCacheHitRatio',header: 'BufferCacheHitRatio',cell: item => item['BufferCacheHitRatio'],ariaLabel: createLabelFunction('BufferCacheHitRatio'),sortingField: 'BufferCacheHitRatio',}, {id: 'CommitLatency',header: 'CommitLatency',cell: item => customFormatNumberShort(parseFloat(item['CommitLatency']),0),ariaLabel: createLabelFunction('CommitLatency'),sortingField: 'CommitLatency',}, {id: 'CommitThroughput',header: 'CommitThroughput',cell: item => customFormatNumberShort(parseFloat(item['CommitThroughput']),0) ,ariaLabel: createLabelFunction('CommitThroughput'),sortingField: 'CommitThroughput',}, + {id: 'DBLoad',header: 'DBLoad',cell: item => customFormatNumberShort(parseFloat(item['DBLoad']),0) ,ariaLabel: createLabelFunction('DBLoad'),sortingField: 'DBLoad',}, + {id: 'DBLoadCPU',header: 'DBLoadCPU',cell: item => customFormatNumberShort(parseFloat(item['DBLoadCPU']),0) ,ariaLabel: createLabelFunction('DBLoadCPU'),sortingField: 'DBLoadCPU',}, + {id: 'DBLoadNonCPU',header: 'DBLoadNonCPU',cell: item => customFormatNumberShort(parseFloat(item['DBLoadNonCPU']),0) ,ariaLabel: createLabelFunction('DBLoadNonCPU'),sortingField: 'DBLoadNonCPU',}, + {id: 'DBLoadRelativeToNumVCPUs',header: 'DBLoadRelativeToNumVCPUs',cell: item => customFormatNumberShort(parseFloat(item['DBLoadRelativeToNumVCPUs']),0) ,ariaLabel: createLabelFunction('DBLoadRelativeToNumVCPUs'),sortingField: 'DBLoadRelativeToNumVCPUs',}, {id: 'ReadIOPS',header: 'ReadIOPS',cell: item => customFormatNumberShort(parseFloat(item['ReadIOPS']) || 0 ,0),ariaLabel: createLabelFunction('ReadIOPS') || 0,sortingField: 'ReadIOPS',}, {id: 'WriteIOPS',header: 'WriteIOPS',cell: item => customFormatNumberShort(parseFloat(item['WriteIOPS']) || 0,0),ariaLabel: createLabelFunction('WriteIOPS') || 0,sortingField: 'WriteIOPS',}, {id: 'ReadLatency',header: 'ReadLatency',cell: item => customFormatNumberShort(parseFloat(item['ReadLatency']),0),ariaLabel: createLabelFunction('ReadLatency'),sortingField: 'ReadLatency',}, @@ -262,20 +304,118 @@ function App() { {id: 'StorageNetworkReceiveThroughput',header: 'StorageNetworkReceiveThroughput',cell: item => customFormatNumber(parseFloat(item['StorageNetworkReceiveThroughput']) || 0 ,0) ,ariaLabel: createLabelFunction('StorageNetworkReceiveThroughput'),sortingField: 'StorageNetworkReceiveThroughput',}, {id: 'StorageNetworkThroughput',header: 'StorageNetworkThroughput',cell: item => customFormatNumber(parseFloat(item['StorageNetworkThroughput']) || 0,0) ,ariaLabel: createLabelFunction('StorageNetworkThroughput'),sortingField: 'StorageNetworkThroughput',}, {id: 'StorageNetworkTransmitThroughput',header: 'StorageNetworkTransmitThroughput',cell: item => customFormatNumber(parseFloat(item['StorageNetworkTransmitThroughput']) || 0,0) ,ariaLabel: createLabelFunction('StorageNetworkTransmitThroughput'),sortingField: 'ReadThStorageNetworkTransmitThroughputroughput',}, - ]; - const visibleContent = ['resource', 'type', 'CommitThroughput', 'ReadIOPS', 'WriteIOPS', 'NetworkThroughput', 'ReadThroughput', 'StorageNetworkThroughput', 'WriteThroughput']; + const visibleContent = ['resource', 'type', 'DBLoad', 'CommitThroughput', 'ReadIOPS', 'WriteIOPS', 'NetworkThroughput', 'ReadThroughput', 'StorageNetworkThroughput', 'WriteThroughput']; const [shardMetrics,setShardMetrics] = useState({ tableMetrics : [] , tableSummary : {}, - chartSummary : { categories : [], data : [] }, - chartHistory : { CommitThroughput : [], DBShardGroupACUUtilization : [], DBShardGroupCapacity : [] } + chartSummary : { + CommitThroughput : { categories : [], data : [] }, + DBLoad : { categories : [], data : [] }, + CommitLatency : { categories : [], data : [] }, + }, + chartHistory : { CommitThroughput : [], DBLoad : [], DBShardGroupACUUtilization : [], DBShardGroupCapacity : [] }, + chartGlobal : { CommitThroughput : [] , DBLoad : [] }, }); - //-- Function Open connection + //-- Table Routers globally + const columnsTableRoutersGlobal = [ + {id: 'name',header: 'Name',cell: item => item['name'] ,ariaLabel: createLabelFunction('name'),sortingField: 'name',}, + {id: 'numbackends',header: 'Users',cell: item => (
+ + + + +   + {customFormatNumberInteger(parseFloat(item['numbackends']))} + +
) ,ariaLabel: createLabelFunction('numbackends'),sortingField: 'numbackends',}, + {id: 'commitThroughput',header: 'CommitThroughput',cell: item => (
+ + {customFormatNumberInteger(parseFloat(item['xactCommit']))} + + +
) ,ariaLabel: createLabelFunction('xactCommit'),sortingField: 'xactCommit',}, + + {id: 'vcpu',header: 'vCPU',cell: item => (
+ + + + +   + {customFormatNumberInteger(parseFloat(item['vcpu']))} + +
) ,ariaLabel: createLabelFunction('vcpu'),sortingField: 'vcpu',}, + {id: 'numbackendsActive',header: 'ActiveSessions',cell: item => customFormatNumberInteger(parseFloat(item['numbackendsActive'])) ,ariaLabel: createLabelFunction('numbackendsActive'),sortingField: 'numbackendsActive',}, + {id: 'totalIOPS',header: 'IOPS',cell: item => (
+ + + + + + +   + {customFormatNumberInteger(parseFloat(item['totalIOPS']))} + +
) ,ariaLabel: createLabelFunction('totalIOPS'),sortingField: 'totalIOPS',}, + {id: 'totalNetworkBytes',header: 'Network',cell: item => (
+ + + + + +   + {customFormatNumber(parseFloat(item['totalNetworkBytes']))} + +
) ,ariaLabel: createLabelFunction('totalNetworkBytes'),sortingField: 'totalNetworkBytes',}, + {id: 'totalIOBytes',header: 'IOBytes',cell: item => customFormatNumber(parseFloat(item['totalIOBytes']),0) ,ariaLabel: createLabelFunction('totalIOBytes'),sortingField: 'totalIOBytes',}, + {id: 'tuples',header: 'Tuples',cell: item => customFormatNumberInteger(parseFloat(item['tuples'])) ,ariaLabel: createLabelFunction('tuples'),sortingField: 'tuples',}, + {id: 'tuplesRead',header: 'TuplesRead',cell: item => customFormatNumberInteger(parseFloat(item['tuplesRead'])) ,ariaLabel: createLabelFunction('tuplesRead'),sortingField: 'tuplesRead',}, + {id: 'tuplesWritten',header: 'TuplesWritten',cell: item => customFormatNumberInteger(parseFloat(item['tuplesWritten'])) ,ariaLabel: createLabelFunction('tuplesWritten'),sortingField: 'tuplesWritten',}, + ]; + + const visibleContentRoutersGlobal = ['name', 'vcpu', 'commitThroughput', 'numbackends', 'totalIOPS', 'totalNetworkBytes']; + + + //-- Table Storage Usage + const columnsStorageTable = [ + {id: 'name',header: 'Identifier',cell: item => item['name'],ariaLabel: createLabelFunction('name'),sortingField: 'name',}, + {id: 'type',header: 'Type',cell: item => item['type'],ariaLabel: createLabelFunction('type'),sortingField: 'type',}, + {id: 'size',header: 'Size',cell: item => customFormatNumber(parseFloat(item['size']) || 0 ,0) ,ariaLabel: createLabelFunction('size'),sortingField: 'size',}, + {id: 'pct',header: '(%)',cell: item => (
+ +
) ,ariaLabel: createLabelFunction('pct'),sortingField: 'pct',}, + ]; + + const visibleContentStorageTable = ['name', 'type', 'size', 'pct']; + + + //-- Table Proccesses + + const columnsTableEm = [ + {id: 'id',header: 'PID',cell: item => item['id'],ariaLabel: createLabelFunction('id'),sortingField: 'id',}, + {id: 'parentID',header: 'ParentPID',cell: item => item['parentID'] || "-",ariaLabel: createLabelFunction('parentID'),sortingField: 'parentID',}, + {id: 'name',header: 'Name',cell: item => item['name'],ariaLabel: createLabelFunction('name'),sortingField: 'name',}, + {id: 'cpuUsedPc',header: 'CPU',cell: item => item['cpuUsedPc'] || "-",ariaLabel: createLabelFunction('cpuUsedPc'),sortingField: 'cpuUsedPc',}, + {id: 'memoryUsedPc',header: 'Memory',cell: item => item['memoryUsedPc'],ariaLabel: createLabelFunction('memoryUsedPc'),sortingField: 'memoryUsedPc',}, + {id: 'rss',header: 'RSS',cell: item => item['rss'],ariaLabel: createLabelFunction('rss'),sortingField: 'rss',}, + {id: 'vmlimit',header: 'VMLimit',cell: item => item['vmlimit'],ariaLabel: createLabelFunction('vmlimit'),sortingField: 'vmlimit',}, + {id: 'vss',header: 'VSS',cell: item => item['vss'],ariaLabel: createLabelFunction('vss'),sortingField: 'vss',}, + {id: 'tgid',header: 'TGID',cell: item => item['tgid'],ariaLabel: createLabelFunction('tgid'),sortingField: 'tgid',} + ]; + + const visibleContentEm = ['id', 'parentID', 'name', 'cpuUsedPc', 'memoryUsedPc', 'rss', 'vmlimit', 'vss', 'tgid' ]; + + + + + + //-- Function open connection async function openClusterConnection() { var api_url = configuration["apps-settings"]["api_url"]; @@ -321,9 +461,9 @@ function App() { //-- Function Cluster Gather Stats async function gatherClusterStats() { - //-- API CALL 1 + //-- API - 01 - Gather Stats var localClusterStats = {}; - if ( currentTabId.current == "tab01" || currentTabId.current == "tab02" || currentTabId.current == "tab03" ) { + if ( currentTabId.current == "tab01" || currentTabId.current == "tab02" || currentTabId.current == "tab03" || currentTabId.current == "tab04" ) { var api_url = configuration["apps-settings"]["api_url"]; @@ -332,13 +472,9 @@ function App() { clusterId : cnf_identifier, engineType : cnf_engine } - }).then((data)=>{ - + }).then((data)=>{ var info = data.data.cluster; - localClusterStats = { cluster : {...info} }; - - //setClusterStats({ cluster : {...info} }); - + localClusterStats = { cluster : {...info} }; }) .catch((err) => { console.log('Timeout API Call : /api/aurora/cluster/postgresql/limitless/gather/stats/' ); @@ -348,11 +484,11 @@ function App() { } - //-- API CALL 2 + //-- API - 02 - Gather stats details var localClusterStatsDetails = {}; if ( currentTabId.current == "tab01" && splitPanelIsShow.current === true ) { - - + + /* var api_url = configuration["apps-settings"]["api_url"]; await Axios.get(`${api_url}/api/aurora/cluster/postgresql/limitless/gather/stats/details`,{ @@ -361,8 +497,7 @@ function App() { engineType : cnf_engine, metricId : metricCurrent.current['metricId'] } - }).then((data)=>{ - //setClusterStatsDetails({ ...data.data }); + }).then((data)=>{ localClusterStatsDetails = { ...data.data }; }) .catch((err) => { @@ -370,12 +505,13 @@ function App() { console.log(err); }); + */ } - //-- API CALL 3 + //-- API - 03 - Gather Cloudwatch var localShardCloudwatchMetricAnalytics = {}; if ( currentTabId.current == "tab03" ) { @@ -392,9 +528,8 @@ function App() { stat : "Average", resourceType : optionType.current, } - }).then((data)=>{ + }).then((data)=>{ - //setShardCloudwatchMetric({... data.data }); localShardCloudwatchMetricAnalytics = {... data.data }; }) @@ -406,7 +541,7 @@ function App() { } - //-- API CALL : 4 + //-- API - 04 - Gather Cloudwatch var localShardMetrics = {}; if ( currentTabId.current == "tab02" ) { var api_url = configuration["apps-settings"]["api_url"]; @@ -416,10 +551,8 @@ function App() { clusterId : cnf_identifier, engineType : cnf_engine, } - }).then((data)=>{ - - //setShardMetrics({... data.data }); - localShardMetrics = {... data.data }; + }).then((data)=>{ + localShardMetrics = {... data.data }; }) .catch((err) => { console.log('Timeout API Call : /api/aurora/cluster/postgresql/limitless/shard/gather/cloudwatch/metrics/table' ); @@ -429,7 +562,7 @@ function App() { } - //-- API CALL 5 + //-- API - 05 - Gather Cloudwatch var localShardCloudwatchMetric = {}; if ( currentTabId.current == "tab02" && splitPanelIsShow.current === true ) { var api_url = configuration["apps-settings"]["api_url"]; @@ -445,8 +578,7 @@ function App() { stat : "Average", resourceType : "ALL", } - }).then((data)=>{ - //setShardCloudwatchMetric({... data.data }); + }).then((data)=>{ localShardCloudwatchMetric = {... data.data }; }) .catch((err) => { @@ -457,7 +589,6 @@ function App() { } - if (Object.keys(localClusterStats).length > 0) setClusterStats(localClusterStats); @@ -474,9 +605,31 @@ function App() { setShardCloudwatchMetric(localShardCloudwatchMetric); - - + } + + //-- Gather Storage Usage + async function gatherStorageUsage(){ + + if ( currentTabId.current == "tab04" ) { + var api_url = configuration["apps-settings"]["api_url"]; + + await Axios.get(`${api_url}/api/aurora/cluster/postgresql/limitless/gather/storage/info`,{ + params: { connectionId : cnf_connection_id, + clusterId : cnf_identifier, + engineType : cnf_engine, + type : optionTypeStorage.current, + } + }).then((data)=>{ + console.log(data.data); + setStorageUsage({... data.data }); + }) + .catch((err) => { + console.log('Timeout API Call : /api/aurora/cluster/postgresql/limitless/gather/storage/info' ); + console.log(err); + }); + + } } @@ -506,7 +659,6 @@ function App() { case 'other': break; - } @@ -591,117 +743,242 @@ function App() { } } + header={ +
+ + { splitPanelIsShow.current === true && currentTabId.current == "tab02" && +
+ {metricName.current} +
+ } + { splitPanelIsShow.current === true && currentTabId.current == "tab01" && +
+ {(currentNode.current['type'] == "routers" ? "Router : " : "Shard : ") } + {clusterStats['cluster'][currentNode.current['type']][currentNode.current['nodeId']]?.['name']} +
+ } +
+ + } > - { splitPanelIsShow.current === true && currentTabId.current == "tab01" && - - - - - - - -
- - - -
+ { splitPanelIsShow.current === true && currentTabId.current == "tab01" && + +
+ + Performance + + } + > + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ } { splitPanelIsShow.current === true && currentTabId.current == "tab02" && -
+
+ + + + +
+ + setStackedChart(detail.checked) + } + checked={stackedChart} + > + Stacked + + +
- - - -
- {}} - /> - + + + + + + + + + + +
+ + + + + + + + + +
-
-
- - - - - - - - -
- - - + stacked={stackedChart} + /> - - - - - -
+
- } @@ -711,7 +988,7 @@ function App() { - - - + - - - @@ -754,6 +1031,7 @@ function App() { currentTabId.current=detail.activeTabId; setActiveTabId(detail.activeTabId); setsplitPanelShow(false); + gatherStorageUsage(); gatherGlobalStats(); } @@ -766,28 +1044,31 @@ function App() { content:
- - Aurora Cluster - - } - > +
+ { clusterStats['cluster']['status'] != 'available' && @@ -719,27 +996,27 @@ function App() { {parameter_object_values['rds_host']} - {clusterStats['cluster']['status']} - Status - +
{clusterStats['cluster']['shardId']}
ShardIdentifier
+ {clusterStats['cluster']['status']} + Status +
{clusterStats['cluster']?.['metrics']?.['vcpu'] || 0}
vCPU
+
{clusterStats['cluster']['minACU']}
MinACU
+
{clusterStats['cluster']['maxACU']}
MaxACU
+
{clusterStats['cluster']['lastUpdate']}
LastUpdate
-
- + + + Cluster + + } + > + Commit Throughput + + + - +
- {}} - /> +
+
+
+
+
+ +
-
-
- - +
+
-

@@ -940,7 +1241,7 @@ function App() {
+ } > -
- - Distributed transaction routers - - } - > - - - - -
- - {clusterStats['cluster']['routers'].map((item,key) => ( - { - metricCurrent.current = detail; - splitPanelIsShow.current = true; - setsplitPanelShow(true); - gatherGlobalStats(); - } - } - /> - ))} - -
-
- -
-
+
+ { + currentNode.current['nodeId'] = item[0]['indexId']; + currentNode.current['type'] = 'routers'; + splitPanelIsShow.current = true; + setsplitPanelShow(true); + + } + } + /> +
{/*----ROUTING LAYER */} @@ -1017,49 +1302,25 @@ function App() {
- {/**----- DATA SHARD LAYER */} -
- - Data access shards - - } - > - - - - - - - - - -
-
- - {clusterStats['cluster']['shards'].map((item,key) => ( - { - metricCurrent.current = detail; - splitPanelIsShow.current = true; - setsplitPanelShow(true); - gatherGlobalStats(); - } - } - /> - ))} - -
-
- -
- -
+
+ { + currentNode.current['nodeId'] = item[0]['indexId']; + currentNode.current['type'] = 'shards'; + splitPanelIsShow.current = true; + setsplitPanelShow(true); + + } + } + /> +
@@ -1079,249 +1340,458 @@ function App() { content:
- - - - - - - + + +
- - - - - - + Capacity + + } + > + + + + - - + + + + +
+ + + + - - - - + + + + + +
+ +
+
+ + DBLoad + + } + > + + + + - - - -
+ + + + onClickMetric({ metricName : "DBLoad" })}> + + + - -
- - - - - - -
- onClickMetric({ metricName : "CommitThroughput" })}> - - - - -
- - - - - - - - - - - - - - - - -
- onClickMetric({ metricName : "ReadIOPS" })}> - - - - onClickMetric({ metricName : "WriteIOPS" })}> - - - - onClickMetric({ metricName : "ReadThroughput" })}> - - - - onClickMetric({ metricName : "WriteThroughput" })}> - - - - onClickMetric({ metricName : "NetworkThroughput" })}> - - - - onClickMetric({ metricName : "NetworkTransmitThroughput" })}> - - - - onClickMetric({ metricName : "NetworkReceiveThroughput" })}> - - - - onClickMetric({ metricName : "StorageNetworkThroughput" })}> - - - - onClickMetric({ metricName : "StorageNetworkTransmitThroughput" })}> - - - - onClickMetric({ metricName : "StorageNetworkReceiveThroughput" })}> - - -
+ + +
+ + + + + + + + + +
+ onClickMetric({ metricName : "DBLoadCPU" })}> + + + + onClickMetric({ metricName : "DBLoadNonCPU" })}> + + + + onClickMetric({ metricName : "DBLoadRelativeToNumVCPUs" })}> + + + +
+
+
+ + Throughput + + } + > + + + + + +
+ + + + + + onClickMetric({ metricName : "CommitThroughput" })}> + + + + +
+ + + + + + + + + + + + + + + + +
+ onClickMetric({ metricName : "ReadIOPS" })}> + + + + onClickMetric({ metricName : "WriteIOPS" })}> + + + + onClickMetric({ metricName : "ReadThroughput" })}> + + + + onClickMetric({ metricName : "WriteThroughput" })}> + + + + onClickMetric({ metricName : "NetworkThroughput" })}> + + + + onClickMetric({ metricName : "NetworkTransmitThroughput" })}> + + + + onClickMetric({ metricName : "NetworkReceiveThroughput" })}> + + + + onClickMetric({ metricName : "StorageNetworkThroughput" })}> + + + + onClickMetric({ metricName : "StorageNetworkTransmitThroughput" })}> + + + + onClickMetric({ metricName : "StorageNetworkReceiveThroughput" })}> + + +
+
+ +
+ + Latency + + } + > + + + + + + +
+ + + + onClickMetric({ metricName : "CommitLatency" })}> + + + + +
+ - -
+ + + + + + + +
+ onClickMetric({ metricName : "DBLoadCPU" })}> + + + + onClickMetric({ metricName : "DBLoadNonCPU" })}> + + + +
+ +
- - - - -
- - -
+
@@ -1346,7 +1816,7 @@ function App() {
+ { cloudwatchMetric.current.type == "1" && + + + { - optionType.current = detail.selectedOption.value; - setSelectedOptionType(detail.selectedOption); - gatherGlobalStats(); - }} - options={[ - { label: "Shards + Routers", value: "ALL" }, - { label: "Shards", value: "DAS" }, - { label: "Routers", value: "DTR" } - ]} - /> - - + + } @@ -1416,7 +1887,7 @@ function App() { - - @@ -1490,9 +1964,9 @@ function App() { value={ shardCloudwatchMetricAnalytics['summary']?.['max'] || 0 } title={"Maximum"} precision={2} - format={3} + format={cloudwatchMetric.current.format} fontColorValue={configuration.colors.fonts.metric100} - fontSizeValue={"30px"} + fontSizeValue={"26px"} fontSizeTitle={"12px"} /> @@ -1502,9 +1976,9 @@ function App() { value={ shardCloudwatchMetricAnalytics['summary']?.['min']|| 0 } title={"Minimum"} precision={2} - format={3} + format={cloudwatchMetric.current.format} fontColorValue={configuration.colors.fonts.metric100} - fontSizeValue={"30px"} + fontSizeValue={"26px"} fontSizeTitle={"12px"} /> @@ -1515,7 +1989,7 @@ function App() { precision={0} format={3} fontColorValue={configuration.colors.fonts.metric100} - fontSizeValue={"30px"} + fontSizeValue={"26px"} fontSizeTitle={"12px"} /> @@ -1524,9 +1998,9 @@ function App() { value={ shardCloudwatchMetricAnalytics['summary']?.['total'] || 0 } title={"Total"} precision={0} - format={4} + format={cloudwatchMetric.current.format} fontColorValue={configuration.colors.fonts.metric100} - fontSizeValue={"30px"} + fontSizeValue={"26px"} fontSizeTitle={"12px"} /> @@ -1536,19 +2010,11 @@ function App() {
+
- - {/* - - */} - {}} - /> + series = {JSON.stringify(shardCloudwatchMetricAnalytics['currentState']?.['chart']?.['data'])} + labels = {JSON.stringify(shardCloudwatchMetricAnalytics['currentState']?.['chart']?.['categories'])} + /> +

+ + setStackedChart(detail.checked) + } + checked={stackedChart} + > + Stacked + + } > Historical @@ -1479,9 +1953,9 @@ function App() { value={ shardCloudwatchMetricAnalytics['summary']?.['average'] || 0 } title={"Average"} precision={2} - format={3} + format={cloudwatchMetric.current.format} fontColorValue={configuration.colors.fonts.metric100} - fontSizeValue={"30px"} + fontSizeValue={"26px"} fontSizeTitle={"12px"} />
- - @@ -1559,6 +2025,139 @@ function App() {
- {}} - /> - +
+ }, + { + label: "Storage Usage", + id: "tab04", + content: +
+
+ + Storage summary + + } + > +
+ + + + + + + +
+ + + + + + + + +
+
+ +
+ + Storage analysis ({selectedOptionTypeStorage['label'] }) + + } + + > + + + + + + +
+ + + + Storage distribution +
+
+ + +
+
+ +
+
+ +
+ }, ]} diff --git a/server/api.core.js b/server/api.core.js index eca4bd9..95dbef1 100644 --- a/server/api.core.js +++ b/server/api.core.js @@ -1625,6 +1625,32 @@ async function gatherClwAuroraPostgresqlLimitlessTable(req, res) { +//--++ AURORA - POSTGRESQL - LIMITLESS : Gather Cloudwatch Information +app.get("/api/aurora/cluster/postgresql/limitless/gather/storage/info", gatherAuroraPostgresqlLimitlessStorageInfo); +async function gatherAuroraPostgresqlLimitlessStorageInfo(req, res) { + + // Token Validation + var standardToken = verifyToken(req.headers['x-token']); + var cognitoToken = verifyTokenCognito(req.headers['x-token-cognito']); + + if (standardToken.isValid === false || cognitoToken.isValid === false) + return res.status(511).send({ data: [], message : "Token is invalid. StandardToken : " + String(standardToken.isValid) + ", CognitoToken : " + String(cognitoToken.isValid) }); + + + try + { + var params = req.query; + + var result = await auroraLimitlessPostgresqlObjectContainer[params.engineType + ":" + params.clusterId].getStorageUsage(params); + res.status(200).send({ ...result }); + + } + catch(err){ + console.log(err); + } +} + + //--++ AURORA - POSTGRESQL - LIMITLESS : Close Connection app.get("/api/aurora/cluster/postgresql/limitless/close/connection/", closeConnectionAuroraPostgresqlLimitlessCluster); async function closeConnectionAuroraPostgresqlLimitlessCluster(req, res) { diff --git a/server/class.engine.js b/server/class.engine.js index 6b87336..76764db 100644 --- a/server/class.engine.js +++ b/server/class.engine.js @@ -4311,6 +4311,34 @@ class classAuroraLimitlessPostgresqlEngine { query_start asc limit 10; `; + #sql_storage_global_usage = ` + SELECT + a.subcluster_id, + a.subcluster_type, + sum(a.db_size) db_size + FROM + rds_aurora.limitless_database b + cross join + rds_aurora.limitless_stat_database_size(b.datname) a + GROUP BY + a.subcluster_id, + a.subcluster_type + ORDER BY 3 DESC + `; + + #sql_storage_db_usage = ` + SELECT + b.datname, + sum(a.db_size) db_size + FROM + rds_aurora.limitless_database b + cross join + rds_aurora.limitless_stat_database_size(b.datname) a + GROUP BY + b.datname + ORDER BY 2 DESC + `; + #objectMetrics = []; #cluster = { metrics : { global : {}, routers : {}, shards : {} } , @@ -4328,15 +4356,23 @@ class classAuroraLimitlessPostgresqlEngine { 'BufferCacheHitRatio', 'CommitLatency', 'CommitThroughput', + 'DBLoad', + 'DBLoadCPU', + 'DBLoadNonCPU', + 'DBLoadRelativeToNumVCPUs', + 'Deadlocks', + 'MaximumUsedTransactionIDs', 'NetworkReceiveThroughput', 'NetworkThroughput', 'NetworkTransmitThroughput', + 'RDSToAuroraPostgreSQLReplicaLag', 'ReadIOPS', 'ReadLatency', 'ReadThroughput', 'StorageNetworkReceiveThroughput', 'StorageNetworkThroughput', 'StorageNetworkTransmitThroughput', + 'SwapUsage', 'TempStorageIOPS', 'TempStorageThroughput', 'WriteIOPS', @@ -4347,6 +4383,7 @@ class classAuroraLimitlessPostgresqlEngine { + //-- Constructor method constructor(object) { this.objectConnection = object.connection; @@ -4626,9 +4663,9 @@ class classAuroraLimitlessPostgresqlEngine { //-- Gather instances ids from CloudWatch var result = await AWSObject.getGenericMetricsInsight({ - sqlQuery : `SELECT AVG(DBLoad) FROM \"AWS/RDS\" WHERE DBClusterIdentifier = '${this.objectProperties.clusterId}' GROUP BY DBShardGroupSubClusterIdentifier,DBShardGroupInstanceIdentifier`, - period : 60 * 180, - interval : 180 + sqlQuery : `SELECT AVG(CommitThroughput) FROM \"AWS/RDS\" WHERE DBClusterIdentifier = '${this.objectProperties.clusterId}' GROUP BY DBShardGroupSubClusterIdentifier,DBShardGroupInstanceIdentifier`, + period : 60, + interval : 5 }); @@ -4656,7 +4693,8 @@ class classAuroraLimitlessPostgresqlEngine { codeType : item['subcluster_type']=="shard" ? "DAS" : "DTR" , subClusterId : item['subcluster_id'], subInstanceId : this.#subClustersIds[item['subcluster_id']]?.['subInstanceId'], - metrics : new classMetrics({ metrics : this.objectMetrics }) + metrics : new classMetrics({ metrics : this.objectMetrics }), + name : (item['subcluster_type']=="shard" ? "DAS" : "DTR") + "-" + item['subcluster_id'] + "-" + this.#subClustersIds[item['subcluster_id']]?.['subInstanceId'] } } ; } @@ -4710,7 +4748,8 @@ class classAuroraLimitlessPostgresqlEngine { codeType : item['subcluster_type']=="shard" ? "DAS" : "DTR" , subClusterId : item['subcluster_id'], subInstanceId : this.#subClustersIds[item['subcluster_id']]?.['subInstanceId'], - metrics : new classMetrics({ metrics : this.objectMetrics }) + metrics : new classMetrics({ metrics : this.objectMetrics }), + name : (item['subcluster_type']=="shard" ? "DAS" : "DTR") + "-" + item['subcluster_id'] + "-" + this.#subClustersIds[item['subcluster_id']]?.['subInstanceId'] } } ; } @@ -4732,17 +4771,21 @@ class classAuroraLimitlessPostgresqlEngine { var routers = []; var chartSummary = { categories : [], data : [] } ; var chartRaw = []; + var indexShard = 0; + var indexRouter = 0; try { for (let shardId of Object.keys(this.#shards)) { if (this.#shards[shardId].type == "shard"){ shards.push({ ...this.#shards[shardId], - metrics : this.#shards[shardId].metrics.getMetricList(), + ...this.#shards[shardId].metrics.getMetricList(), indexId : indexShard }); + indexShard++; } else{ routers.push({ ...this.#shards[shardId], - metrics : this.#shards[shardId].metrics.getMetricList(), + ...this.#shards[shardId].metrics.getMetricList(), indexId : indexRouter }); + indexRouter++; } chartRaw.push({ @@ -4818,6 +4861,7 @@ class classAuroraLimitlessPostgresqlEngine { labels : [], values : [], charts : [], + chartGlobal : [], summary : { total : 0, average : 0, min : 0, max : 0, count : 0 }, currentState : { chart : { @@ -4884,7 +4928,7 @@ class classAuroraLimitlessPostgresqlEngine { case "2": metrics.push({ namespace : "AWS/RDS", - label : "DBShardGroup-" + this.#shardGroupMetadata['DBShardGroupIdentifier'], + label : this.#shardGroupMetadata['DBShardGroupIdentifier'], metric : object.metric, dimension : [ { @@ -4897,6 +4941,42 @@ class classAuroraLimitlessPostgresqlEngine { }); break; + + case "3": + metrics.push({ + namespace : "AWS/RDS", + label : this.#shardGroupMetadata['DBClusterIdentifier'], + metric : object.metric, + dimension : [ + { + "Name" : "DBClusterIdentifier", + "Value" : this.#shardGroupMetadata['DBClusterIdentifier'], + } + ], + stat : object.stat + }); + break; + + + case "4": + metrics.push({ + namespace : "AWS/RDS", + label : this.#shardGroupMetadata['DBClusterIdentifier'], + metric : object.metric, + dimension : [ + { + "Name" : "DBClusterIdentifier", + "Value" : this.#shardGroupMetadata['DBClusterIdentifier'], + }, + { + "Name" : "DBShardGroupIdentifier", + "Value" : this.#shardGroupMetadata['DBShardGroupIdentifier'], + }, + ], + stat : object.stat + }); + break; + } @@ -4912,10 +4992,18 @@ class classAuroraLimitlessPostgresqlEngine { var max = []; var min = []; var rawData = []; + + var totalValue = {}; dataset.forEach(item => { var total = 0; - var dataRecords = item.Timestamps.map((value, index) => { + var dataRecords = item.Timestamps.map((value, index) => { + // Global values + if (!(totalValue.hasOwnProperty(item.Timestamps[index]))) + totalValue[item.Timestamps[index]] = 0; + totalValue[item.Timestamps[index]] = totalValue[item.Timestamps[index]] + item.Values[index]; + + // Item values total = total + item.Values[index]; summary.count = summary.count + 1; return [item.Timestamps[index], item.Values[index] ]; @@ -4943,7 +5031,16 @@ class classAuroraLimitlessPostgresqlEngine { summary.max = Math.max(...max); summary.min = Math.max(...min); summary.average = summary.total / summary.count; - result = { labels : labels, values : values, charts : charts, summary : summary, currentState : currentState }; + + + // Data Global + var chartGlobal = []; + for (let item of Object.keys(totalValue)) { + chartGlobal.push([item,totalValue[item]]); + } + + + result = { labels : labels, values : values, charts : charts, chartGlobal : chartGlobal, summary : summary, currentState : currentState }; } @@ -5010,8 +5107,13 @@ class classAuroraLimitlessPostgresqlEngine { async getCloudwatchMetricsTable(){ var tableMetrics = []; var tableSummary = {}; - var chartSummary = { categories : [], data : [] }; - var chartHistory = { CommitThroughput : [], DBShardGroupACUUtilization : [], DBShardGroupCapacity : [] }; + var chartSummary = { CommitThroughput : [], DBLoad : [], CommitLatency : [] }; + var totalShards = 0; + + var chartSummary = { CommitThroughput : { categories : [], data : [] }, DBLoad : { categories : [], data : [] }, CommitLatency : { categories : [], data : [] } }; + var chartSummaryRaw = { CommitThroughput : [], DBLoad : [], CommitLatency : [] }; + var chartHistory = { CommitThroughput : [], DBLoad : [], CommitLatency : [], DBShardGroupACUUtilization : [], DBShardGroupCapacity : [] }; + var chartGlobal = { CommitThroughput : [], DBLoad : [] }; try { for (let shardId of Object.keys(this.#shards)) { @@ -5029,11 +5131,46 @@ class classAuroraLimitlessPostgresqlEngine { }); tableMetrics.push(columns); - chartSummary.categories.push(this.#shards[shardId]?.['codeType'] + "-" + this.#shards[shardId]?.['subClusterId'] + "-" + this.#shards[shardId]?.['subInstanceId']); - chartSummary.data.push(columns['CommitThroughput']); + + chartSummaryRaw['CommitThroughput'].push( { + name : this.#shards[shardId]?.['codeType'] + "-" + this.#shards[shardId]?.['subClusterId'] + "-" + this.#shards[shardId]?.['subInstanceId'], + value : columns['CommitThroughput'] + }); + chartSummaryRaw['DBLoad'].push( { + name : this.#shards[shardId]?.['codeType'] + "-" + this.#shards[shardId]?.['subClusterId'] + "-" + this.#shards[shardId]?.['subInstanceId'], + value : columns['DBLoad'] + }); + + chartSummaryRaw['CommitLatency'].push( { + name : this.#shards[shardId]?.['codeType'] + "-" + this.#shards[shardId]?.['subClusterId'] + "-" + this.#shards[shardId]?.['subInstanceId'], + value : columns['CommitLatency'] + }); + + totalShards++; + } + + // Latency adjustment + tableSummary['CommitLatency'] = tableSummary['CommitLatency'] / totalShards; + tableSummary['ReadLatency'] = tableSummary['ReadLatency'] / totalShards; + tableSummary['WriteLatency'] = tableSummary['WriteLatency'] / totalShards; + + // Sorting charts + chartSummaryRaw['CommitThroughput'].sort((a, b) => b.value - a.value); + chartSummaryRaw['DBLoad'].sort((a, b) => b.value - a.value); + chartSummaryRaw['CommitLatency'].sort((a, b) => b.value - a.value); + + chartSummary['CommitThroughput'].data = chartSummaryRaw['CommitThroughput'].map(item => item.value); + chartSummary['CommitThroughput'].categories = chartSummaryRaw['CommitThroughput'].map(item => item.name); + + chartSummary['DBLoad'].data = chartSummaryRaw['DBLoad'].map(item => item.value); + chartSummary['DBLoad'].categories = chartSummaryRaw['DBLoad'].map(item => item.name); + + chartSummary['CommitLatency'].data = chartSummaryRaw['CommitLatency'].map(item => item.value); + chartSummary['CommitLatency'].categories = chartSummaryRaw['CommitLatency'].map(item => item.name); + // - Global - CommitThroughput var dataset = await this.getCloudwatchMetrics({ type : "1", metric : 'CommitThroughput', @@ -5043,6 +5180,64 @@ class classAuroraLimitlessPostgresqlEngine { resourceType : "ALL", }); chartHistory['CommitThroughput'] = dataset['charts']; + chartGlobal['CommitThroughput'] = dataset['chartGlobal']; + + + // Global - CommitLatency + dataset = await this.getCloudwatchMetrics({ + type : "1", + metric : 'CommitLatency', + period : 1, + interval : 30, + stat : "Average", + resourceType : "ALL", + }); + chartHistory['CommitLatency'] = dataset['charts']; + chartGlobal['CommitLatency'] = dataset['chartGlobal']; + + chartGlobal['CommitLatency'].forEach(function(item, index) { + chartGlobal['CommitLatency'][index][1] = chartGlobal['CommitLatency'][index][1] / totalShards; + }); + + + // Global - DBLoad + dataset = await this.getCloudwatchMetrics({ + type : "1", + metric : 'DBLoad', + period : 1, + interval : 30, + stat : "Average", + resourceType : "ALL", + }); + chartHistory['DBLoad'] = dataset['charts']; + chartGlobal['DBLoad'] = dataset['chartGlobal']; + + // Global - DBLoadCPU + dataset = await this.getCloudwatchMetrics({ + type : "1", + metric : 'DBLoadCPU', + period : 1, + interval : 30, + stat : "Average", + resourceType : "ALL", + }); + chartHistory['DBLoadCPU'] = dataset['charts']; + chartGlobal['DBLoadCPU'] = dataset['chartGlobal']; + + + // Global - DBLoadNonCPU + dataset = await this.getCloudwatchMetrics({ + type : "1", + metric : 'DBLoadNonCPU', + period : 1, + interval : 30, + stat : "Average", + resourceType : "ALL", + }); + chartHistory['DBLoadNonCPU'] = dataset['charts']; + chartGlobal['DBLoadNonCPU'] = dataset['chartGlobal']; + + dataset = await this.getCloudwatchMetrics({ type : "2", @@ -5070,10 +5265,125 @@ class classAuroraLimitlessPostgresqlEngine { this.#objLog.write("getCloudwatchMetricsTable","err",err); } - return { tableMetrics : tableMetrics, tableSummary : tableSummary, chartSummary : chartSummary, chartHistory : chartHistory }; + return { tableMetrics : tableMetrics, tableSummary : tableSummary, chartSummary : chartSummary, chartHistory : chartHistory, chartGlobal : chartGlobal }; } + + async getCloudWatchMetricsGlobal(object){ + + var result = {} + try { + var dataset = await AWSObject.getGenericMetricsInsight({ + sqlQuery : `SELECT AVG(${object.metric}) FROM \"AWS/RDS\" WHERE DBClusterIdentifier = '${this.objectProperties.clusterId}'`, + period : 60 * 180, + interval : 180 + }); + + result = dataset; + + } + catch(err){ + this.#objLog.write("getCloudWatchMetricsGlobal","err",err); + } + return result; + + + } + + + + //-- Gather Storage Usage + async getStorageUsage(object){ + + var result = { chart : { categories : [], series : []} , table : [], summary : {} }; + try { + + + + + var shardStorage = 0; + var routerStorage = 0; + var totalStorage = 0; + + if (object.type != "database"){ + + //-- Execute storage query + var dataset = (await this.#connection.query(this.#sql_storage_global_usage)).rows; + + dataset.forEach(item => { + + if (this.#shards.hasOwnProperty(item['subcluster_id'])) { + + if (object.type == item['subcluster_type'] || object.type == "ALL"){ + result.chart.categories.push(this.#shards[item['subcluster_id']].name); + result.chart.series.push(item['db_size']); + result.table.push({ name : this.#shards[item['subcluster_id']].name, type : item['subcluster_type'], size : item['db_size'], pct :0 }); + totalStorage = totalStorage + parseFloat(item['db_size']); + } + + if (item['subcluster_type']=='shard') + shardStorage = shardStorage + parseFloat(item['db_size']); + + if (item['subcluster_type']=='router') + routerStorage = routerStorage + parseFloat(item['db_size']); + + } + }); + + for (let index=0; index < result.table.length; index++){ + result.table[index]['pct'] = Math.trunc((parseFloat(result.table[index]['size'])/totalStorage)*100); + } + + + + } + else{ + + //-- Execute storage query + var dataset = (await this.#connection.query(this.#sql_storage_db_usage)).rows; + + totalStorage = dataset.reduce((n, {db_size}) => n + parseFloat(db_size), 0); + + dataset.forEach(item => { + + result.chart.categories.push(item['datname']); + result.chart.series.push(item['db_size']); + result.table.push({ name : item['datname'], type : 'database', size : item['db_size'], pct : Math.trunc((parseFloat(item['db_size'])/totalStorage)*100) }); + + }); + + + + var dataset = (await this.#connection.query(this.#sql_storage_global_usage)).rows; + dataset.forEach(item => { + + if (item['subcluster_type']=='shard') + shardStorage = shardStorage + parseFloat(item['db_size']); + + if (item['subcluster_type']=='router') + routerStorage = routerStorage + parseFloat(item['db_size']); + + }); + + + } + + result['summary']['totalStorage'] = shardStorage + routerStorage; + result['summary']['shardStorage'] = shardStorage ; + result['summary']['routerStorage'] = routerStorage; + + } + catch(err){ + this.#objLog.write("getStorageUsage","err",err); + } + + return result; + + } + + + }