Skip to content

Commit 3eff0f9

Browse files
author
marc
committed
UI: show encryption stats on stores report.
requires cockroachdb#26802 for new `StoresResponse` fields. This adds basic file stats to the stores report page. Also improves the styling: - show decoded key info protobuf fields rather than raw proto (eg: creation date rather than unix timestamp) - table styling moved to core style file - full-width cells to head different sections Release note (admin ui change): add encryption statistics on stores report page
1 parent 492cbd3 commit 3eff0f9

File tree

5 files changed

+125
-22
lines changed

5 files changed

+125
-22
lines changed
Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,121 @@
11
import React from "react";
22

33
import * as protos from "src/js/protos";
4+
import _ from "lodash";
5+
import Long from "long";
6+
import moment from "moment";
47
import { EncryptionStatusProps } from "oss/src/views/reports/containers/stores/encryption";
8+
import { Bytes } from "src/util/format";
9+
import { FixLong } from "src/util/fixLong";
10+
11+
const dateFormat = "Y-MM-DD HH:mm:ss";
512

613
export default class EncryptionStatus extends React.Component<EncryptionStatusProps, {}> {
714

15+
renderHeaderRow(header: string) {
16+
return (
17+
<tr className="stores-table__row">
18+
<td colSpan={2} className="stores-table__cell stores-table__cell--header--row">{header}</td>
19+
</tr>
20+
);
21+
}
22+
823
renderSimpleRow(header: string, value: string) {
924
return (
1025
<tr className="stores-table__row">
1126
<th className="stores-table__cell stores-table__cell--header">{header}</th>
12-
<td className="stores-table__cell" title={value}><pre>{value}</pre></td>
27+
<td className="stores-table__cell" title={value}>{value}</td>
1328
</tr>
1429
);
1530
}
1631

17-
render(): React.ReactElement<any> {
18-
const { store } = this.props;
19-
const rawStatus = store.encryption_status;
32+
renderStoreKey(key: protos.cockroach.ccl.storageccl.engineccl.enginepbccl.IKeyInfo) {
33+
// Get the enum name from its value (eg: "AES128_CTR" for 1).
34+
const encryptionType = protos.cockroach.ccl.storageccl.engineccl.enginepbccl.EncryptionType[key.encryption_type];
35+
const createdAt = moment.unix(FixLong(key.creation_time).toNumber()).utc().format(dateFormat);
36+
37+
return [
38+
this.renderHeaderRow("Active Store Key: user specified"),
39+
this.renderSimpleRow("Algorithm", encryptionType),
40+
this.renderSimpleRow("Key ID", key.key_id),
41+
this.renderSimpleRow("Created", createdAt),
42+
this.renderSimpleRow("Source", key.source),
43+
];
44+
}
45+
46+
renderDataKey(key: protos.cockroach.ccl.storageccl.engineccl.enginepbccl.IKeyInfo) {
47+
// Get the enum name from its value (eg: "AES128_CTR" for 1).
48+
const encryptionType = protos.cockroach.ccl.storageccl.engineccl.enginepbccl.EncryptionType[key.encryption_type];
49+
const createdAt = moment.unix(key.creation_time.toNumber()).utc().format(dateFormat);
50+
51+
return [
52+
this.renderHeaderRow("Active Data Key: automatically generated"),
53+
this.renderSimpleRow("Algorithm", encryptionType),
54+
this.renderSimpleRow("Key ID", key.key_id),
55+
this.renderSimpleRow("Created", createdAt),
56+
this.renderSimpleRow("Parent Key ID", key.parent_key_id),
57+
];
58+
}
59+
60+
calculatePercentage(active: Long, total: Long): number {
61+
if (active === total) {
62+
return 100;
63+
}
64+
return Long.fromInt(100).mul(active).toNumber() / total.toNumber();
65+
}
66+
67+
renderFileStats(stats: protos.cockroach.server.serverpb.IStoreDetails) {
68+
const totalFiles = FixLong(stats.total_files);
69+
const totalBytes = FixLong(stats.total_bytes);
70+
if (totalFiles.eq(0) && totalBytes.eq(0)) {
71+
return null;
72+
}
73+
74+
const activeFiles = FixLong(stats.active_key_files);
75+
const activeBytes = FixLong(stats.active_key_bytes);
76+
77+
let fileDetails = this.calculatePercentage(activeFiles, totalFiles).toFixed(2) + "%";
78+
fileDetails += " (" + activeFiles + "/" + totalFiles + ")";
79+
80+
let byteDetails = this.calculatePercentage(activeBytes, totalBytes).toFixed(2) + "%";
81+
byteDetails += " (" + Bytes(activeBytes.toNumber()) + "/" + Bytes(totalBytes.toNumber()) + ")";
2082

83+
return [
84+
this.renderHeaderRow("Encryption Progress: fraction encrypted using the active data key"),
85+
this.renderSimpleRow("Files", fileDetails),
86+
this.renderSimpleRow("Bytes", byteDetails),
87+
];
88+
}
89+
90+
decodeEncryptionStatus(data: Uint8Array): protos.cockroach.ccl.storageccl.engineccl.enginepbccl.EncryptionStatus {
91+
let decodedStatus;
92+
93+
// Attempt to decode protobuf.
2194
try {
22-
const decodedStatus = protos.cockroach.ccl.storageccl.engineccl.enginepbccl.EncryptionStatus.decode(rawStatus);
23-
return this.renderSimpleRow("Encryption Status", JSON.stringify(decodedStatus.toJSON(), null, 2));
95+
decodedStatus = protos.cockroach.ccl.storageccl.engineccl.enginepbccl.EncryptionStatus.decode(data);
2496
} catch (e) {
2597
console.log("Error decoding protobuf: ", e);
2698
return null;
2799
}
100+
return decodedStatus;
101+
}
102+
103+
getEncryptionRows() {
104+
const { store } = this.props;
105+
const rawStatus = store.encryption_status;
106+
if (_.isEmpty(rawStatus)) {
107+
return null;
108+
}
109+
110+
const decodedStatus = this.decodeEncryptionStatus(rawStatus);
111+
if (decodedStatus == null) {
112+
return null;
113+
}
114+
115+
return [
116+
this.renderStoreKey(decodedStatus.active_store_key),
117+
this.renderDataKey(decodedStatus.active_data_key),
118+
this.renderFileStats(store),
119+
];
28120
}
29121
}

pkg/ui/src/views/reports/containers/stores/encryption.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface EncryptionStatusProps {
88

99
export default class EncryptionStatus extends React.Component<EncryptionStatusProps, {}> {
1010

11-
render(): React.ReactElement<any> {
11+
getEncryptionRows(): React.ReactElement<any> {
1212
return null;
1313
}
1414
}

pkg/ui/src/views/reports/containers/stores/index.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import { AdminUIState } from "src/redux/state";
1010
import { nodeIDAttr } from "src/util/constants";
1111
import EncryptionStatus from "src/views/reports/containers/stores/encryption";
1212

13-
import "./stores.styl";
14-
1513
interface StoresOwnProps {
1614
stores: protos.cockroach.server.serverpb.StoresResponse;
1715
lastError: Error;
@@ -58,12 +56,12 @@ class Stores extends React.Component<StoresProps, {}> {
5856
);
5957
}
6058

61-
renderStore(store: protos.cockroach.server.serverpb.IStoreDetails, key: number) {
59+
renderStore(store: protos.cockroach.server.serverpb.IStoreDetails) {
6260
return (
63-
<table key={key} className="stores-table">
61+
<table key={store.store_id} className="stores-table">
6462
<tbody>
6563
{ this.renderSimpleRow("Store ID", store.store_id.toString()) }
66-
<EncryptionStatus store={store} />
64+
{ new EncryptionStatus({store: store}).getEncryptionRows() }
6765
</tbody>
6866
</table>
6967
);
@@ -122,8 +120,8 @@ class Stores extends React.Component<StoresProps, {}> {
122120
<h1>Stores</h1>
123121
<h2>{header} stores</h2>
124122
{
125-
_.map(stores.stores, (store, key) => (
126-
this.renderStore(store, key)
123+
_.map(_.sortBy(stores.stores, (store) => store.store_id), (store) => (
124+
this.renderStore(store)
127125
))
128126
}
129127
</div>

pkg/ui/src/views/reports/containers/stores/stores.styl

Lines changed: 0 additions & 8 deletions
This file was deleted.

pkg/ui/styl/pages/reports.styl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,27 @@ $reports-table
139139
margin 0
140140
padding 0
141141

142+
.stores-table
143+
@extend $reports-table
144+
145+
&__cell
146+
background-color white
147+
padding 6px 12px
148+
max-width none
149+
width 100%
150+
151+
&--header
152+
background-color $link-color
153+
text-align right
154+
width 150px
155+
min-width 150px
156+
157+
&--row
158+
background-color $link-color
159+
text-align center
160+
color white
161+
font-weight 900
162+
142163
.connections-table
143164
@extend $reports-table
144165
font-size 12px

0 commit comments

Comments
 (0)