389-ds-base/SOURCES/0009-Issue-6756-CLI-UI-Properly-handle-disabled-NDN-cache.patch

1202 lines
66 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From b28b00ee5169cfb00414bc9bcca67f88432ad567 Mon Sep 17 00:00:00 2001
From: Simon Pichugin <spichugi@redhat.com>
Date: Thu, 10 Jul 2025 11:53:12 -0700
Subject: [PATCH] Issue 6756 - CLI, UI - Properly handle disabled NDN cache
(#6757)
Description: Fix the db_monitor function in monitor.py to check if
nsslapd-ndn-cache-enabled is off and conditionally include NDN cache
statistics only when enabled.
Update dbMonitor.jsx components to detect when NDN cache is disabled and
conditionally render NDN cache tabs, charts, and related content with proper
fallback display when disabled.
Add test_ndn_cache_disabled to verify both JSON and non-JSON output formats
correctly handle when NDN cache is turned off and on.
Fixes: https://github.com/389ds/389-ds-base/issues/6756
Reviewed by: @mreynolds389 (Thanks!)
---
dirsrvtests/tests/suites/clu/dbmon_test.py | 90 +++
src/cockpit/389-console/src/database.jsx | 4 +-
.../src/lib/database/databaseConfig.jsx | 48 +-
.../389-console/src/lib/monitor/dbMonitor.jsx | 735 ++++++++++--------
src/lib389/lib389/cli_conf/monitor.py | 77 +-
5 files changed, 580 insertions(+), 374 deletions(-)
diff --git a/dirsrvtests/tests/suites/clu/dbmon_test.py b/dirsrvtests/tests/suites/clu/dbmon_test.py
index 4a82eb0ef..b04ee67c9 100644
--- a/dirsrvtests/tests/suites/clu/dbmon_test.py
+++ b/dirsrvtests/tests/suites/clu/dbmon_test.py
@@ -11,6 +11,7 @@ import subprocess
import pytest
import json
import glob
+import re
from lib389.tasks import *
from lib389.utils import *
@@ -274,6 +275,95 @@ def test_dbmon_mp_pagesize(topology_st):
assert real_free_percentage == dbmon_free_percentage
+def test_ndn_cache_disabled(topology_st):
+ """Test dbmon output when ndn-cache-enabled is turned off
+
+ :id: 760e217c-70e8-4767-b504-dda7ba2e1f64
+ :setup: Standalone instance
+ :steps:
+ 1. Run dbmon with nsslapd-ndn-cache-enabled=on (default)
+ 2. Verify NDN cache stats are present in the output
+ 3. Set nsslapd-ndn-cache-enabled=off and restart
+ 4. Run dbmon again and verify NDN cache stats are not present
+ 5. Set nsslapd-ndn-cache-enabled=on and restart
+ 6. Run dbmon again and verify NDN cache stats are back
+ :expectedresults:
+ 1. Success
+ 2. Should display NDN cache data
+ 3. Success
+ 4. Should not display NDN cache data
+ 5. Success
+ 6. Should display NDN cache data
+ """
+ inst = topology_st.standalone
+ args = FakeArgs()
+ args.backends = None
+ args.indexes = False
+ args.json = True
+ lc = LogCapture()
+
+ log.info("Testing with NDN cache enabled (default)")
+ db_monitor(inst, DEFAULT_SUFFIX, lc.log, args)
+ db_mon_as_str = "".join((str(rec) for rec in lc.outputs))
+ db_mon_as_str = re.sub("^[^{]*{", "{", db_mon_as_str)[:-2]
+ db_mon = json.loads(db_mon_as_str)
+
+ assert 'ndncache' in db_mon
+ assert 'hit_ratio' in db_mon['ndncache']
+ lc.flush()
+
+ log.info("Setting nsslapd-ndn-cache-enabled to OFF")
+ inst.config.set('nsslapd-ndn-cache-enabled', 'off')
+ inst.restart()
+
+ log.info("Testing with NDN cache disabled")
+ db_monitor(inst, DEFAULT_SUFFIX, lc.log, args)
+ db_mon_as_str = "".join((str(rec) for rec in lc.outputs))
+ db_mon_as_str = re.sub("^[^{]*{", "{", db_mon_as_str)[:-2]
+ db_mon = json.loads(db_mon_as_str)
+
+ assert 'ndncache' not in db_mon
+ lc.flush()
+
+ log.info("Setting nsslapd-ndn-cache-enabled to ON")
+ inst.config.set('nsslapd-ndn-cache-enabled', 'on')
+ inst.restart()
+
+ log.info("Testing with NDN cache re-enabled")
+ db_monitor(inst, DEFAULT_SUFFIX, lc.log, args)
+ db_mon_as_str = "".join((str(rec) for rec in lc.outputs))
+ db_mon_as_str = re.sub("^[^{]*{", "{", db_mon_as_str)[:-2]
+ db_mon = json.loads(db_mon_as_str)
+
+ assert 'ndncache' in db_mon
+ assert 'hit_ratio' in db_mon['ndncache']
+ lc.flush()
+
+ args.json = False
+
+ log.info("Testing with NDN cache enabled - non-JSON output")
+ db_monitor(inst, DEFAULT_SUFFIX, lc.log, args)
+ output = "".join((str(rec) for rec in lc.outputs))
+
+ assert "Normalized DN Cache:" in output
+ assert "Cache Hit Ratio:" in output
+ lc.flush()
+
+ log.info("Setting nsslapd-ndn-cache-enabled to OFF")
+ inst.config.set('nsslapd-ndn-cache-enabled', 'off')
+ inst.restart()
+
+ log.info("Testing with NDN cache disabled - non-JSON output")
+ db_monitor(inst, DEFAULT_SUFFIX, lc.log, args)
+ output = "".join((str(rec) for rec in lc.outputs))
+
+ assert "Normalized DN Cache:" not in output
+ lc.flush()
+
+ inst.config.set('nsslapd-ndn-cache-enabled', 'on')
+ inst.restart()
+
+
if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
diff --git a/src/cockpit/389-console/src/database.jsx b/src/cockpit/389-console/src/database.jsx
index 276125dfc..86b642b92 100644
--- a/src/cockpit/389-console/src/database.jsx
+++ b/src/cockpit/389-console/src/database.jsx
@@ -198,7 +198,7 @@ export class Database extends React.Component {
});
const cmd = [
"dsconf", "-j", "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
- "config", "get", "nsslapd-ndn-cache-max-size"
+ "config", "get", "nsslapd-ndn-cache-max-size", "nsslapd-ndn-cache-enabled"
];
log_cmd("loadNDN", "Load NDN cache size", cmd);
cockpit
@@ -206,10 +206,12 @@ export class Database extends React.Component {
.done(content => {
const config = JSON.parse(content);
const attrs = config.attrs;
+ const ndn_cache_enabled = attrs['nsslapd-ndn-cache-enabled'][0] === "on";
this.setState(prevState => ({
globalDBConfig: {
...prevState.globalDBConfig,
ndncachemaxsize: attrs['nsslapd-ndn-cache-max-size'][0],
+ ndn_cache_enabled: ndn_cache_enabled,
},
configUpdated: 0,
loaded: true,
diff --git a/src/cockpit/389-console/src/lib/database/databaseConfig.jsx b/src/cockpit/389-console/src/lib/database/databaseConfig.jsx
index 4c7fce706..adb8227d7 100644
--- a/src/cockpit/389-console/src/lib/database/databaseConfig.jsx
+++ b/src/cockpit/389-console/src/lib/database/databaseConfig.jsx
@@ -2,12 +2,16 @@ import cockpit from "cockpit";
import React from "react";
import { log_cmd } from "../tools.jsx";
import {
+ Alert,
Button,
Checkbox,
+ Form,
Grid,
GridItem,
+ Hr,
NumberInput,
Spinner,
+ Switch,
Tab,
Tabs,
TabTitleText,
@@ -852,12 +856,29 @@ export class GlobalDatabaseConfig extends React.Component {
<Tab eventKey={3} title={<TabTitleText>{_("NDN Cache")}</TabTitleText>}>
<div className="ds-left-indent-md">
+ <Grid
+ title={_("Warning: Normalized DN Cache is disabled")}
+ className="ds-margin-top-xlg"
+ >
+ {this.props.data.ndn_cache_enabled === false && (
+ <GridItem span={8}>
+ <Alert
+ variant="warning"
+ isInline
+ title={_("Normalized DN Cache is disabled")}
+ className="ds-margin-bottom"
+ >
+ {_("The Normalized DN Cache is currently disabled. To enable it, go to Server Settings → Tuning & Limits and enable 'Normalized DN Cache', then restart the server for the changes to take effect.")}
+ </Alert>
+ </GridItem>
+ )}
+ </Grid>
<Grid
title={_("Set the maximum size in bytes for the Normalized DN Cache (nsslapd-ndn-cache-max-size).")}
className="ds-margin-top-xlg"
>
<GridItem className="ds-label" span={4}>
- {_("Normalized DN Cache Max Size")}
+ {_("Normalized DN Cache Max Size") }
</GridItem>
<GridItem span={8}>
<NumberInput
@@ -873,9 +894,9 @@ export class GlobalDatabaseConfig extends React.Component {
plusBtnAriaLabel="plus"
widthChars={10}
validated={'ndncachemaxsize' in this.state.error &&
- this.state.error['ndncachemaxsize']
- ? ValidatedOptions.error
- : ValidatedOptions.default}
+ this.state.error['ndncachemaxsize']
+ ? ValidatedOptions.error
+ : ValidatedOptions.default}
/>
</GridItem>
</Grid>
@@ -1470,7 +1491,7 @@ export class GlobalDatabaseConfigMDB extends React.Component {
<Tab eventKey={0} title={<TabTitleText>{_("Database Size")}</TabTitleText>}>
<div className="ds-left-indent-md">
<Grid
- title={_("Database maximum size in megabytes. The practical maximum size of an LMDB database is limited by the systems addressable memory (nsslapd-mdb-max-size).")}
+ title={_("Database maximum size in megabytes. The practical maximum size of an LMDB database is limited by the system's addressable memory (nsslapd-mdb-max-size).")}
className="ds-margin-top-xlg"
>
<GridItem className="ds-label" span={4}>
@@ -1641,6 +1662,23 @@ export class GlobalDatabaseConfigMDB extends React.Component {
<Tab eventKey={4} title={<TabTitleText>{_("NDN Cache")}</TabTitleText>}>
<div className="ds-left-indent-md">
+ <Grid
+ title={_("Warning: Normalized DN Cache is disabled")}
+ className="ds-margin-top-xlg"
+ >
+ {this.props.data.ndn_cache_enabled === false && (
+ <GridItem span={8}>
+ <Alert
+ variant="warning"
+ isInline
+ title={_("Normalized DN Cache is disabled")}
+ className="ds-margin-bottom"
+ >
+ {_("The Normalized DN Cache is currently disabled. To enable it, go to Server Settings → Tuning & Limits and enable 'Normalized DN Cache', then restart the server for the changes to take effect.")}
+ </Alert>
+ </GridItem>
+ )}
+ </Grid>
<Grid
title={_("Set the maximum size in bytes for the Normalized DN Cache (nsslapd-ndn-cache-max-size).")}
className="ds-margin-top-xlg"
diff --git a/src/cockpit/389-console/src/lib/monitor/dbMonitor.jsx b/src/cockpit/389-console/src/lib/monitor/dbMonitor.jsx
index bb9950ccd..c7c7c954f 100644
--- a/src/cockpit/389-console/src/lib/monitor/dbMonitor.jsx
+++ b/src/cockpit/389-console/src/lib/monitor/dbMonitor.jsx
@@ -39,7 +39,8 @@ export class DatabaseMonitor extends React.Component {
ndnCount: 5,
dbCacheList: [],
ndnCacheList: [],
- ndnCacheUtilList: []
+ ndnCacheUtilList: [],
+ ndn_cache_enabled: false
};
// Toggle currently active tab
@@ -110,6 +111,7 @@ export class DatabaseMonitor extends React.Component {
{ name: "", x: "4", y: 0 },
{ name: "", x: "5", y: 0 },
],
+ ndn_cache_enabled: false
});
}
@@ -136,19 +138,27 @@ export class DatabaseMonitor extends React.Component {
chart_data.shift();
chart_data.push({ name: _("Cache Hit Ratio"), x: count.toString(), y: parseInt(dbratio) });
- // Build up the NDN Cache chart data
- const ndnratio = config.attrs.normalizeddncachehitratio[0];
- const ndn_chart_data = this.state.ndnCacheList;
- ndn_chart_data.shift();
- ndn_chart_data.push({ name: _("Cache Hit Ratio"), x: count.toString(), y: parseInt(ndnratio) });
-
- // Build up the DB Cache Util chart data
- const ndn_util_chart_data = this.state.ndnCacheUtilList;
- const currNDNSize = parseInt(config.attrs.currentnormalizeddncachesize[0]);
- const maxNDNSize = parseInt(config.attrs.maxnormalizeddncachesize[0]);
- const ndn_utilization = (currNDNSize / maxNDNSize) * 100;
- ndn_util_chart_data.shift();
- ndn_util_chart_data.push({ name: _("Cache Utilization"), x: ndnCount.toString(), y: parseInt(ndn_utilization) });
+ // Check if NDN cache is enabled
+ const ndn_cache_enabled = config.attrs.normalizeddncachehitratio &&
+ config.attrs.normalizeddncachehitratio.length > 0;
+ let ndn_chart_data = this.state.ndnCacheList;
+ let ndn_util_chart_data = this.state.ndnCacheUtilList;
+
+ // Only build NDN cache chart data if NDN cache is enabled
+ if (ndn_cache_enabled) {
+ const ndnratio = config.attrs.normalizeddncachehitratio[0];
+ ndn_chart_data = this.state.ndnCacheList;
+ ndn_chart_data.shift();
+ ndn_chart_data.push({ name: _("Cache Hit Ratio"), x: count.toString(), y: parseInt(ndnratio) });
+
+ // Build up the NDN Cache Util chart data
+ ndn_util_chart_data = this.state.ndnCacheUtilList;
+ const currNDNSize = parseInt(config.attrs.currentnormalizeddncachesize[0]);
+ const maxNDNSize = parseInt(config.attrs.maxnormalizeddncachesize[0]);
+ const ndn_utilization = (currNDNSize / maxNDNSize) * 100;
+ ndn_util_chart_data.shift();
+ ndn_util_chart_data.push({ name: _("Cache Utilization"), x: ndnCount.toString(), y: parseInt(ndn_utilization) });
+ }
this.setState({
data: config.attrs,
@@ -157,7 +167,8 @@ export class DatabaseMonitor extends React.Component {
ndnCacheList: ndn_chart_data,
ndnCacheUtilList: ndn_util_chart_data,
count,
- ndnCount
+ ndnCount,
+ ndn_cache_enabled
});
})
.fail(() => {
@@ -197,13 +208,20 @@ export class DatabaseMonitor extends React.Component {
if (!this.state.loading) {
dbcachehit = parseInt(this.state.data.dbcachehitratio[0]);
- ndncachehit = parseInt(this.state.data.normalizeddncachehitratio[0]);
- ndncachemax = parseInt(this.state.data.maxnormalizeddncachesize[0]);
- ndncachecurr = parseInt(this.state.data.currentnormalizeddncachesize[0]);
- utilratio = Math.round((ndncachecurr / ndncachemax) * 100);
- if (utilratio === 0) {
- // Just round up to 1
- utilratio = 1;
+
+ // Check if NDN cache is enabled
+ const ndn_cache_enabled = this.state.data.normalizeddncachehitratio &&
+ this.state.data.normalizeddncachehitratio.length > 0;
+
+ if (ndn_cache_enabled) {
+ ndncachehit = parseInt(this.state.data.normalizeddncachehitratio[0]);
+ ndncachemax = parseInt(this.state.data.maxnormalizeddncachesize[0]);
+ ndncachecurr = parseInt(this.state.data.currentnormalizeddncachesize[0]);
+ utilratio = Math.round((ndncachecurr / ndncachemax) * 100);
+ if (utilratio === 0) {
+ // Just round up to 1
+ utilratio = 1;
+ }
}
// Database cache
@@ -214,119 +232,131 @@ export class DatabaseMonitor extends React.Component {
} else {
chartColor = ChartThemeColor.purple;
}
- // NDN cache ratio
- if (ndncachehit > 89) {
- ndnChartColor = ChartThemeColor.green;
- } else if (ndncachehit > 74) {
- ndnChartColor = ChartThemeColor.orange;
- } else {
- ndnChartColor = ChartThemeColor.purple;
- }
- // NDN cache utilization
- if (utilratio > 95) {
- ndnUtilColor = ChartThemeColor.purple;
- } else if (utilratio > 90) {
- ndnUtilColor = ChartThemeColor.orange;
- } else {
- ndnUtilColor = ChartThemeColor.green;
+
+ // NDN cache colors only if enabled
+ if (ndn_cache_enabled) {
+ // NDN cache ratio
+ if (ndncachehit > 89) {
+ ndnChartColor = ChartThemeColor.green;
+ } else if (ndncachehit > 74) {
+ ndnChartColor = ChartThemeColor.orange;
+ } else {
+ ndnChartColor = ChartThemeColor.purple;
+ }
+ // NDN cache utilization
+ if (utilratio > 95) {
+ ndnUtilColor = ChartThemeColor.purple;
+ } else if (utilratio > 90) {
+ ndnUtilColor = ChartThemeColor.orange;
+ } else {
+ ndnUtilColor = ChartThemeColor.green;
+ }
}
- content = (
- <Tabs activeKey={this.state.activeTabKey} onSelect={this.handleNavSelect}>
- <Tab eventKey={0} title={<TabTitleText>{_("Database Cache")}</TabTitleText>}>
- <div className="ds-margin-top">
- <Card isSelectable>
- <CardBody>
- <div className="ds-container">
- <div className="ds-center">
- <TextContent className="ds-margin-top-xlg" title={_("The database cache hit ratio (dbcachehitratio).")}>
- <Text component={TextVariants.h3}>
- {_("Cache Hit Ratio")}
- </Text>
- </TextContent>
- <TextContent>
- <Text component={TextVariants.h2}>
- <b>{dbcachehit}%</b>
- </Text>
- </TextContent>
- </div>
- <div className="ds-margin-left" style={{ height: '200px', width: '500px' }}>
- <Chart
- ariaDesc="Database Cache"
- ariaTitle={_("Live Database Cache Statistics")}
- containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
- height={200}
- maxDomain={{ y: 100 }}
- minDomain={{ y: 0 }}
- padding={{
- bottom: 30,
- left: 40,
- top: 10,
- right: 10,
- }}
- width={500}
- themeColor={chartColor}
- >
- <ChartAxis />
- <ChartAxis dependentAxis showGrid tickValues={[25, 50, 75, 100]} />
- <ChartGroup>
- <ChartArea
- data={this.state.dbCacheList}
- />
- </ChartGroup>
- </Chart>
- </div>
+ // Create tabs based on what caches are available
+ const tabs = [];
+
+ // Database Cache tab is always available
+ tabs.push(
+ <Tab eventKey={0} key="db-cache-tab" title={<TabTitleText>{_("Database Cache")}</TabTitleText>}>
+ <div className="ds-margin-top">
+ <Card isSelectable>
+ <CardBody>
+ <div className="ds-container">
+ <div className="ds-center">
+ <TextContent className="ds-margin-top-xlg" title={_("The database cache hit ratio (dbcachehitratio).")}>
+ <Text component={TextVariants.h3}>
+ {_("Cache Hit Ratio")}
+ </Text>
+ </TextContent>
+ <TextContent>
+ <Text component={TextVariants.h2}>
+ <b>{dbcachehit}%</b>
+ </Text>
+ </TextContent>
</div>
- </CardBody>
- </Card>
- </div>
+ <div className="ds-margin-left" style={{ height: '200px', width: '500px' }}>
+ <Chart
+ ariaDesc="Database Cache"
+ ariaTitle={_("Live Database Cache Statistics")}
+ containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
+ height={200}
+ maxDomain={{ y: 100 }}
+ minDomain={{ y: 0 }}
+ padding={{
+ bottom: 30,
+ left: 40,
+ top: 10,
+ right: 10,
+ }}
+ width={500}
+ themeColor={chartColor}
+ >
+ <ChartAxis />
+ <ChartAxis dependentAxis showGrid tickValues={[25, 50, 75, 100]} />
+ <ChartGroup>
+ <ChartArea
+ data={this.state.dbCacheList}
+ />
+ </ChartGroup>
+ </Chart>
+ </div>
+ </div>
+ </CardBody>
+ </Card>
+ </div>
+
+ <Grid hasGutter className="ds-margin-top-xlg">
+ <GridItem span={3}>
+ {_("Database Cache Hit Ratio:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{this.state.data.dbcachehitratio}%</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("Database Cache Tries:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.dbcachetries)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("Database Cache Hits:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.dbcachehits)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("Cache Pages Read:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.dbcachepagein)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("Cache Pages Written:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.dbcachepageout)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("Read-Only Page Evictions:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.dbcacheroevict)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("Read-Write Page Evictions:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.dbcacherwevict)}</b>
+ </GridItem>
+ </Grid>
+ </Tab>
+ );
- <Grid hasGutter className="ds-margin-top-xlg">
- <GridItem span={3}>
- {_("Database Cache Hit Ratio:")}
- </GridItem>
- <GridItem span={2}>
- <b>{this.state.data.dbcachehitratio}%</b>
- </GridItem>
- <GridItem span={3}>
- {_("Database Cache Tries:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.dbcachetries)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("Database Cache Hits:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.dbcachehits)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("Cache Pages Read:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.dbcachepagein)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("Cache Pages Written:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.dbcachepageout)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("Read-Only Page Evictions:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.dbcacheroevict)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("Read-Write Page Evictions:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.dbcacherwevict)}</b>
- </GridItem>
- </Grid>
- </Tab>
- <Tab eventKey={1} title={<TabTitleText>{_("Normalized DN Cache")}</TabTitleText>}>
+ // Only add NDN Cache tab if NDN cache is enabled
+ if (ndn_cache_enabled) {
+ tabs.push(
+ <Tab eventKey={1} key="ndn-cache-tab" title={<TabTitleText>{_("Normalized DN Cache")}</TabTitleText>}>
<div className="ds-margin-top-lg">
<Grid hasGutter>
<GridItem span={6}>
@@ -487,6 +517,12 @@ export class DatabaseMonitor extends React.Component {
</Grid>
</div>
</Tab>
+ );
+ }
+
+ content = (
+ <Tabs activeKey={this.state.activeTabKey} onSelect={this.handleNavSelect}>
+ {tabs}
</Tabs>
);
}
@@ -533,7 +569,8 @@ export class DatabaseMonitorMDB extends React.Component {
ndnCount: 5,
dbCacheList: [],
ndnCacheList: [],
- ndnCacheUtilList: []
+ ndnCacheUtilList: [],
+ ndn_cache_enabled: false
};
// Toggle currently active tab
@@ -585,6 +622,7 @@ export class DatabaseMonitorMDB extends React.Component {
{ name: "", x: "4", y: 0 },
{ name: "", x: "5", y: 0 },
],
+ ndn_cache_enabled: false
});
}
@@ -605,19 +643,28 @@ export class DatabaseMonitorMDB extends React.Component {
count = 1;
}
- // Build up the NDN Cache chart data
- const ndnratio = config.attrs.normalizeddncachehitratio[0];
- const ndn_chart_data = this.state.ndnCacheList;
- ndn_chart_data.shift();
- ndn_chart_data.push({ name: _("Cache Hit Ratio"), x: count.toString(), y: parseInt(ndnratio) });
-
- // Build up the DB Cache Util chart data
- const ndn_util_chart_data = this.state.ndnCacheUtilList;
- const currNDNSize = parseInt(config.attrs.currentnormalizeddncachesize[0]);
- const maxNDNSize = parseInt(config.attrs.maxnormalizeddncachesize[0]);
- const ndn_utilization = (currNDNSize / maxNDNSize) * 100;
- ndn_util_chart_data.shift();
- ndn_util_chart_data.push({ name: _("Cache Utilization"), x: ndnCount.toString(), y: parseInt(ndn_utilization) });
+ // Check if NDN cache is enabled
+ const ndn_cache_enabled = config.attrs.normalizeddncachehitratio &&
+ config.attrs.normalizeddncachehitratio.length > 0;
+ let ndn_chart_data = this.state.ndnCacheList;
+ let ndn_util_chart_data = this.state.ndnCacheUtilList;
+
+ // Only build NDN cache chart data if NDN cache is enabled
+ if (ndn_cache_enabled) {
+ // Build up the NDN Cache chart data
+ const ndnratio = config.attrs.normalizeddncachehitratio[0];
+ ndn_chart_data = this.state.ndnCacheList;
+ ndn_chart_data.shift();
+ ndn_chart_data.push({ name: _("Cache Hit Ratio"), x: count.toString(), y: parseInt(ndnratio) });
+
+ // Build up the DB Cache Util chart data
+ ndn_util_chart_data = this.state.ndnCacheUtilList;
+ const currNDNSize = parseInt(config.attrs.currentnormalizeddncachesize[0]);
+ const maxNDNSize = parseInt(config.attrs.maxnormalizeddncachesize[0]);
+ const ndn_utilization = (currNDNSize / maxNDNSize) * 100;
+ ndn_util_chart_data.shift();
+ ndn_util_chart_data.push({ name: _("Cache Utilization"), x: ndnCount.toString(), y: parseInt(ndn_utilization) });
+ }
this.setState({
data: config.attrs,
@@ -625,7 +672,8 @@ export class DatabaseMonitorMDB extends React.Component {
ndnCacheList: ndn_chart_data,
ndnCacheUtilList: ndn_util_chart_data,
count,
- ndnCount
+ ndnCount,
+ ndn_cache_enabled
});
})
.fail(() => {
@@ -662,197 +710,214 @@ export class DatabaseMonitorMDB extends React.Component {
);
if (!this.state.loading) {
- ndncachehit = parseInt(this.state.data.normalizeddncachehitratio[0]);
- ndncachemax = parseInt(this.state.data.maxnormalizeddncachesize[0]);
- ndncachecurr = parseInt(this.state.data.currentnormalizeddncachesize[0]);
- utilratio = Math.round((ndncachecurr / ndncachemax) * 100);
- if (utilratio === 0) {
- // Just round up to 1
- utilratio = 1;
- }
-
- // NDN cache ratio
- if (ndncachehit > 89) {
- ndnChartColor = ChartThemeColor.green;
- } else if (ndncachehit > 74) {
- ndnChartColor = ChartThemeColor.orange;
- } else {
- ndnChartColor = ChartThemeColor.purple;
- }
- // NDN cache utilization
- if (utilratio > 95) {
- ndnUtilColor = ChartThemeColor.purple;
- } else if (utilratio > 90) {
- ndnUtilColor = ChartThemeColor.orange;
- } else {
- ndnUtilColor = ChartThemeColor.green;
- }
-
- content = (
- <Tabs activeKey={this.state.activeTabKey} onSelect={this.handleNavSelect}>
- <Tab eventKey={0} title={<TabTitleText>{_("Normalized DN Cache")}</TabTitleText>}>
- <div className="ds-margin-top-lg">
- <Grid hasGutter>
- <GridItem span={6}>
- <Card isSelectable>
- <CardBody>
- <div className="ds-container">
- <div className="ds-center">
- <TextContent className="ds-margin-top-xlg" title={_("The normalized DN cache hit ratio (normalizeddncachehitratio).")}>
- <Text component={TextVariants.h3}>
- {_("Cache Hit Ratio")}
- </Text>
- </TextContent>
- <TextContent>
- <Text component={TextVariants.h2}>
- <b>{ndncachehit}%</b>
- </Text>
- </TextContent>
- </div>
- <div className="ds-margin-left" style={{ height: '200px', width: '350px' }}>
- <Chart
- ariaDesc="NDN Cache"
- ariaTitle={_("Live Normalized DN Cache Statistics")}
- containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
- height={200}
- maxDomain={{ y: 100 }}
- minDomain={{ y: 0 }}
- padding={{
- bottom: 40,
- left: 60,
- top: 10,
- right: 15,
- }}
- width={350}
- themeColor={ndnChartColor}
- >
- <ChartAxis />
- <ChartAxis dependentAxis showGrid tickValues={[25, 50, 75, 100]} />
- <ChartGroup>
- <ChartArea
- data={this.state.ndnCacheList}
- />
- </ChartGroup>
- </Chart>
- </div>
- </div>
- </CardBody>
- </Card>
- </GridItem>
- <GridItem span={6}>
- <Card isSelectable>
- <CardBody>
- <div className="ds-container">
- <div className="ds-center">
- <TextContent className="ds-margin-top-lg" title={_("The amount of the cache that is being used: max size (maxnormalizeddncachesize) vs current size (currentnormalizeddncachesize)")}>
- <Text component={TextVariants.h2}>
- {_("Cache Utilization")}
- </Text>
- </TextContent>
- <TextContent>
- <Text component={TextVariants.h3}>
- <b>{utilratio}%</b>
- </Text>
- </TextContent>
- <TextContent className="ds-margin-top-xlg">
- <Text component={TextVariants.h5}>
- {_("Cached DN's")}
- </Text>
- </TextContent>
- <b>{numToCommas(this.state.data.currentnormalizeddncachecount[0])}</b>
+ // Check if NDN cache is enabled
+ const ndn_cache_enabled = this.state.data.normalizeddncachehitratio &&
+ this.state.data.normalizeddncachehitratio.length > 0;
+
+ if (ndn_cache_enabled) {
+ ndncachehit = parseInt(this.state.data.normalizeddncachehitratio[0]);
+ ndncachemax = parseInt(this.state.data.maxnormalizeddncachesize[0]);
+ ndncachecurr = parseInt(this.state.data.currentnormalizeddncachesize[0]);
+ utilratio = Math.round((ndncachecurr / ndncachemax) * 100);
+ if (utilratio === 0) {
+ // Just round up to 1
+ utilratio = 1;
+ }
+
+ // NDN cache ratio
+ if (ndncachehit > 89) {
+ ndnChartColor = ChartThemeColor.green;
+ } else if (ndncachehit > 74) {
+ ndnChartColor = ChartThemeColor.orange;
+ } else {
+ ndnChartColor = ChartThemeColor.purple;
+ }
+ // NDN cache utilization
+ if (utilratio > 95) {
+ ndnUtilColor = ChartThemeColor.purple;
+ } else if (utilratio > 90) {
+ ndnUtilColor = ChartThemeColor.orange;
+ } else {
+ ndnUtilColor = ChartThemeColor.green;
+ }
+
+ content = (
+ <Tabs activeKey={this.state.activeTabKey} onSelect={this.handleNavSelect}>
+ <Tab eventKey={0} title={<TabTitleText>{_("Normalized DN Cache")}</TabTitleText>}>
+ <div className="ds-margin-top-lg">
+ <Grid hasGutter>
+ <GridItem span={6}>
+ <Card isSelectable>
+ <CardBody>
+ <div className="ds-container">
+ <div className="ds-center">
+ <TextContent className="ds-margin-top-xlg" title={_("The normalized DN cache hit ratio (normalizeddncachehitratio).")}>
+ <Text component={TextVariants.h3}>
+ {_("Cache Hit Ratio")}
+ </Text>
+ </TextContent>
+ <TextContent>
+ <Text component={TextVariants.h2}>
+ <b>{ndncachehit}%</b>
+ </Text>
+ </TextContent>
+ </div>
+ <div className="ds-margin-left" style={{ height: '200px', width: '350px' }}>
+ <Chart
+ ariaDesc="NDN Cache"
+ ariaTitle={_("Live Normalized DN Cache Statistics")}
+ containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
+ height={200}
+ maxDomain={{ y: 100 }}
+ minDomain={{ y: 0 }}
+ padding={{
+ bottom: 40,
+ left: 60,
+ top: 10,
+ right: 15,
+ }}
+ width={350}
+ themeColor={ndnChartColor}
+ >
+ <ChartAxis />
+ <ChartAxis dependentAxis showGrid tickValues={[25, 50, 75, 100]} />
+ <ChartGroup>
+ <ChartArea
+ data={this.state.ndnCacheList}
+ />
+ </ChartGroup>
+ </Chart>
+ </div>
</div>
- <div className="ds-margin-left" style={{ height: '200px', width: '350px' }}>
- <Chart
- ariaDesc="NDN Cache Utilization"
- ariaTitle={_("Live Normalized DN Cache Utilization Statistics")}
- containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
- height={200}
- maxDomain={{ y: 100 }}
- minDomain={{ y: 0 }}
- padding={{
- bottom: 40,
- left: 60,
- top: 10,
- right: 15,
- }}
- width={350}
- themeColor={ndnUtilColor}
- >
- <ChartAxis />
- <ChartAxis dependentAxis showGrid tickValues={[25, 50, 75, 100]} />
- <ChartGroup>
- <ChartArea
- data={this.state.ndnCacheUtilList}
- />
- </ChartGroup>
- </Chart>
+ </CardBody>
+ </Card>
+ </GridItem>
+ <GridItem span={6}>
+ <Card isSelectable>
+ <CardBody>
+ <div className="ds-container">
+ <div className="ds-center">
+ <TextContent className="ds-margin-top-lg" title={_("The amount of the cache that is being used: max size (maxnormalizeddncachesize) vs current size (currentnormalizeddncachesize)")}>
+ <Text component={TextVariants.h2}>
+ {_("Cache Utilization")}
+ </Text>
+ </TextContent>
+ <TextContent>
+ <Text component={TextVariants.h3}>
+ <b>{utilratio}%</b>
+ </Text>
+ </TextContent>
+ <TextContent className="ds-margin-top-xlg">
+ <Text component={TextVariants.h5}>
+ {_("Cached DN's")}
+ </Text>
+ </TextContent>
+ <b>{numToCommas(this.state.data.currentnormalizeddncachecount[0])}</b>
+ </div>
+ <div className="ds-margin-left" style={{ height: '200px', width: '350px' }}>
+ <Chart
+ ariaDesc="NDN Cache Utilization"
+ ariaTitle={_("Live Normalized DN Cache Utilization Statistics")}
+ containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
+ height={200}
+ maxDomain={{ y: 100 }}
+ minDomain={{ y: 0 }}
+ padding={{
+ bottom: 40,
+ left: 60,
+ top: 10,
+ right: 15,
+ }}
+ width={350}
+ themeColor={ndnUtilColor}
+ >
+ <ChartAxis />
+ <ChartAxis dependentAxis showGrid tickValues={[25, 50, 75, 100]} />
+ <ChartGroup>
+ <ChartArea
+ data={this.state.ndnCacheUtilList}
+ />
+ </ChartGroup>
+ </Chart>
+ </div>
</div>
- </div>
- </CardBody>
- </Card>
- </GridItem>
- </Grid>
-
- <Grid hasGutter className="ds-margin-top-xlg">
- <GridItem span={3}>
- {_("NDN Cache Hit Ratio:")}
- </GridItem>
- <GridItem span={2}>
- <b>{this.state.data.normalizeddncachehitratio}%</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache Max Size:")}
- </GridItem>
- <GridItem span={2}>
- <b>{displayBytes(this.state.data.maxnormalizeddncachesize)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache Tries:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.normalizeddncachetries)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Current Cache Size:")}
- </GridItem>
- <GridItem span={2}>
- <b>{displayBytes(this.state.data.currentnormalizeddncachesize)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache Hits:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.normalizeddncachehits)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache DN Count:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.currentnormalizeddncachecount)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache Evictions:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.normalizeddncacheevictions)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache Thread Size:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.normalizeddncachethreadsize)}</b>
- </GridItem>
- <GridItem span={3}>
- {_("NDN Cache Thread Slots:")}
- </GridItem>
- <GridItem span={2}>
- <b>{numToCommas(this.state.data.normalizeddncachethreadslots)}</b>
- </GridItem>
- </Grid>
- </div>
- </Tab>
- </Tabs>
- );
+ </CardBody>
+ </Card>
+ </GridItem>
+ </Grid>
+
+ <Grid hasGutter className="ds-margin-top-xlg">
+ <GridItem span={3}>
+ {_("NDN Cache Hit Ratio:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{this.state.data.normalizeddncachehitratio}%</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache Max Size:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{displayBytes(this.state.data.maxnormalizeddncachesize)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache Tries:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.normalizeddncachetries)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Current Cache Size:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{displayBytes(this.state.data.currentnormalizeddncachesize)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache Hits:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.normalizeddncachehits)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache DN Count:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.currentnormalizeddncachecount)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache Evictions:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.normalizeddncacheevictions)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache Thread Size:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.normalizeddncachethreadsize)}</b>
+ </GridItem>
+ <GridItem span={3}>
+ {_("NDN Cache Thread Slots:")}
+ </GridItem>
+ <GridItem span={2}>
+ <b>{numToCommas(this.state.data.normalizeddncachethreadslots)}</b>
+ </GridItem>
+ </Grid>
+ </div>
+ </Tab>
+ </Tabs>
+ );
+ } else {
+ // No NDN cache available
+ content = (
+ <div className="ds-margin-top-xlg ds-center">
+ <TextContent>
+ <Text component={TextVariants.h3}>
+ {_("Normalized DN Cache is disabled")}
+ </Text>
+ </TextContent>
+ </div>
+ );
+ }
}
return (
diff --git a/src/lib389/lib389/cli_conf/monitor.py b/src/lib389/lib389/cli_conf/monitor.py
index b01796549..c7f9322d1 100644
--- a/src/lib389/lib389/cli_conf/monitor.py
+++ b/src/lib389/lib389/cli_conf/monitor.py
@@ -129,6 +129,14 @@ def db_monitor(inst, basedn, log, args):
# Gather the global DB stats
report_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
ldbm_mon = ldbm_monitor.get_status()
+ ndn_cache_enabled = inst.config.get_attr_val_utf8('nsslapd-ndn-cache-enabled') == 'on'
+
+ # Build global cache stats
+ result = {
+ 'date': report_time,
+ 'backends': {},
+ }
+
if ldbm_monitor.inst_db_impl == DB_IMPL_BDB:
dbcachesize = int(ldbm_mon['nsslapd-db-cache-size-bytes'][0])
# Warning: there are two different page sizes associated with bdb:
@@ -153,32 +161,6 @@ def db_monitor(inst, basedn, log, args):
dbcachefree = max(int(dbcachesize - (pagesize * dbpages)), 0)
dbcachefreeratio = dbcachefree/dbcachesize
- ndnratio = ldbm_mon['normalizeddncachehitratio'][0]
- ndncursize = int(ldbm_mon['currentnormalizeddncachesize'][0])
- ndnmaxsize = int(ldbm_mon['maxnormalizeddncachesize'][0])
- ndncount = ldbm_mon['currentnormalizeddncachecount'][0]
- ndnevictions = ldbm_mon['normalizeddncacheevictions'][0]
- if ndncursize > ndnmaxsize:
- ndnfree = 0
- ndnfreeratio = 0
- else:
- ndnfree = ndnmaxsize - ndncursize
- ndnfreeratio = "{:.1f}".format(ndnfree / ndnmaxsize * 100)
-
- # Build global cache stats
- result = {
- 'date': report_time,
- 'ndncache': {
- 'hit_ratio': ndnratio,
- 'free': convert_bytes(str(ndnfree)),
- 'free_percentage': ndnfreeratio,
- 'count': ndncount,
- 'evictions': ndnevictions
- },
- 'backends': {},
- }
-
- if ldbm_monitor.inst_db_impl == DB_IMPL_BDB:
result['dbcache'] = {
'hit_ratio': dbhitratio,
'free': convert_bytes(str(dbcachefree)),
@@ -188,6 +170,32 @@ def db_monitor(inst, basedn, log, args):
'pageout': dbcachepageout
}
+ # Add NDN cache stats only if enabled
+ if ndn_cache_enabled:
+ try:
+ ndnratio = ldbm_mon['normalizeddncachehitratio'][0]
+ ndncursize = int(ldbm_mon['currentnormalizeddncachesize'][0])
+ ndnmaxsize = int(ldbm_mon['maxnormalizeddncachesize'][0])
+ ndncount = ldbm_mon['currentnormalizeddncachecount'][0]
+ ndnevictions = ldbm_mon['normalizeddncacheevictions'][0]
+ if ndncursize > ndnmaxsize:
+ ndnfree = 0
+ ndnfreeratio = 0
+ else:
+ ndnfree = ndnmaxsize - ndncursize
+ ndnfreeratio = "{:.1f}".format(ndnfree / ndnmaxsize * 100)
+
+ result['ndncache'] = {
+ 'hit_ratio': ndnratio,
+ 'free': convert_bytes(str(ndnfree)),
+ 'free_percentage': ndnfreeratio,
+ 'count': ndncount,
+ 'evictions': ndnevictions
+ }
+ # In case, the user enabled NDN cache but still have not restarted the instance
+ except IndexError:
+ ndn_cache_enabled = False
+
# Build the backend results
for be in backend_objs:
be_name = be.rdn
@@ -277,13 +285,16 @@ def db_monitor(inst, basedn, log, args):
log.info(" - Pages In: {}".format(result['dbcache']['pagein']))
log.info(" - Pages Out: {}".format(result['dbcache']['pageout']))
log.info("")
- log.info("Normalized DN Cache:")
- log.info(" - Cache Hit Ratio: {}%".format(result['ndncache']['hit_ratio']))
- log.info(" - Free Space: {}".format(result['ndncache']['free']))
- log.info(" - Free Percentage: {}%".format(result['ndncache']['free_percentage']))
- log.info(" - DN Count: {}".format(result['ndncache']['count']))
- log.info(" - Evictions: {}".format(result['ndncache']['evictions']))
- log.info("")
+
+ if ndn_cache_enabled:
+ log.info("Normalized DN Cache:")
+ log.info(" - Cache Hit Ratio: {}%".format(result['ndncache']['hit_ratio']))
+ log.info(" - Free Space: {}".format(result['ndncache']['free']))
+ log.info(" - Free Percentage: {}%".format(result['ndncache']['free_percentage']))
+ log.info(" - DN Count: {}".format(result['ndncache']['count']))
+ log.info(" - Evictions: {}".format(result['ndncache']['evictions']))
+ log.info("")
+
log.info("Backends:")
for be_name, attr_dict in result['backends'].items():
log.info(f" - {attr_dict['suffix']} ({be_name}):")
--
2.49.0