///////////////////////////////////////////////////////////// // // pgAdmin 4 - PostgreSQL Tools // // Copyright (C) 2013 - 2024, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // ////////////////////////////////////////////////////////////// import React, { useState, useEffect, useRef, useReducer, useMemo } from 'react'; import gettext from 'sources/gettext'; import PropTypes from 'prop-types'; import { makeStyles } from '@material-ui/core/styles'; import url_for from 'sources/url_for'; import getApiInstance from 'sources/api_instance'; import {getGCD, getEpoch} from 'sources/utils'; import ChartContainer from '../components/ChartContainer'; import { Grid } from '@material-ui/core'; import { DATA_POINT_SIZE } from 'sources/chartjs'; import StreamingChart from '../../../../static/js/components/PgChart/StreamingChart'; import {useInterval, usePrevious} from 'sources/custom_hooks'; import axios from 'axios'; import { getStatsUrl, transformData,statsReducer, X_AXIS_LENGTH } from './utility.js'; import clsx from 'clsx'; import { commonTableStyles } from '../../../../static/js/Theme'; const useStyles = makeStyles((theme) => ({ container: { height: 'auto', padding: '0px !important', marginBottom: '4px', }, tableContainer: { background: theme.otherVars.tableBg, padding: '0px', border: '1px solid '+theme.otherVars.borderColor, borderCollapse: 'collapse', borderRadius: '4px', overflow: 'hidden', }, chartContainer: { padding: '4px', }, containerHeader: { fontWeight: 'bold', marginBottom: '0px', borderBottom: '1px solid '+theme.otherVars.borderColor, padding: '4px 8px', }, })); const chartsDefault = { 'hpc_stats': {'Process': [], 'Handle': []}, }; const SummaryTable = (props) => { const tableClasses = commonTableStyles(); const data = props.data; return ( {data.map((item, index) => ( ))}
Property Value
{item.name} {item.value}
); }; SummaryTable.propTypes = { data: PropTypes.any, }; export default function Summary({preferences, sid, did, pageVisible, enablePoll=true}) { const refreshOn = useRef(null); const prevPrefernces = usePrevious(preferences); const [processHandleCount, processHandleCountReduce] = useReducer(statsReducer, chartsDefault['hpc_stats']); const [osStats, setOsStats] = useState([]); const [cpuStats, setCpuStats] = useState([]); const [, setCounterData] = useState({}); const [pollDelay, setPollDelay] = useState(5000); const [errorMsg, setErrorMsg] = useState(null); const [chartDrawnOnce, setChartDrawnOnce] = useState(false); useEffect(()=>{ let calcPollDelay = false; if(prevPrefernces) { if(prevPrefernces['hpc_stats_refresh'] != preferences['hpc_stats_refresh']) { processHandleCountReduce({reset: chartsDefault['hpc_stats']}); calcPollDelay = true; } } else { calcPollDelay = true; } if(calcPollDelay) { const keys = Object.keys(chartsDefault); const length = keys.length; if(length == 1){ setPollDelay( preferences[keys[0]+'_refresh']*1000 ); } else { setPollDelay( getGCD(Object.keys(chartsDefault).map((name)=>preferences[name+'_refresh']))*1000 ); } } }, [preferences]); useEffect(()=>{ /* Charts rendered are not visible when, the dashboard is hidden but later visible */ if(pageVisible && !chartDrawnOnce) { setChartDrawnOnce(true); } }, [pageVisible]); useEffect(() => { try { // Fetch the latest data point from the API endpoint let url; url = url_for('dashboard.system_statistics'); url += '/' + sid; url += did > 0 ? '/' + did : ''; url += '?chart_names=' + 'pg_sys_os_info,pg_sys_cpu_info'; const api = getApiInstance(); api({ url: url, type: 'GET', }) .then((res) => { let data = res.data; const os_info_obj = data['pg_sys_os_info']; let os_info_list = [ { icon: '', name: gettext('Name'), value: gettext(os_info_obj['name']) }, { icon: '', name: gettext('Version'), value: gettext(os_info_obj['version']) }, { icon: '', name: gettext('Host name'), value: gettext(os_info_obj['host_name']) }, { icon: '', name: gettext('Domain name'), value: gettext(os_info_obj['domain_name']) }, { icon: '', name: gettext('Architecture'), value: gettext(os_info_obj['architecture']) }, { icon: '', name: gettext('Os up since seconds'), value: gettext(os_info_obj['os_up_since_seconds']) }, ]; setOsStats(os_info_list); const cpu_info_obj = data['pg_sys_cpu_info']; let cpu_info_list = [ { icon: '', name: gettext('Vendor'), value: gettext(cpu_info_obj['vendor']) }, { icon: '', name: gettext('Description'), value: gettext(cpu_info_obj['description']) }, { icon: '', name: gettext('Model name'), value: gettext(cpu_info_obj['model_name']) }, { icon: '', name: gettext('No of cores'), value: gettext(cpu_info_obj['no_of_cores']) }, { icon: '', name: gettext('Architecture'), value: gettext(cpu_info_obj['architecture']) }, { icon: '', name: gettext('Clock speed Hz'), value: gettext(cpu_info_obj['clock_speed_hz']) }, { icon: '', name: gettext('L1 dcache size'), value: gettext(cpu_info_obj['l1dcache_size']) }, { icon: '', name: gettext('L1 icache size'), value: gettext(cpu_info_obj['l1icache_size']) }, { icon: '', name: gettext('L2 cache size'), value: gettext(cpu_info_obj['l2cache_size']) }, { icon: '', name: gettext('L3 cache size'), value: gettext(cpu_info_obj['l3cache_size']) }, ]; setCpuStats(cpu_info_list); setErrorMsg(null); }) .catch((error) => { console.error('Error fetching data:', error); }); } catch (error) { console.error('Error fetching data:', error); } }, [sid, did, enablePoll, pageVisible]); useInterval(()=>{ const currEpoch = getEpoch(); if(refreshOn.current === null) { let tmpRef = {}; Object.keys(chartsDefault).forEach((name)=>{ tmpRef[name] = currEpoch; }); refreshOn.current = tmpRef; } let getFor = []; Object.keys(chartsDefault).forEach((name)=>{ if(currEpoch >= refreshOn.current[name]) { getFor.push(name); refreshOn.current[name] = currEpoch + preferences[name+'_refresh']; } }); let path = getStatsUrl(sid, did, getFor); if (!pageVisible){ return; } axios.get(path) .then((resp)=>{ let data = resp.data; setErrorMsg(null); processHandleCountReduce({incoming: data['hpc_stats']}); setCounterData((prevCounterData)=>{ return { ...prevCounterData, ...data, }; }); }) .catch((error)=>{ if(!errorMsg) { processHandleCountReduce({reset:chartsDefault['hpc_stats']}); setCounterData({}); if(error.response) { if (error.response.status === 428) { setErrorMsg(gettext('Please connect to the selected server to view the graph.')); } else { setErrorMsg(gettext('An error occurred whilst rendering the graph.')); } } else if(error.request) { setErrorMsg(gettext('Not connected to the server or the connection to the server has been closed.')); return; } else { console.error(error); } } }); }, enablePoll ? pollDelay : -1); return ( <>
{pollDelay}
{chartDrawnOnce && } ); } Summary.propTypes = { preferences: PropTypes.object.isRequired, sid: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.number.isRequired]), did: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.number.isRequired]), pageVisible: PropTypes.bool, enablePoll: PropTypes.bool, }; function SummaryWrapper(props) { const classes = useStyles(); const options = useMemo(()=>({ showDataPoints: props.showDataPoints, showTooltip: props.showTooltip, lineBorderWidth: props.lineBorderWidth, }), [props.showTooltip, props.showDataPoints, props.lineBorderWidth]); return ( <>
{gettext('OS information')}
{gettext('CPU information')}
); } SummaryWrapper.propTypes = { processHandleCount: PropTypes.any.isRequired, osStats: PropTypes.any.isRequired, cpuStats: PropTypes.any.isRequired, errorMsg: PropTypes.any, showTooltip: PropTypes.bool, showDataPoints: PropTypes.bool, lineBorderWidth: PropTypes.number, isTest: PropTypes.bool, };