Hi,

Please find the attached System Stats extension patch.
As my Final Submission for GSoC.


Thanks,
Kunal
diff --git a/web/pgadmin/dashboard/__init__.py b/web/pgadmin/dashboard/__init__.py
index d13b8bdeb..4d9db7f03 100644
--- a/web/pgadmin/dashboard/__init__.py
+++ b/web/pgadmin/dashboard/__init__.py
@@ -10,7 +10,7 @@
 """A blueprint module implementing the dashboard frame."""
 import math
 from functools import wraps
-from flask import render_template, url_for, Response, g, request
+from flask import render_template, url_for, Response, g, request, current_app
 from flask_babel import gettext
 from flask_security import login_required
 import simplejson as json
@@ -71,7 +71,6 @@ class DashboardModule(PgAdminModule):
         self.dashboard_preference = Preferences(
             'dashboards', gettext('Dashboards')
         )
-
         self.session_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'session_stats_refresh',
             gettext("Session statistics refresh rate"), 'integer',
@@ -79,7 +78,6 @@ class DashboardModule(PgAdminModule):
             category_label=PREF_LABEL_REFRESH_RATES,
             help_str=help_string
         )
-
         self.tps_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'tps_stats_refresh',
             gettext("Transaction throughput refresh rate"), 'integer',
@@ -87,7 +85,6 @@ class DashboardModule(PgAdminModule):
             category_label=PREF_LABEL_REFRESH_RATES,
             help_str=help_string
         )
-
         self.ti_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'ti_stats_refresh',
             gettext("Tuples in refresh rate"), 'integer',
@@ -95,7 +92,6 @@ class DashboardModule(PgAdminModule):
             category_label=PREF_LABEL_REFRESH_RATES,
             help_str=help_string
         )
-
         self.to_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'to_stats_refresh',
             gettext("Tuples out refresh rate"), 'integer',
@@ -111,7 +107,52 @@ class DashboardModule(PgAdminModule):
             category_label=PREF_LABEL_REFRESH_RATES,
             help_str=help_string
         )
+        self.thread_activity_refresh = self.dashboard_preference.register(
+            'dashboards', 'thread_activity_refresh',
+            gettext("Thread activity refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.cpu_activity_refresh = self.dashboard_preference.register(
+            'dashboards', 'cpu_activity_refresh',
+            gettext("CPU activity refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.memory_comp_refresh = self.dashboard_preference.register(
+            'dashboards', 'memory_comp_refresh',
+            gettext("Memory composition refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.disk_info_refresh = self.dashboard_preference.register(
+            'dashboards', 'disk_info_refresh',
+            gettext("Disk Information refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
 
+        self.avg_load_refresh = self.dashboard_preference.register(
+            'dashboards', 'avg_load_refresh',
+            gettext("Average load refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+        self.nics_refresh = self.dashboard_preference.register(
+            'dashboards', 'nics_refresh',
+            gettext("NICs refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
         self.display_graphs = self.dashboard_preference.register(
             'display', 'show_graphs',
             gettext("Show graphs?"), 'boolean', True,
@@ -197,6 +238,18 @@ class DashboardModule(PgAdminModule):
             'dashboard.get_prepared_by_database_id',
             'dashboard.config',
             'dashboard.get_config_by_server_id',
+            'dashboard.cpu_activity',
+            'dashboard.get_cpu_activity_by_server_id',
+            'dashboard.get_cpu_activity_by_database_id',
+            'dashboard.os_activity',
+            'dashboard.get_os_activity_by_server_id',
+            'dashboard.get_os_activity_by_database_id',
+            'dashboard.memory_activity',
+            'dashboard.get_memory_activity_by_server_id',
+            'dashboard.get_memory_activity_by_database_id',
+            'dashboard.system_stats',
+            'dashboard.system_stats_sid',
+            'dashboard.system_stats_did',
         ]
 
 
@@ -303,25 +356,12 @@ def index(sid=None, did=None):
 
         if not g.conn.connected():
             g.version = 0
-
-    # Show the appropriate dashboard based on the identifiers passed to us
-    if sid is None and did is None:
-        return render_template('/dashboard/welcome_dashboard.html')
-    if did is None:
-        return render_template(
-            '/dashboard/server_dashboard.html',
-            sid=sid,
-            rates=rates,
-            version=g.version
-        )
+    # To check system stats extension
     else:
-        return render_template(
-            '/dashboard/database_dashboard.html',
-            sid=sid,
-            did=did,
-            rates=rates,
-            version=g.version
-        )
+        is_error, err_msg, ret_status, msg = check_system_stats_installed(
+            g.conn, ret_status)
+        if is_error:
+            return err_msg
 
 
 def get_data(sid, did, template, check_long_running_query=False):
@@ -484,6 +524,114 @@ def config(sid=None):
     return get_data(sid, None, 'config.sql')
 
 
+def check_system_stats_installed(conn, ret_status):
+    """
+    Check system_stats extension is present or not
+    :param conn:
+    :param ret_status:
+    :return:
+    """
+    msg = ''
+    status_in, rid_tar = conn.execute_scalar(
+        "SELECT count(*) FROM pg_extension WHERE extname = 'system_stats';"
+    )
+    if not status_in:
+        current_app.logger.debug(
+            "Failed to find the system_stats extension in this database.")
+        return True, internal_server_error(
+            gettext("Failed to find the system_stats extension in "
+                    "this database.")
+        ), None, None
+
+    if rid_tar == '0':
+        msg = gettext(
+            "The Extension plugin is not enabled. Please create the "
+            "system_stats extension in this database."
+        )
+        ret_status = False
+    return False, None, ret_status, msg
+
+
+@blueprint.route('/system_stats',
+                 endpoint='system_stats')
+@blueprint.route('/system_stats/<int:sid>',
+                 endpoint='system_stats_sid')
+@blueprint.route('/system_stats/<int:sid>/<int:did>',
+                 endpoint='system_stats_did')
+@login_required
+@check_precondition
+def system_stats(sid=None, did=None):
+
+    resp_data = {}
+
+    if request.args['chart_names'] != '':
+        chart_names = request.args['chart_names'].split(',')
+        if not sid:
+            return internal_server_error(errormsg='Server ID not specified.')
+
+        sql = render_template(
+            "/".join([g.template_path, 'system_stats.sql']), did=did,
+            chart_names=chart_names,
+        )
+        status, res = g.conn.execute_dict(sql)
+        for chart_row in res['rows']:
+            resp_data[chart_row['chart_name']] = \
+                json.loads(chart_row['chart_data'])
+
+    return ajax_response(
+        response=resp_data,
+        status=200
+    )
+
+
+@blueprint.route('/cpu_activity/', endpoint='cpu_activity')
+@blueprint.route('/cpu_activity/<int:sid>',
+                 endpoint='get_cpu_activity_by_server_id')
+@blueprint.route('/cpu_activity/<int:sid>/<int:did>',
+                 endpoint='get_cpu_activity_by_database_id')
+@login_required
+@check_precondition
+def cpu_activity(sid=None, did=None):
+    """
+    This function returns server activity information
+    :param sid: server id
+    :return:
+    """
+    return get_data(sid, did, 'cpu.sql')
+
+
+@blueprint.route('/os_activity/', endpoint='os_activity')
+@blueprint.route('/os_activity/<int:sid>',
+                 endpoint='get_os_activity_by_server_id')
+@blueprint.route('/os_activity/<int:sid>/<int:did>',
+                 endpoint='get_os_activity_by_database_id')
+@login_required
+@check_precondition
+def os_activity(sid=None, did=None):
+    """
+    This function returns server lock information
+    :param sid: server id
+    :return:
+    """
+    return get_data(sid, did, 'os.sql')
+
+
+@blueprint.route('/memory_activity/', endpoint='memory_activity')
+@blueprint.route('/memory_activity/<int:sid>',
+                 endpoint='get_memory_activity_by_server_id')
+@blueprint.route('/memory_activity/<int:sid>/<int:did>',
+                 endpoint='get_memory_activity_by_database_id')
+@login_required
+@check_precondition
+def memory_activity(sid=None, did=None):
+    """
+    This function returns prepared XACT information
+    :param sid: server id
+    :return:
+    """
+    return get_data(sid, did, 'memory.sql')
+
+
 @blueprint.route(
     '/cancel_query/<int:sid>/<int:pid>', methods=['DELETE']
 )
diff --git a/web/pgadmin/dashboard/static/js/Dashboard.jsx b/web/pgadmin/dashboard/static/js/Dashboard.jsx
index 0c70481c1..c8690c3b1 100644
--- a/web/pgadmin/dashboard/static/js/Dashboard.jsx
+++ b/web/pgadmin/dashboard/static/js/Dashboard.jsx
@@ -28,6 +28,7 @@ import _ from 'lodash';
 import CachedOutlinedIcon from '@material-ui/icons/CachedOutlined';
 import EmptyPanelMessage from '../../../static/js/components/EmptyPanelMessage';
 import TabPanel from '../../../static/js/components/TabPanel';
+import Graphs_stats from '../../system_stats/static/js/Graphs_system_stats';
 
 function parseData(data) {
   let res = [];
@@ -121,13 +122,19 @@ export default function Dashboard({
   sid,
   did,
   treeNodeInfo,
+  ret_status,
   ...props
 }) {
   const classes = useStyles();
   let tabs = [gettext('Sessions'), gettext('Locks'), gettext('Prepared Transactions')];
+  let header = [gettext('Database Stats'), gettext('System Stats')];
   const [dashData, setdashData] = useState([]);
+  const [sysData, setSysData] = useState([]);
+  const [osData, setOsData] = useState([]);
+  const [memData, setMemData] = useState([]);
   const [msg, setMsg] = useState('');
   const [tabVal, setTabVal] = useState(0);
+  const [headVal,setHeadVal] = useState(0);
   const [refresh, setRefresh] = useState(false);
   const [schemaDict, setSchemaDict] = React.useState({});
 
@@ -139,6 +146,10 @@ export default function Dashboard({
     setTabVal(tabVal);
   };
 
+  const headChanged = (e, headVal) => {
+    setHeadVal(headVal);
+  };
+
   const serverConfigColumns = [
     {
       accessor: 'name',
@@ -772,6 +783,124 @@ export default function Dashboard({
     }
   }, [nodeData, tabVal, did, preferences, refresh, props.dbConnected]);
 
+  useEffect(() => {
+    let url,
+      message = gettext(
+        'Please connect to the selected server to view the dashboard.'
+      );
+    if (sid && props.serverConnected) {
+      url = url_for('dashboard.cpu_activity');
+
+      message = gettext('Loading dashboard...');
+      if (did && !props.dbConnected) return;
+      if (did) url += sid + '/' + did;
+      else url += sid;
+
+      const api = getApiInstance();
+      if (node) {
+        api({
+          url: url,
+          type: 'GET',
+        })
+          .then((res) => {
+            setSysData(parseData(res.data));
+          })
+          .catch((error) => {
+            Notify.alert(
+              gettext('Failed to retrieve data from the server.'),
+              _.isUndefined(error.response) ? error.message : error.response.data.errormsg
+            );
+            // show failed message.
+            setMsg(gettext('Failed to retrieve data from the server.'));
+          });
+      } else {
+        setMsg(message);
+      }
+    }
+    if (message != '') {
+      setMsg(message);
+    }
+  }, [nodeData, did, preferences, refresh, props.dbConnected]);
+
+
+  useEffect(() => {
+    let url,
+      message = gettext(
+        'Please connect to the selected server to view the dashboard.'
+      );
+    if (sid && props.serverConnected) {
+      url = url_for('dashboard.os_activity');
+
+      message = gettext('Loading dashboard...');
+      if (did && !props.dbConnected) return;
+      if (did) url += sid + '/' + did;
+      else url += sid;
+
+      const api = getApiInstance();
+      if (node) {
+        api({
+          url: url,
+          type: 'GET',
+        })
+          .then((res) => {
+            setOsData(parseData(res.data));
+          })
+          .catch((error) => {
+            Notify.alert(
+              gettext('Failed to retrieve data from the server.'),
+              _.isUndefined(error.response) ? error.message : error.response.data.errormsg
+            );
+            // show failed message.
+            setMsg(gettext('Failed to retrieve data from the server.'));
+          });
+      } else {
+        setMsg(message);
+      }
+    }
+    if (message != '') {
+      setMsg(message);
+    }
+  }, [nodeData, did, preferences, refresh, props.dbConnected]);
+
+  useEffect(() => {
+    let url,
+      message = gettext(
+        'Please connect to the selected server to view the dashboard.'
+      );
+    if (sid && props.serverConnected) {
+      url = url_for('dashboard.memory_activity');
+
+      message = gettext('Loading dashboard...');
+      if (did && !props.dbConnected) return;
+      if (did) url += sid + '/' + did;
+      else url += sid;
+
+      const api = getApiInstance();
+      if (node) {
+        api({
+          url: url,
+          type: 'GET',
+        })
+          .then((res) => {
+            setMemData(parseData(res.data));
+          })
+          .catch((error) => {
+            Notify.alert(
+              gettext('Failed to retrieve data from the server.'),
+              _.isUndefined(error.response) ? error.message : error.response.data.errormsg
+            );
+            // show failed message.
+            setMsg(gettext('Failed to retrieve data from the server.'));
+          });
+      } else {
+        setMsg(message);
+      }
+    }
+    if (message != '') {
+      setMsg(message);
+    }
+  }, [nodeData, did, preferences, refresh, props.dbConnected]);
+
   const RefreshButton = () =>{
     return(
       <PgIconButton
@@ -816,69 +945,108 @@ export default function Dashboard({
       {sid && props.serverConnected ? (
         <Box className={classes.dashboardPanel}>
           <Box className={classes.emptyPanel}>
-            {!_.isUndefined(preferences) && preferences.show_graphs && (
-              <Graphs
-                key={sid + did}
-                preferences={preferences}
-                sid={sid}
-                did={did}
-                pageVisible={props.panelVisible}
-              ></Graphs>
-            )}
-            {!_.isUndefined(preferences) && preferences.show_activity && (
-              <Box className={classes.panelContent}>
-                <Box
-                  className={classes.cardHeader}
-                  title={props.dbConnected ?  gettext('Database activity') : gettext('Server activity')}
-                >
-                  {props.dbConnected ?  gettext('Database activity') : gettext('Server activity')}{' '}
-                </Box>
-                <Box height="100%" display="flex" flexDirection="column">
-                  <Box>
-                    <Tabs
-                      value={tabVal}
-                      onChange={tabChanged}
-                    >
-                      {tabs.map((tabValue, i) => {
-                        return <Tab key={i} label={tabValue} />;
-                      })}
-                      <RefreshButton/>
-                    </Tabs>
-                  </Box>
-                  <TabPanel value={tabVal} index={0} classNameRoot={classes.tabPanel}>
-                    <PgTable
-                      caveTable={false}
-                      columns={activityColumns}
-                      data={dashData}
-                      schema={schemaDict}
-                    ></PgTable>
-                  </TabPanel>
-                  <TabPanel value={tabVal} index={1} classNameRoot={classes.tabPanel}>
-                    <PgTable
-                      caveTable={false}
-                      columns={databaseLocksColumns}
-                      data={dashData}
-                    ></PgTable>
-                  </TabPanel>
-                  <TabPanel value={tabVal} index={2} classNameRoot={classes.tabPanel}>
-                    <PgTable
-                      caveTable={false}
-                      columns={databasePreparedColumns}
-                      data={dashData}
-                    ></PgTable>
-                  </TabPanel>
-                  <TabPanel value={tabVal} index={3} classNameRoot={classes.tabPanel}>
-                    <PgTable
-                      caveTable={false}
-                      columns={serverConfigColumns}
-                      data={dashData}
-                    ></PgTable>
-                  </TabPanel>
+
+            <Box className={classes.panelContent}>
+              <Box height="100%" display="flex" flexDirection="column">
+                <Box>
+                  {ret_status!==0 && (<Tabs
+                    value={headVal}
+                    onChange={headChanged}
+                  >
+                    {header.map((headValue, i) => {
+                      return <Tab key={i} label={headValue} />;
+                    })}
+                  </Tabs>)}
                 </Box>
+                <TabPanel value={headVal} index={0} classNameRoot={classes.tabPanel}>
+                  {!_.isUndefined(preferences) && preferences.show_graphs && (
+                    <Graphs
+                      key={sid + did}
+                      preferences={preferences}
+                      sid={sid}
+                      did={did}
+                      pageVisible={props.panelVisible}
+                    ></Graphs>
+                  )}
+                  {!_.isUndefined(preferences) && preferences.show_activity && (
+                    <Box className={classes.panelContent}>
+                      <Box
+                        className={classes.cardHeader}
+                        title={props.dbConnected ?  gettext('Database activity') : gettext('Server activity')}
+                      >
+                        {props.dbConnected ?  gettext('Database activity') : gettext('Server activity')}{' '}
+                      </Box>
+                      <Box height="100%" display="flex" flexDirection="column">
+                        <Box>
+                          <Tabs
+                            value={tabVal}
+                            onChange={tabChanged}
+                          >
+                            {tabs.map((tabValue, i) => {
+                              return <Tab key={i} label={tabValue} />;
+                            })}
+                            <RefreshButton/>
+                          </Tabs>
+                        </Box>
+                        <TabPanel value={tabVal} index={0} classNameRoot={classes.tabPanel}>
+                          <PgTable
+                            caveTable={false}
+                            columns={activityColumns}
+                            data={dashData}
+                            schema={schemaDict}
+                          ></PgTable>
+                        </TabPanel>
+                        <TabPanel value={tabVal} index={1} classNameRoot={classes.tabPanel}>
+                          <PgTable
+                            caveTable={false}
+                            columns={databaseLocksColumns}
+                            data={dashData}
+                          ></PgTable>
+                        </TabPanel>
+                        <TabPanel value={tabVal} index={2} classNameRoot={classes.tabPanel}>
+                          <PgTable
+                            caveTable={false}
+                            columns={databasePreparedColumns}
+                            data={dashData}
+                          ></PgTable>
+                        </TabPanel>
+                        <TabPanel value={tabVal} index={3} classNameRoot={classes.tabPanel}>
+                          <PgTable
+                            caveTable={false}
+                            columns={serverConfigColumns}
+                            data={dashData}
+                          ></PgTable>
+                        </TabPanel>
+                      </Box>
+                    </Box>
+                  )}
+                </TabPanel>
+                <TabPanel value={headVal} index={1} classNameRoot={classes.tabPanel}>
+                  {!_.isUndefined(preferences) && !_.isUndefined(sysData) && sysData.length>0
+                  && !_.isUndefined(osData) && osData.length>0  && !_.isUndefined(memData) &&
+                  memData.length>0 && preferences.show_graphs && (
+                    <Graphs_stats
+                      key={sid + did}
+                      preferences={preferences}
+                      sid={sid}
+                      did={did}
+                      pageVisible={props.panelVisible}
+                      sysData1 = {sysData}
+                      osData1 = {osData}
+                      memData1 = {memData}
+                    ></Graphs_stats>
+                  )}
+                </TabPanel>
               </Box>
-            )}
+            </Box>
           </Box>
         </Box>
+      ) : sid && !props.serverConnected ? (
+        <Box className={classes.dashboardPanel}>
+          <div className={classes.emptyPanel}>
+            <EmptyPanelMessage text={gettext(msg)}/>
+          </div>
+        </Box>
       ) : showDefaultContents() }
     </>
   );
@@ -898,6 +1066,7 @@ Dashboard.propTypes = {
   serverConnected: PropTypes.bool,
   dbConnected: PropTypes.bool,
   panelVisible: PropTypes.bool,
+  ret_status: PropTypes.bool,
 };
 
 export function ChartContainer(props) {
@@ -935,6 +1104,42 @@ ChartContainer.propTypes = {
   errorMsg: PropTypes.string,
 };
 
+export function ChartContainersys(props) {
+  return (
+    <div
+      className="card dashboard-sysgraph"
+      role="object-document"
+      tabIndex="0"
+      aria-labelledby={props.id}
+      style={{ borderbottomwidth: '0px' }}
+    >
+      <div className="card-header">
+        <div className="d-flex">
+          <div id={props.id}>{props.title}</div>
+          <div className="ml-auto my-auto legend" ref={props.legendRef}></div>
+        </div>
+      </div>
+      <div className="card-body dashboard-sysgraph-body">
+        <div className={'chart-wrapper ' + (props.errorMsg ? 'd-none' : '')}>
+          {props.children}
+        </div>
+        <ChartError message={props.errorMsg} />
+      </div>
+    </div>
+  );
+}
+
+ChartContainersys.propTypes = {
+  id: PropTypes.string.isRequired,
+  title: PropTypes.string.isRequired,
+  legendRef: PropTypes.oneOfType([
+    PropTypes.func,
+    PropTypes.shape({ current: PropTypes.any }),
+  ]).isRequired,
+  children: PropTypes.node.isRequired,
+  errorMsg: PropTypes.string,
+};
+
 export function ChartError(props) {
   if (props.message === null) {
     return <></>;
diff --git a/web/pgadmin/dashboard/static/scss/_dashboard.scss b/web/pgadmin/dashboard/static/scss/_dashboard.scss
index f28d5cdfc..e52363a6b 100644
--- a/web/pgadmin/dashboard/static/scss/_dashboard.scss
+++ b/web/pgadmin/dashboard/static/scss/_dashboard.scss
@@ -76,6 +76,49 @@
     }
 }
 
+
+.dashboard-sysgraph {
+    & .legend {
+        font-size: $tree-font-size;
+        & .legend-value {
+            font-weight: normal;
+            margin-left: 0.25rem;
+            & .legend-label {
+                margin-left: 0.25rem;
+            }
+        }
+    }
+
+    & .dashboard-sysgraph-body {
+        padding: 0.25rem 0.5rem;
+        height: 250px;
+
+        & .flotr-labels {
+            color: $color-fg !important;
+        }
+        & .flotr-legend {
+            border: none !important;
+            padding: 0.25rem 0.5rem;
+            & .flotr-legend-label {
+                color: $color-fg !important;
+                padding-left: 0.25rem;
+            }
+
+            & .flotr-legend-color-box>div {
+                border: none !important;
+                &>div {
+                    border: none !important;
+                }
+            }
+
+            & .flotr-legend-bg {
+                border-radius: $border-radius;
+            }
+        }
+    }
+}
+
+
 .welcome-logo {
     width: 400px;
     & .app-name {
diff --git a/web/pgadmin/dashboard/system_stats/static/__init__.py b/web/pgadmin/dashboard/system_stats/static/__init__.py
new file mode 100644
index 000000000..3dd18606b
--- /dev/null
+++ b/web/pgadmin/dashboard/system_stats/static/__init__.py
@@ -0,0 +1,247 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""A blueprint module implementing the dashboard frame."""
+from flask import render_template, g, request, current_app
+from flask_babel import gettext
+from flask_security import login_required
+import simplejson as json
+from pgadmin.utils import PgAdminModule
+from pgadmin.utils.ajax import make_response as ajax_response,\
+    internal_server_error
+from pgadmin.utils.menu import Panel
+from pgadmin.utils.preferences import Preferences
+from pgadmin.utils.constants import PREF_LABEL_DISPLAY, MIMETYPE_APP_JS, \
+    PREF_LABEL_REFRESH_RATES
+
+from config import PG_DEFAULT_DRIVER
+from ... import __init__, check_precondition, get_data
+
+MODULE_NAME = 'dashboard'
+
+
+class DashboardModule(PgAdminModule):
+    def __init__(self, *args, **kwargs):
+        super(DashboardModule, self).__init__(*args, **kwargs)
+
+    def get_own_menuitems(self):
+        return {}
+
+    def get_own_stylesheets(self):
+        """
+        Returns:
+            list: the stylesheets used by this module.
+        """
+        stylesheets = []
+        return stylesheets
+
+    def get_panels(self):
+        return [
+            Panel(
+                name='dashboard',
+                priority=1,
+                title=gettext('Dashboard'),
+                icon='',
+                content='',
+                is_closeable=True,
+                is_private=False,
+                limit=1,
+                is_iframe=False,
+                can_hide=True
+            ).__dict__
+        ]
+
+    def register_preferences(self):
+        """
+        register_preferences
+        Register preferences for this module.
+        """
+        help_string = gettext('The number of seconds between graph samples.')
+
+        # Register options for Dashboards
+        self.dashboard_preference = Preferences(
+            'dashboards', gettext('Dashboards')
+        )
+        self.thread_activity_refresh = self.dashboard_preference.register(
+            'dashboards', 'thread_activity_refresh',
+            gettext("Thread activity refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.cpu_activity_refresh = self.dashboard_preference.register(
+            'dashboards', 'cpu_activity_refresh',
+            gettext("CPU activity refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.memory_comp_refresh = self.dashboard_preference.register(
+            'dashboards', 'memory_comp_refresh',
+            gettext("Memory composition refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.disk_info_refresh = self.dashboard_preference.register(
+            'dashboards', 'disk_info_refresh',
+            gettext("Disk Information refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+        self.avg_load_refresh = self.dashboard_preference.register(
+            'dashboards', 'avg_load_refresh',
+            gettext("Average load refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+        self.nics_refresh = self.dashboard_preference.register(
+            'dashboards', 'nics_refresh',
+            gettext("NICs refresh rate"), 'integer',
+            1, min_val=1, max_val=999999,
+            category_label=PREF_LABEL_REFRESH_RATES,
+            help_str=help_string
+        )
+
+    def get_exposed_url_endpoints(self):
+        """
+        Returns:
+            list: a list of url endpoints exposed to the client.
+        """
+        return [
+            'dashboard.cpu_activity',
+            'dashboard.get_cpu_activity_by_server_id',
+            'dashboard.get_cpu_activity_by_database_id',
+            'dashboard.os_activity',
+            'dashboard.get_os_activity_by_server_id',
+            'dashboard.get_os_activity_by_database_id',
+            'dashboard.memory_activity',
+            'dashboard.get_memory_activity_by_server_id',
+            'dashboard.get_memory_activity_by_database_id',
+            'dashboard.system_stats',
+            'dashboard.system_stats_sid',
+            'dashboard.system_stats_did',
+        ]
+
+
+blueprint = DashboardModule(MODULE_NAME, __name__)
+
+def check_system_stats_installed(conn, ret_status):
+    """
+    Check system_stats extension is present or not
+    :param conn:
+    :param ret_status:
+    :return:
+    """
+    msg = ''
+    status_in, rid_tar = conn.execute_scalar(
+        "SELECT count(*) FROM pg_extension WHERE extname = 'system_stats';"
+    )
+    if not status_in:
+        current_app.logger.debug(
+            "Failed to find the system_stats extension in this database.")
+        return True, internal_server_error(
+            gettext("Failed to find the system_stats extension in "
+                    "this database.")
+        ), None, None
+
+    if rid_tar == '0':
+        msg = gettext(
+            "The Extension plugin is not enabled. Please create the "
+            "system_stats extension in this database."
+        )
+        ret_status = False
+    return False, None, ret_status, msg
+
+
+@blueprint.route('/system_stats',
+                 endpoint='system_stats')
+@blueprint.route('/system_stats/<int:sid>',
+                 endpoint='system_stats_sid')
+@blueprint.route('/system_stats/<int:sid>/<int:did>',
+                 endpoint='system_stats_did')
+@login_required
+@check_precondition
+def system_stats(sid=None, did=None):
+
+    resp_data = {}
+
+    if request.args['chart_names'] != '':
+        chart_names = request.args['chart_names'].split(',')
+
+        if not sid:
+            return internal_server_error(errormsg='Server ID not specified.')
+
+        sql = render_template(
+            "/".join([g.template_path, 'system_stats.sql']), did=did,
+            chart_names=chart_names,
+        )
+        status, res = g.conn.execute_dict(sql)
+        for chart_row in res['rows']:
+            resp_data[chart_row['chart_name']] = \
+                json.loads(chart_row['chart_data'])
+
+    return ajax_response(
+        response=resp_data,
+        status=200
+    )
+
+
+@blueprint.route('/cpu_activity/', endpoint='cpu_activity')
+@blueprint.route('/cpu_activity/<int:sid>',
+                 endpoint='get_cpu_activity_by_server_id')
+@blueprint.route('/cpu_activity/<int:sid>/<int:did>',
+                 endpoint='get_cpu_activity_by_database_id')
+@login_required
+@check_precondition
+def cpu_activity(sid=None, did=None):
+    """
+    This function returns server activity information
+    :param sid: server id
+    :return:
+    """
+    return get_data(sid, did, 'cpu.sql')
+
+
+@blueprint.route('/os_activity/', endpoint='os_activity')
+@blueprint.route('/os_activity/<int:sid>',
+                 endpoint='get_os_activity_by_server_id')
+@blueprint.route('/os_activity/<int:sid>/<int:did>',
+                 endpoint='get_os_activity_by_database_id')
+@login_required
+@check_precondition
+def os_activity(sid=None, did=None):
+    """
+    This function returns server lock information
+    :param sid: server id
+    :return:
+    """
+    return get_data(sid, did, 'os.sql')
+
+
+@blueprint.route('/memory_activity/', endpoint='memory_activity')
+@blueprint.route('/memory_activity/<int:sid>',
+                 endpoint='get_memory_activity_by_server_id')
+@blueprint.route('/memory_activity/<int:sid>/<int:did>',
+                 endpoint='get_memory_activity_by_database_id')
+@login_required
+@check_precondition
+def memory_activity(sid=None, did=None):
+    """
+    This function returns prepared XACT information
+    :param sid: server id
+    :return:
+    """
+    return get_data(sid, did, 'memory.sql')
diff --git a/web/pgadmin/dashboard/system_stats/static/css/Dashboard_system_stats.css b/web/pgadmin/dashboard/system_stats/static/css/Dashboard_system_stats.css
new file mode 100644
index 000000000..cc5f0d54f
--- /dev/null
+++ b/web/pgadmin/dashboard/system_stats/static/css/Dashboard_system_stats.css
@@ -0,0 +1,129 @@
+body {
+  margin: 0;
+  box-sizing: border-box;
+}
+.flex {
+  display: flex;
+  width: 100%;
+  overflow: hidden;
+  height: 100vh;
+}
+.container-chart {
+  min-height: 300px;
+  margin-bottom: 10px;
+  padding: 10px 5px;
+  background: #fff;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  background-clip: border-box;
+  border: 1px solid #dde0e6;
+  border-top: 0px;
+  border-radius: 0.25rem;
+}
+.container-chart-title {
+  width: 95%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  text-align: left;
+  line-height: 1.5;
+}
+.container-chart-content {
+  width: 95%;
+  gap: 5px;
+  display: flex;
+  align-items: center;
+}
+.container-chart-title h1 {
+  font-weight: 600;
+  line-height: 0;
+}
+.container-chart-title h2 {
+  font-weight: normal;
+  font-size: 1em;
+  width: 80%;
+  word-wrap: break-word;
+  text-align: right;
+}
+.container-chart-content .content-one {
+  display: flex;
+  width: 50%;
+  gap: 0 10px;
+  flex-wrap: wrap;
+  padding: 0.5em;
+}
+.container-chart-content .content-two {
+  width: 50%;
+  height: 100%;
+  padding: 0em;
+  display: flex;
+  list-style-type: none;
+  align-items: center;
+}
+.container-chart-content .content-two li {
+  padding: 2px 0;
+}
+
+.container-chart-content .content-two li span {
+  font-weight: 600;
+  padding-left: 4px;
+  font-size: 1em;
+}
+.container-chart-content h3 {
+  font-weight: normal;
+  font-size: 1em;
+}
+.container-chart-content-span {
+  font-weight: 800;
+  font-size: 1.1em;
+}
+.dashboard-container {
+  position: relative;
+  width: 100%;
+  overflow: auto;
+}
+.dashboard-container-flex {
+  display: flex;
+  width: 100%;
+  flex-wrap: wrap;
+  flex-direction: row;
+  gap: 0;
+  justify-content: center;
+  align-items: center;
+  /* background: #e6e6e6; */
+  padding: 20px 0;
+}
+.dashboard-properties {
+  height: 40px;
+  width: 100%;
+  background: #ff0000;
+  position: fixed;
+}
+.dashboard-box-container {
+  display: flex;
+  /* margin-top: 40px; */
+  padding: 20px;
+  padding-top: 0px;
+  flex-wrap: wrap;
+  /* background: #e6e6e6; */
+  justify-content: space-evenly;
+  gap: 10px;
+}
+.box-container {
+  padding: 10px 20px;
+  width: 284px;
+  background: #fff;
+}
+.box-container h1 {
+  opacity: 0.5;
+  font-weight: normal;
+}
+.box-container h2 {
+  font-weight: 700;
+  word-wrap: break-word;
+}
+.h1 {
+  font-size: 0.8875rem;
+}
\ No newline at end of file
diff --git a/web/pgadmin/dashboard/system_stats/static/js/Dashboard_system_stats.jsx b/web/pgadmin/dashboard/system_stats/static/js/Dashboard_system_stats.jsx
new file mode 100644
index 000000000..ba3bdc690
--- /dev/null
+++ b/web/pgadmin/dashboard/system_stats/static/js/Dashboard_system_stats.jsx
@@ -0,0 +1,132 @@
+// // /////////////////////////////////////////////////////////////
+// // //
+// // // pgAdmin 4 - PostgreSQL Tools
+// // //
+// // // Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// // // This software is released under the PostgreSQL Licence
+// // //
+// // /////////////////////////////////////////////////////////////
+import React from 'react';
+import PropTypes from 'prop-types';
+
+
+export default function CPUContainer({_sysData}) {
+  return (
+    <div className="container-chart">
+      <div className="container-chart-title">
+        <h2><span style={{fontWeight: 'bold'}}>{_sysData ? _sysData[0]?.model_name :'Loading'}</span></h2>
+        <h2>{_sysData ? _sysData[0]?.description :'Loading'}</h2>
+      </div>
+      <div className="container-chart-content">
+        <div className="content-one">
+          <h3>
+            Vendor<br />
+            <span className="container-chart-content-span">
+              {_sysData ? _sysData[0]?.vendor :'Loading'}
+            </span>
+          </h3>
+          <h3>
+            Clock Speed<br />
+            <span className="container-chart-content-span">
+              {_sysData ? _sysData[0]?.clock_speed_hz :'Loading'} GHz
+            </span>
+          </h3>
+        </div>
+        <div className="content-two">
+          <div>
+            <li>Cores:<span>{_sysData ? _sysData[0]?.no_of_cores :'Loading'}</span></li>
+            <li>Logical processors:<span>{_sysData ? _sysData[0]?.logical_processor :'Loading'}</span></li>
+            <li>Physical processors:<span>{_sysData ? _sysData[0]?.physical_processor :'Loading'}</span></li>
+            <li>L1_D cache:<span> {_sysData ? _sysData[0]?.l1dcache_size :'Loading'}</span></li>
+            <li>L1 cache:<span>{_sysData ? _sysData[0]?.l1icache_size :'Loading'}</span></li>
+            <li>L2 cache:<span>{_sysData ? _sysData[0]?.l2cache_size :'Loading'}</span></li>
+            <li>L3 cache:<span>{_sysData ? _sysData[0]?.l3cache_size :'Loading'}</span></li>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+CPUContainer.propTypes = {
+  _sysData: PropTypes.array,
+};
+
+
+
+export function OSContainer({_sysData}) {
+  return (
+    <div className="container-chart">
+      <div className="container-chart-title">
+        <h2><span style={{fontWeight: 'bold',fontsize: '1.2rem'}}>{_sysData ? _sysData[0]?.name :'Loading'}</span></h2>
+        <h2>{_sysData ? _sysData[0]?.version :'Loading'}</h2>
+      </div>
+      <div className="container-chart-content">
+        <div className="content-one">
+          <h3>
+            Host Name<br />
+            <span className="container-chart-content-span">
+              {_sysData ? _sysData[0]?.host_name :'Loading'}
+            </span>
+          </h3>
+          <h3>
+            Os up since<br />
+            <span className="container-chart-content-span">
+              {_sysData ? _sysData[0]?.os_up_since_seconds :'Loading'} Sec
+            </span>
+          </h3>
+        </div>
+        <div className="content-two">
+          <div>
+            <li>Architecture<span>{_sysData ? _sysData[0]?.architecture :'Loading'}</span></li>
+            <li>Handle Count:<span>{_sysData ? _sysData[0]?.handle_count :'Loading'}</span></li>
+            <li>Process Count:<span>{_sysData ? _sysData[0]?.process_count :'Loading'}</span></li>
+            <li>Thread Count:<span>{_sysData ? _sysData[0]?.thread_count :'Loading'}</span></li>
+            <li>Process Count:<span>{_sysData ? _sysData[0]?.process_count :'Loading'}</span></li>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+OSContainer.propTypes = {
+  _sysData: PropTypes.array,
+};
+
+export function MEMContainer({_sysData}) {
+  return (
+    <div className="container-chart">
+      <div className="container-chart-title">
+      </div>
+      <div className="container-chart-content">
+        <div className="content-one">
+          <h3>
+            Total Memory<br />
+            <span className="container-chart-content-span">
+              {_sysData ? _sysData[0]?.total_memory :'Loading'}
+            </span>
+          </h3>
+          <h3>
+            Used Memory
+            <br />
+            <span className="container-chart-content-span">
+              {_sysData ? _sysData[0]?.used_memory :'Loading'} GHz
+            </span>
+          </h3>
+        </div>
+        <div className="content-two">
+          <div>
+            <li>Total Swap Memory:<span>{_sysData ? _sysData[0]?.swap_total :'Loading'}</span></li>
+            <li>Used Swap Memory:<span>{_sysData ? _sysData[0]?.swap_used :'Loading'}</span></li>
+            <li>Free Swap Memory:<span>{_sysData ? _sysData[0]?.swap_free :'Loading'}</span></li>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+MEMContainer.propTypes = {
+  _sysData: PropTypes.array,
+};
\ No newline at end of file
diff --git a/web/pgadmin/dashboard/system_stats/static/js/Graphs_system_stats.jsx b/web/pgadmin/dashboard/system_stats/static/js/Graphs_system_stats.jsx
new file mode 100644
index 000000000..9b7036c17
--- /dev/null
+++ b/web/pgadmin/dashboard/system_stats/static/js/Graphs_system_stats.jsx
@@ -0,0 +1,410 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+import React, { useEffect, useRef, useState, useReducer, useCallback, useMemo } from 'react';
+import {LineChart, DATA_POINT_STYLE, DATA_POINT_SIZE} from 'sources/chartjs';
+import { DashboardRowCol, DashboardRow, ChartContainersys} from '../../../static/js/Dashboard';
+import url_for from 'sources/url_for';
+import axios from 'axios';
+import gettext from 'sources/gettext';
+import {getGCD, getEpoch} from 'sources/utils';
+import {useInterval, usePrevious} from 'sources/custom_hooks';
+import PropTypes from 'prop-types';
+import { PieChart } from '../../../../static/js/chartjs';
+import CPUContainer,{ MEMContainer, OSContainer } from './Dashboard_system_stats';
+import _ from 'lodash';
+
+
+export const X_AXIS_LENGTH = 75;
+
+/* Transform the labels data to suit ChartJS */
+export function transformData(labels, refreshRate, use_diff_point_style) {
+  const colors = ['#00BCD4', '#9CCC65', '#E64A19','#AFB4FF','#781C68'];
+  let datasets = Object.keys(labels).map((label, i)=>{
+    return {
+      label: label,
+      data: labels[label] || [],
+      borderColor: colors[i],
+      backgroundColor: colors[i],
+      pointHitRadius: DATA_POINT_SIZE,
+      pointStyle: use_diff_point_style ? DATA_POINT_STYLE[i] : 'circle'
+    };
+  }) || [];
+
+  return {
+    labels: [...Array(X_AXIS_LENGTH).keys()],
+    datasets: datasets,
+    refreshRate: refreshRate,
+  };
+}
+
+/* Custom ChartJS legend callback */
+export function generateLegend(chart) {
+  var text = [];
+  text.push('<div class="' + chart.id + '-legend d-flex">');
+  for (let chart_val of chart.data.datasets) {
+    text.push('<div class="legend-value"><span style="background-color:' + chart_val.backgroundColor + '">&nbsp;&nbsp;&nbsp;&nbsp;</span>');
+    if (chart_val.label) {
+      text.push('<span class="legend-label">' + chart_val.label + '</span>');
+    }
+    text.push('</div>');
+  }
+  text.push('</div>');
+  return text.join('');
+}
+
+/* URL for fetching graphs data */
+export function getStatsUrl(sid=-1, did=-1, chart_names=[]) {
+  let base_url = url_for('dashboard.system_stats');
+  base_url += '/' + sid;
+  base_url += (did > 0) ? ('/' + did) : '';
+  base_url += '?chart_names=' + chart_names.join(',');
+  return base_url;
+}
+
+/* This will process incoming charts data add it the previous charts
+ * data to get the new state.
+ */
+export function statsReducer(state, action) {
+
+  if(action.reset) {
+    return action.reset;
+  }
+
+  if(!action.incoming) {
+    return state;
+  }
+
+  if(!action.counterData) {
+    action.counterData = action.incoming;
+  }
+
+  let newState = {};
+  Object.keys(action.incoming).forEach(label => {
+    if(state[label]) {
+      newState[label] = [
+        action.counter ?  action.incoming[label] - action.counterData[label] : action.incoming[label],
+        ...state[label].slice(0, X_AXIS_LENGTH-1),
+      ];
+    } else {
+      newState[label] = [
+        action.counter ?  action.incoming[label] - action.counterData[label] : action.incoming[label],
+      ];
+    }
+  });
+  return newState;
+}
+
+const chartsDefault = {
+  'thread_activity': {'Process count': [], 'Handle count': [], 'Thread count': []},
+  'cpu_activity': {'Usermode Process': [], 'Kernelmode Process': []},
+  'memory_comp': {'Used Memory': [], 'Free Memory': []},
+  'disk_info': {'File System':[], 'Total Space': [], 'Used Space': []},
+  'avg_load': {'Per 1 Min': [], 'Per 5 Min': [], 'Per 10 Min': []},
+  'nics': {'Tx Bytes': [], 'Tx Packets': [], 'Rx Bytes': [], 'Rx Packets':[]},
+};
+
+export default function Graphs_stats({preferences, sid, did, pageVisible, enablePoll=true, sysData1, osData1, memData1}) {
+
+  const refreshOn = useRef(null);
+  const prevPrefernces = usePrevious(preferences);
+
+  const [threadactivity, threadstatsReduce] = useReducer(statsReducer, chartsDefault['thread_activity']);
+  const [cpuactivity, cpuStatsReduce] = useReducer(statsReducer, chartsDefault['cpu_activity']);
+  const [memorycomp, memStatsReduce] = useReducer(statsReducer, chartsDefault['memory_comp']);
+  const [diskinfo, diskStatsReduce] = useReducer(statsReducer, chartsDefault['disk_info']);
+  const [avgload, loadStatsReduce] = useReducer(statsReducer, chartsDefault['avg_load']);
+  const [nic, nicStatsReduce] = useReducer(statsReducer, chartsDefault['nics']);
+
+
+  const [counterData, setCounterData] = useState({});
+
+  const [errorMsg, setErrorMsg] = useState(null);
+  const [pollDelay, setPollDelay] = useState(1000);
+  const [chartDrawnOnce, setChartDrawnOnce] = useState(false);
+
+  useEffect(()=>{
+    let calcPollDelay = false;
+    if(prevPrefernces) {
+      if(prevPrefernces['thread_activity_refresh'] != preferences['thread_activity_refresh']) {
+        threadstatsReduce({reset: chartsDefault['thread_activity']});
+        calcPollDelay = true;
+      }
+      if(prevPrefernces['cpu_activity_refresh'] != preferences['']) {
+        cpuStatsReduce({reset:chartsDefault['cpu_activity']});
+        calcPollDelay = true;
+      }
+      if(prevPrefernces['memory_comp_refresh'] != preferences['memory_comp_refresh']) {
+        memStatsReduce({reset:chartsDefault['memory_comp']});
+        calcPollDelay = true;
+      }
+      if(prevPrefernces['disk_info_refresh'] != preferences['disk_info_refresh']) {
+        diskStatsReduce({reset:chartsDefault['disk_info']});
+        calcPollDelay = true;
+      }
+      if(prevPrefernces['avg_load_refresh'] != preferences['avg_load_refresh']) {
+        loadStatsReduce({reset:chartsDefault['avg_load']});
+        calcPollDelay = true;
+      }
+      if(prevPrefernces['nics_refresh'] != preferences['nics_refresh']) {
+        nicStatsReduce({reset:chartsDefault['nics']});
+        calcPollDelay = true;
+      }
+    } else {
+      calcPollDelay = true;
+    }
+    if(calcPollDelay) {
+      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]);
+
+  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);
+        threadstatsReduce({incoming: data['thread_activity']});
+        cpuStatsReduce({incoming: data['cpu_activity'], counter: true, counterData: counterData['cpu_activity']});
+        memStatsReduce({incoming: data['memory_comp'], counter: true, counterData: counterData['memory_comp']});
+        diskStatsReduce({incoming: data['disk_info'], counter: true, counterData: counterData['disk_info']});
+        loadStatsReduce({incoming: data['avg_load'], counter: true, counterData: counterData['avg_load']});
+        nicStatsReduce({incoming: data['nics'], counter: true, counterData: counterData['nics']});
+
+
+        setCounterData((prevCounterData)=>{
+          return {
+            ...prevCounterData,
+            ...data,
+          };
+        });
+      })
+      .catch((error)=>{
+        if(!errorMsg) {
+          threadstatsReduce({reset: chartsDefault['thread_activity']});
+          cpuStatsReduce({reset:chartsDefault['cpu_activity']});
+          memStatsReduce({reset:chartsDefault['memory_comp']});
+          diskStatsReduce({reset:chartsDefault['disk_info']});
+          loadStatsReduce({reset:chartsDefault['avg_load']});
+          nicStatsReduce({reset:chartsDefault['nics']});
+          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 (
+    <>
+      <div data-testid='graph-poll-delay' className='d-none'>{pollDelay}</div>
+      {chartDrawnOnce &&
+        <GraphsWrapper
+          threadStats={transformData(threadactivity, preferences['thread_activity_refresh'], preferences['use_diff_point_style'])}
+          cpuStats={transformData(cpuactivity, preferences['cpu_activity_refresh'], preferences['use_diff_point_style'])}
+          memStats={transformData(memorycomp, preferences['memory_comp_refresh'], preferences['use_diff_point_style'])}
+          diskStats={transformData(diskinfo, preferences['disk_info_refresh'], preferences['use_diff_point_style'])}
+          avgStats={transformData(avgload, preferences['avg_load_refresh'], preferences['use_diff_point_style'])}
+          nicStats={transformData(nic, preferences['nics_refresh'], preferences['use_diff_point_style'])}
+          errorMsg={errorMsg}
+          showTooltip={preferences['graph_mouse_track']}
+          showDataPoints={preferences['graph_data_points']}
+          lineBorderWidth={preferences['graph_line_border_width']}
+          isDatabase={did > 0}
+          sysData2={sysData1}
+          osData2={osData1}
+          memData2={memData1}
+        />
+      }
+    </>
+  );
+}
+
+Graphs_stats.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,
+  sysData1: PropTypes.array,
+  osData1: PropTypes.array,
+  memData1: PropTypes.array,
+};
+
+export function GraphsWrapper(props) {
+  const threadStatsLegendRef = useRef();
+  const cpuStatsLegendRef = useRef();
+  const memStatsLegendRef = useRef();
+  const diskStatsLegendRef = useRef();
+  const avgStatsLegendRef = useRef();
+  const nicStatsLegendRef = useRef();
+
+  const options = useMemo(()=>({
+    elements: {
+      point: {
+        radius: props.showDataPoints ? DATA_POINT_SIZE : 0,
+      },
+      line: {
+        borderWidth: props.lineBorderWidth,
+      },
+    },
+    plugins: {
+      legend: {
+        display: false,
+      },
+      tooltip: {
+        enabled: props.showTooltip,
+        callbacks: {
+          title: function(tooltipItem) {
+            let title = '';
+            try {
+              title = parseInt(tooltipItem[0].label) * tooltipItem[0].chart?.data.refreshRate + gettext(' seconds ago');
+            } catch (error) {
+              title = '';
+            }
+            return title;
+          },
+        },
+      }
+    },
+    scales: {
+      x: {
+        reverse: true,
+      },
+      y: {
+        min: 0,
+      }
+    },
+  }), [props.showTooltip, props.showDataPoints, props.lineBorderWidth]);
+  const updateOptions = useMemo(()=>({duration: 0}), []);
+
+  const onInitCallback = useCallback(
+    (legendRef)=>(chart)=>{
+      legendRef.current.innerHTML = generateLegend(chart);
+    }
+  );
+
+  return (
+    <>
+      <DashboardRow>
+        <DashboardRowCol breakpoint='md' parts={4}>
+          <ChartContainersys id='thread-graph' title={gettext('Thread Count')} legendRef={threadStatsLegendRef} errorMsg={props.errorMsg}>
+            <LineChart options={options} data={props.threadStats} updateOptions={updateOptions}
+              onInit={onInitCallback(threadStatsLegendRef)}/>
+          </ChartContainersys>
+          {!_.isUndefined(props.osData2) && props.osData2.length>0 && (<OSContainer _sysData={props.osData2}></OSContainer>)}
+        </DashboardRowCol>
+        <DashboardRowCol breakpoint='md' parts={4}>
+          <ChartContainersys id='cpu-graph' title={gettext('CPU Activity')} legendRef={cpuStatsLegendRef} errorMsg={props.errorMsg}>
+            <LineChart options={options} data={props.cpuStats} updateOptions={updateOptions}
+              onInit={onInitCallback(cpuStatsLegendRef)}/>
+          </ChartContainersys>
+          {!_.isUndefined(props.sysData2) && props.sysData2.length>0 && (<CPUContainer _sysData={props.sysData2}></CPUContainer>)}
+        </DashboardRowCol>
+        <DashboardRowCol breakpoint='md' parts={4}>
+          <ChartContainersys id='mem-graph' title={gettext('Memory')} legendRef={memStatsLegendRef} errorMsg={props.errorMsg}>
+            <LineChart  options={options} data={props.memStats} updateOptions={updateOptions}
+              onInit={onInitCallback(memStatsLegendRef)}/>
+          </ChartContainersys>
+          {!_.isUndefined(props.memData2) && props.memData2.length>0 && (<MEMContainer _sysData={props.memData2}></MEMContainer>)}
+        </DashboardRowCol>
+      </DashboardRow>
+      <DashboardRow>
+        <DashboardRowCol breakpoint='md' parts={4}>
+          <ChartContainersys id='disk-graph' title={gettext('Disk')} legendRef={diskStatsLegendRef} errorMsg={props.errorMsg}>
+            <PieChart options={options} data={props.diskStats} updateOptions={updateOptions}
+              onInit={onInitCallback(diskStatsLegendRef)}/>
+          </ChartContainersys>
+          {/* {!_.isUndefined(props.sysData2) && props.sysData2.length>0 && (<CPUContainer _sysData={props.sysData2}></CPUContainer>)} */}
+        </DashboardRowCol>
+        <DashboardRowCol breakpoint='md' parts={4}>
+          <ChartContainersys id='avg-graph' title={gettext('Average Load')} legendRef={avgStatsLegendRef} errorMsg={props.errorMsg}>
+            <LineChart options={options} data={props.avgStats} updateOptions={updateOptions}
+              onInit={onInitCallback(avgStatsLegendRef)}/>
+          </ChartContainersys>
+          {/* {!_.isUndefined(props.sysData2) && props.sysData2.length>0 && (<CPUContainer _sysData={props.sysData2}></CPUContainer>)} */}
+        </DashboardRowCol>
+        <DashboardRowCol breakpoint='md' parts={4}>
+          <ChartContainersys id='nic-graph' title={gettext('NIC Detail')} legendRef={nicStatsLegendRef} errorMsg={props.errorMsg}>
+            <LineChart options={options} data={props.nicStats} updateOptions={updateOptions}
+              onInit={onInitCallback(nicStatsLegendRef)}/>
+          </ChartContainersys>
+          {/* {!_.isUndefined(props.sysData2) && props.sysData2.length>0 && (<CPUContainer _sysData={props.sysData2}></CPUContainer>)} */}
+        </DashboardRowCol>
+      </DashboardRow>
+    </>
+  );
+}
+
+const propTypeStats = PropTypes.shape({
+  labels: PropTypes.array.isRequired,
+  datasets: PropTypes.array,
+  refreshRate: PropTypes.number.isRequired,
+});
+GraphsWrapper.propTypes = {
+  threadStats: propTypeStats.isRequired,
+  cpuStats: propTypeStats.isRequired,
+  memStats: propTypeStats.isRequired,
+  diskStats: propTypeStats.isRequired,
+  avgStats: propTypeStats.isRequired,
+  nicStats: propTypeStats.isRequired,
+  errorMsg: PropTypes.string,
+  showTooltip: PropTypes.bool.isRequired,
+  showDataPoints: PropTypes.bool.isRequired,
+  lineBorderWidth: PropTypes.number.isRequired,
+  isDatabase: PropTypes.bool.isRequired,
+  sysData2: PropTypes.array.isRequired,
+  osData2: PropTypes.array.isRequired,
+  memData2: PropTypes.array.isRequired,
+
+
+};
diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/default/cpu.sql b/web/pgadmin/dashboard/templates/dashboard/sql/default/cpu.sql
new file mode 100644
index 000000000..709f4ce9e
--- /dev/null
+++ b/web/pgadmin/dashboard/templates/dashboard/sql/default/cpu.sql
@@ -0,0 +1 @@
+/*pga4dash*/ SELECT model_name, vendor,description, logical_processor, physical_processor, no_of_cores, clock_speed_hz, l1dcache_size, l1icache_size, l2cache_size, l3cache_size FROM pg_sys_cpu_info();
diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/default/memory.sql b/web/pgadmin/dashboard/templates/dashboard/sql/default/memory.sql
new file mode 100644
index 000000000..8cab1d632
--- /dev/null
+++ b/web/pgadmin/dashboard/templates/dashboard/sql/default/memory.sql
@@ -0,0 +1 @@
+/*pga4dash*/ SELECT total_memory, used_memory, free_memory,swap_total, swap_used, swap_free FROM pg_sys_memory_info();
diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/default/os.sql b/web/pgadmin/dashboard/templates/dashboard/sql/default/os.sql
new file mode 100644
index 000000000..97c011c92
--- /dev/null
+++ b/web/pgadmin/dashboard/templates/dashboard/sql/default/os.sql
@@ -0,0 +1 @@
+/*pga4dash*/ SELECT version, name, handle_count, process_count,host_name, architecture, os_up_since_seconds, last_bootup_time, thread_count FROM pg_sys_os_info();
diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/default/system_stats.sql b/web/pgadmin/dashboard/templates/dashboard/sql/default/system_stats.sql
new file mode 100644
index 000000000..5907f16dc
--- /dev/null
+++ b/web/pgadmin/dashboard/templates/dashboard/sql/default/system_stats.sql
@@ -0,0 +1,41 @@
+/*pga4dash*/
+{% set add_union = false %}
+{% if 'thread_activity' in chart_names %}
+{% set add_union = true %}
+SELECT 'thread_activity' as chart_name, row_to_json(row(process_count, handle_count, thread_count)) as chart_data FROM pg_sys_os_info()
+{% endif %}
+{% if add_union and 'cpu_activity' in chart_names %}
+UNION ALL
+{% endif %}
+{% if 'cpu_activity' in chart_names %}
+{% set add_union = true %}
+SELECT 'cpu_activity' as chart_name, row_to_json(row(sum(usermode_normal_process_percent),sum(kernelmode_process_percent))) as chart_data  FROM pg_sys_cpu_usage_info()
+{% endif %}
+{% if add_union and 'memory_comp' in chart_names %}
+UNION ALL
+{% endif %}
+{% if 'memory_comp' in chart_names %}
+{% set add_union = true %}
+SELECT 'memory_comp' as chart_name, row_to_json(row(used_memory,free_memory)) as chart_data  FROM pg_sys_memory_info()
+{% endif %}
+{% if add_union and 'disk_info' in chart_names %}
+UNION ALL
+{% endif %}
+{% if 'disk_info' in chart_names %}
+{% set add_union = true %}
+SELECT 'disk_info' as chart_name, row_to_json(row(file_system,total_space,used_space)) as chart_data  FROM pg_sys_disk_info()
+{% endif %}
+{% if add_union and 'avg_load' in chart_names %}
+UNION ALL
+{% endif %}
+{% if 'avg_load' in chart_names %}
+{% set add_union = true %}
+SELECT 'avg_load' as chart_name, row_to_json(row(load_avg_one_minute,load_avg_five_minutes,load_avg_ten_minutes)) as chart_data  FROM pg_sys_load_avg_info()
+{% endif %}
+{% if add_union and 'nics' in chart_names %}
+UNION ALL
+{% endif %}
+{% if 'nics' in chart_names %}
+{% set add_union = true %}
+SELECT 'nics' as chart_name, row_to_json(row(interface_name,tx_bytes,tx_packets,rx_bytes,rx_packets)) as chart_data  FROM pg_sys_network_info();
+{% endif %}

Reply via email to