Skip to content

Commit 3a4e626

Browse files
author
arthosofteq
authored
Merge pull request #761 from RedisInsight/feature/RI-2642-total-keys-per-db
#RI-3038 BE return total keys per database if dbN > 1
2 parents 93144f6 + bb86abf commit 3a4e626

File tree

4 files changed

+67
-13
lines changed

4 files changed

+67
-13
lines changed

redisinsight/api/src/modules/instances/dto/database-overview.dto.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ export class DatabaseOverview {
1919
})
2020
totalKeys?: number;
2121

22+
@ApiPropertyOptional({
23+
description: 'Nested object with total number of keys per logical database',
24+
type: Number,
25+
})
26+
totalKeysPerDb?: Record<string, number>;
27+
2228
@ApiPropertyOptional({
2329
description: 'Median for connected clients in the all shards',
2430
type: Number,

redisinsight/api/src/modules/shared/services/instances-business/overview.service.spec.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const mockClientsInfo = {
4141
const mockKeyspace = {
4242
db0: 'keys=1,expires=0,avg_ttl=0',
4343
db1: 'keys=0,expires=0,avg_ttl=0',
44-
db2: 'keys=0,expires=0,avg_ttl=0',
44+
db2: 'keys=1,expires=0,avg_ttl=0',
4545
};
4646
const mockNodeInfo = {
4747
host: 'localhost',
@@ -59,7 +59,11 @@ const databaseId = mockStandaloneDatabaseEntity.id;
5959
export const mockDatabaseOverview: DatabaseOverview = {
6060
version: mockServerInfo.redis_version,
6161
usedMemory: 1,
62-
totalKeys: 1,
62+
totalKeys: 2,
63+
totalKeysPerDb: {
64+
db0: 1,
65+
db2: 1,
66+
},
6367
connectedClients: 1,
6468
opsPerSecond: 1,
6569
networkInKbps: 1,
@@ -94,13 +98,28 @@ describe('OverviewService', () => {
9498
version: '6.0.5',
9599
connectedClients: 1,
96100
totalKeys: 1,
101+
totalKeysPerDb: undefined,
97102
usedMemory: 1000000,
98103
cpuUsagePercentage: undefined,
99104
opsPerSecond: undefined,
100105
networkInKbps: undefined,
101106
networkOutKbps: undefined,
102107
});
103108
});
109+
it('should return total 0 and empty total per db object', async () => {
110+
spyGetNodeInfo.mockResolvedValueOnce({
111+
...mockNodeInfo,
112+
keyspace: {
113+
db0: 'keys=0,expires=0,avg_ttl=0',
114+
},
115+
});
116+
117+
expect(await service.getOverview(databaseId, mockClient)).toEqual({
118+
...mockDatabaseOverview,
119+
totalKeys: 0,
120+
totalKeysPerDb: undefined,
121+
});
122+
});
104123
it('check for cpu on second attempt', async () => {
105124
spyGetNodeInfo.mockResolvedValueOnce(mockNodeInfo);
106125
spyGetNodeInfo.mockResolvedValueOnce({
@@ -205,7 +224,11 @@ describe('OverviewService', () => {
205224
expect(await service.getOverview(databaseId, mockCluster)).toEqual({
206225
...mockDatabaseOverview,
207226
connectedClients: 1,
208-
totalKeys: 3,
227+
totalKeys: 6,
228+
totalKeysPerDb: {
229+
db0: 3,
230+
db2: 3,
231+
},
209232
usedMemory: 3,
210233
networkInKbps: 6,
211234
networkOutKbps: 6,
@@ -256,7 +279,11 @@ describe('OverviewService', () => {
256279
expect(await service.getOverview(databaseId, mockCluster)).toEqual({
257280
...mockDatabaseOverview,
258281
connectedClients: 1,
259-
totalKeys: 3,
282+
totalKeys: 6,
283+
totalKeysPerDb: {
284+
db0: 3,
285+
db2: 3,
286+
},
260287
usedMemory: 3,
261288
networkInKbps: 6,
262289
networkOutKbps: 6,

redisinsight/api/src/modules/shared/services/instances-business/overview.service.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ export class OverviewService {
3434
nodesInfo = [await this.getNodeInfo(client)];
3535
}
3636

37+
const [totalKeys, totalKeysPerDb] = this.calculateTotalKeys(nodesInfo);
3738
return {
3839
version: this.getVersion(nodesInfo),
39-
totalKeys: this.calculateTotalKeys(nodesInfo),
40+
totalKeys,
41+
totalKeysPerDb,
4042
usedMemory: this.calculateUsedMemory(nodesInfo),
4143
connectedClients: this.calculateConnectedClients(nodesInfo),
4244
opsPerSecond: this.calculateOpsPerSec(nodesInfo),
@@ -192,27 +194,44 @@ export class OverviewService {
192194
* @param nodes
193195
* @private
194196
*/
195-
private calculateTotalKeys(nodes = []): number {
197+
private calculateTotalKeys(nodes = []): [number, Record<string, number>] {
196198
if (!this.isMetricsAvailable(nodes, 'keyspace', [undefined])) {
197-
return undefined;
199+
return [undefined, undefined];
198200
}
199201

200202
try {
201203
const masterNodes = filter(nodes, (node) => ['master', undefined].includes(
202204
get(node, 'replication.role'),
203205
));
204206

205-
return sumBy(masterNodes, (node) => sum(
207+
const totalKeysPerDb = {};
208+
209+
masterNodes.forEach((node) => {
206210
map(
207211
get(node, 'keyspace', {}),
208-
(dbKeys): number => {
212+
(dbKeys, dbNumber): void => {
209213
const { keys } = convertBulkStringsToObject(dbKeys, ',', '=');
210-
return parseInt(keys, 10);
214+
215+
if (!totalKeysPerDb[dbNumber]) {
216+
totalKeysPerDb[dbNumber] = 0;
217+
}
218+
219+
totalKeysPerDb[dbNumber] += parseInt(keys, 10);
211220
},
212-
),
213-
));
221+
);
222+
});
223+
224+
// filter 0 values
225+
Object.keys(totalKeysPerDb).forEach((key) => {
226+
if (!totalKeysPerDb[key]) {
227+
delete totalKeysPerDb[key];
228+
}
229+
});
230+
231+
const totalKeys = totalKeysPerDb ? sum(Object.values(totalKeysPerDb)) : undefined;
232+
return [totalKeys, Object.keys(totalKeysPerDb).length > 1 ? totalKeysPerDb : undefined];
214233
} catch (e) {
215-
return null;
234+
return [null, null];
216235
}
217236
}
218237

redisinsight/api/test/api/instance/GET-instance-id-overview.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const endpoint = (instanceId = constants.TEST_INSTANCE_ID) =>
88
const responseSchema = Joi.object().keys({
99
version: Joi.string().required(),
1010
totalKeys: Joi.number().integer().allow(null),
11+
totalKeysPerDb: Joi.object().allow(null),
1112
usedMemory: Joi.number().integer().allow(null),
1213
connectedClients: Joi.number().allow(null),
1314
opsPerSecond: Joi.number().allow(null),
@@ -68,6 +69,7 @@ describe('GET /instance/:instanceId/overview', () => {
6869
expect(body.version).to.eql(rte.env.version);
6970
expect(body.cpuUsagePercentage).to.eql(undefined)
7071
expect(body.totalKeys).to.not.eql(undefined)
72+
expect(body.totalKeysPerDb).to.eql(undefined)
7173
expect(body.connectedClients).to.not.eql(undefined)
7274
expect(body.opsPerSecond).to.not.eql(undefined)
7375
expect(body.networkInKbps).to.not.eql(undefined)

0 commit comments

Comments
 (0)