You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by vo...@apache.org on 2023/03/06 19:52:39 UTC
[druid] branch master updated: Web console: Compaction history dialog (#13861)
This is an automated email from the ASF dual-hosted git repository.
vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 38b6373bf7 Web console: Compaction history dialog (#13861)
38b6373bf7 is described below
commit 38b6373bf78165c1ed95198d2e0cffecfc6eb06f
Author: Vadim Ogievetsky <va...@ogievetsky.com>
AuthorDate: Mon Mar 6 11:52:25 2023 -0800
Web console: Compaction history dialog (#13861)
* initial renames
* add comaction history diff
* final fixes
* update snapshots
* use maps
* update test
---
licenses.yaml | 2 +-
.../e2e-tests/component/datasources/overview.ts | 2 +-
web-console/package-lock.json | 14 +-
web-console/package.json | 2 +-
web-console/script/licenses | 6 +-
web-console/src/components/index.ts | 1 +
.../__snapshots__/show-value.spec.tsx.snap | 2 +-
.../src/components/show-value/show-value.tsx | 2 +-
.../supervisor-history-panel.spec.tsx.snap} | 2 +-
.../supervisor-history-panel.scss} | 2 +-
.../supervisor-history-panel.spec.tsx} | 6 +-
.../supervisor-history-panel.tsx} | 37 +++---
.../compaction-config-dialog.spec.tsx.snap} | 40 ++++--
.../compaction-config-dialog.scss} | 13 +-
.../compaction-config-dialog.spec.tsx} | 12 +-
.../compaction-config-dialog.tsx} | 24 +++-
.../compaction-history-dialog.scss} | 22 +++-
.../compaction-history-dialog.tsx | 145 +++++++++++++++++++++
.../__snapshots__/history-dialog.spec.tsx.snap | 2 +-
web-console/src/dialogs/index.ts | 2 +-
.../supervisor-table-action-dialog.tsx | 10 +-
web-console/src/utils/sampler.ts | 13 +-
.../views/datasources-view/datasources-view.tsx | 12 +-
23 files changed, 285 insertions(+), 88 deletions(-)
diff --git a/licenses.yaml b/licenses.yaml
index 7d68a4d8f5..6c9e4a6e49 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -5693,7 +5693,7 @@ license_category: binary
module: web-console
license_name: Apache License version 2.0
copyright: Imply Data
-version: 0.17.4
+version: 0.17.5
---
diff --git a/web-console/e2e-tests/component/datasources/overview.ts b/web-console/e2e-tests/component/datasources/overview.ts
index 95d6d630c9..9a6db40fcd 100644
--- a/web-console/e2e-tests/component/datasources/overview.ts
+++ b/web-console/e2e-tests/component/datasources/overview.ts
@@ -99,7 +99,7 @@ export class DatasourcesOverview {
private async openCompactionConfigurationDialog(datasourceName: string): Promise<void> {
await this.openEditActions(datasourceName);
await this.clickMenuItem('Edit compaction configuration');
- await this.page.waitForSelector('div.compaction-dialog');
+ await this.page.waitForSelector('div.compaction-config-dialog');
}
private async clickMenuItem(text: string): Promise<void> {
diff --git a/web-console/package-lock.json b/web-console/package-lock.json
index 8e9f115fd8..0285118311 100644
--- a/web-console/package-lock.json
+++ b/web-console/package-lock.json
@@ -22,7 +22,7 @@
"d3-axis": "^2.1.0",
"d3-scale": "^3.3.0",
"d3-selection": "^2.0.0",
- "druid-query-toolkit": "^0.17.4",
+ "druid-query-toolkit": "^0.17.5",
"file-saver": "^2.0.2",
"follow-redirects": "^1.14.7",
"fontsource-open-sans": "^3.0.9",
@@ -8542,9 +8542,9 @@
}
},
"node_modules/druid-query-toolkit": {
- "version": "0.17.4",
- "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.17.4.tgz",
- "integrity": "sha512-d/mNJ9ausAfxQaxgGWfP4dHpwcIqjkbdz1NNmTk6DHMbwlskk96MnXrvPsOCmeoKMb0iYVeVtq9CbB1vNaPZ5A==",
+ "version": "0.17.5",
+ "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.17.5.tgz",
+ "integrity": "sha512-N+kqu6xy2Gd3zQwNbBxQXG+qjU7jzbCXvE84uxsIh5gxRbiKAEOsyWtKrWF/DZZ91g/WSIMQih5klkmmcjlVfQ==",
"dependencies": {
"tslib": "^2.3.1"
},
@@ -33236,9 +33236,9 @@
}
},
"druid-query-toolkit": {
- "version": "0.17.4",
- "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.17.4.tgz",
- "integrity": "sha512-d/mNJ9ausAfxQaxgGWfP4dHpwcIqjkbdz1NNmTk6DHMbwlskk96MnXrvPsOCmeoKMb0iYVeVtq9CbB1vNaPZ5A==",
+ "version": "0.17.5",
+ "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.17.5.tgz",
+ "integrity": "sha512-N+kqu6xy2Gd3zQwNbBxQXG+qjU7jzbCXvE84uxsIh5gxRbiKAEOsyWtKrWF/DZZ91g/WSIMQih5klkmmcjlVfQ==",
"requires": {
"tslib": "^2.3.1"
}
diff --git a/web-console/package.json b/web-console/package.json
index 12bb391cf0..fde4d2a57a 100644
--- a/web-console/package.json
+++ b/web-console/package.json
@@ -79,7 +79,7 @@
"d3-axis": "^2.1.0",
"d3-scale": "^3.3.0",
"d3-selection": "^2.0.0",
- "druid-query-toolkit": "^0.17.4",
+ "druid-query-toolkit": "^0.17.5",
"file-saver": "^2.0.2",
"follow-redirects": "^1.14.7",
"fontsource-open-sans": "^3.0.9",
diff --git a/web-console/script/licenses b/web-console/script/licenses
index 46df1fdb48..35aa2f5b58 100755
--- a/web-console/script/licenses
+++ b/web-console/script/licenses
@@ -90,7 +90,7 @@ checker.init(
Object.assign(packages, extraPackages);
- const seen = {};
+ const seen = new Map();
const mapped = Object.keys(packages)
.sort()
.map(p => {
@@ -98,8 +98,8 @@ checker.init(
if (!m) throw new Error(`Malformed name@version`);
const name = m[1];
if (name === 'web-console') return; // This is me!
- if (seen[name]) return; // Dedupe
- seen[name] = true;
+ if (seen.has(name)) return; // Dedupe
+ seen.set(name, true);
const version = m[2];
const meta = packages[p];
diff --git a/web-console/src/components/index.ts b/web-console/src/components/index.ts
index 56da967599..a84dc063f8 100644
--- a/web-console/src/components/index.ts
+++ b/web-console/src/components/index.ts
@@ -51,6 +51,7 @@ export * from './show-json/show-json';
export * from './show-log/show-log';
export * from './show-value/show-value';
export * from './suggestion-menu/suggestion-menu';
+export * from './supervisor-history-panel/supervisor-history-panel';
export * from './table-cell/table-cell';
export * from './table-cell-unparseable/table-cell-unparseable';
export * from './table-clickable-cell/table-clickable-cell';
diff --git a/web-console/src/components/show-value/__snapshots__/show-value.spec.tsx.snap b/web-console/src/components/show-value/__snapshots__/show-value.spec.tsx.snap
index a2bae8643c..c01065774a 100644
--- a/web-console/src/components/show-value/__snapshots__/show-value.spec.tsx.snap
+++ b/web-console/src/components/show-value/__snapshots__/show-value.spec.tsx.snap
@@ -2,7 +2,7 @@
exports[`ShowValue matches snapshot 1`] = `
<div
- class="show-json"
+ class="show-value"
>
<div
class="top-actions"
diff --git a/web-console/src/components/show-value/show-value.tsx b/web-console/src/components/show-value/show-value.tsx
index d04219d869..14c76c9277 100644
--- a/web-console/src/components/show-value/show-value.tsx
+++ b/web-console/src/components/show-value/show-value.tsx
@@ -32,7 +32,7 @@ export interface ShowValueProps {
export const ShowValue = React.memo(function ShowValue(props: ShowValueProps) {
const { jsonValue, onDiffWithPrevious, downloadFilename } = props;
return (
- <div className="show-json">
+ <div className="show-value">
{(onDiffWithPrevious || downloadFilename) && (
<div className="top-actions">
<ButtonGroup className="right-buttons">
diff --git a/web-console/src/components/show-history/__snapshots__/show-history.spec.tsx.snap b/web-console/src/components/supervisor-history-panel/__snapshots__/supervisor-history-panel.spec.tsx.snap
similarity index 95%
rename from web-console/src/components/show-history/__snapshots__/show-history.spec.tsx.snap
rename to web-console/src/components/supervisor-history-panel/__snapshots__/supervisor-history-panel.spec.tsx.snap
index dc505ddbd3..6fc2308a29 100644
--- a/web-console/src/components/show-history/__snapshots__/show-history.spec.tsx.snap
+++ b/web-console/src/components/supervisor-history-panel/__snapshots__/supervisor-history-panel.spec.tsx.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`ShowHistory matches snapshot 1`] = `
+exports[`SupervisorHistoryPanel matches snapshot 1`] = `
<div
class="loader"
>
diff --git a/web-console/src/components/show-history/show-history.scss b/web-console/src/components/supervisor-history-panel/supervisor-history-panel.scss
similarity index 97%
copy from web-console/src/components/show-history/show-history.scss
copy to web-console/src/components/supervisor-history-panel/supervisor-history-panel.scss
index e062642464..2d35ad870a 100644
--- a/web-console/src/components/show-history/show-history.scss
+++ b/web-console/src/components/supervisor-history-panel/supervisor-history-panel.scss
@@ -18,7 +18,7 @@
@import '../../variables';
-.show-history {
+.supervisor-history-panel {
position: relative;
height: 100%;
diff --git a/web-console/src/components/show-history/show-history.spec.tsx b/web-console/src/components/supervisor-history-panel/supervisor-history-panel.spec.tsx
similarity index 84%
rename from web-console/src/components/show-history/show-history.spec.tsx
rename to web-console/src/components/supervisor-history-panel/supervisor-history-panel.spec.tsx
index 678fd22e91..e8414feb9a 100644
--- a/web-console/src/components/show-history/show-history.spec.tsx
+++ b/web-console/src/components/supervisor-history-panel/supervisor-history-panel.spec.tsx
@@ -19,11 +19,11 @@
import { render } from '@testing-library/react';
import React from 'react';
-import { ShowHistory } from './show-history';
+import { SupervisorHistoryPanel } from './supervisor-history-panel';
-describe('ShowHistory', () => {
+describe('SupervisorHistoryPanel', () => {
it('matches snapshot', () => {
- const showJson = <ShowHistory endpoint="test" downloadFilenamePrefix="test" />;
+ const showJson = <SupervisorHistoryPanel supervisorId="test" />;
const { container } = render(showJson);
expect(container.firstChild).toMatchSnapshot();
});
diff --git a/web-console/src/components/show-history/show-history.tsx b/web-console/src/components/supervisor-history-panel/supervisor-history-panel.tsx
similarity index 74%
rename from web-console/src/components/show-history/show-history.tsx
rename to web-console/src/components/supervisor-history-panel/supervisor-history-panel.tsx
index 72ae421d33..e3fd38b916 100644
--- a/web-console/src/components/show-history/show-history.tsx
+++ b/web-console/src/components/supervisor-history-panel/supervisor-history-panel.tsx
@@ -29,29 +29,34 @@ import { deepSet } from '../../utils';
import { Loader } from '../loader/loader';
import { ShowValue } from '../show-value/show-value';
-import './show-history.scss';
+import './supervisor-history-panel.scss';
-export interface VersionSpec {
+export interface SupervisorHistoryEntry {
version: string;
spec: IngestionSpec;
}
-export interface ShowHistoryProps {
- endpoint: string;
- downloadFilenamePrefix?: string;
+export interface SupervisorHistoryPanelProps {
+ supervisorId: string;
}
-export const ShowHistory = React.memo(function ShowHistory(props: ShowHistoryProps) {
- const { downloadFilenamePrefix, endpoint } = props;
+export const SupervisorHistoryPanel = React.memo(function SupervisorHistoryPanel(
+ props: SupervisorHistoryPanelProps,
+) {
+ const { supervisorId } = props;
- const [historyState] = useQueryManager<string, VersionSpec[]>({
- processQuery: async (endpoint: string) => {
- const resp = await Api.instance.get(endpoint);
- return resp.data.map((vs: VersionSpec) => deepSet(vs, 'spec', cleanSpec(vs.spec, true)));
+ const [diffIndex, setDiffIndex] = useState(-1);
+ const [historyState] = useQueryManager<string, SupervisorHistoryEntry[]>({
+ initQuery: supervisorId,
+ processQuery: async supervisorId => {
+ const resp = await Api.instance.get(
+ `/druid/indexer/v1/supervisor/${Api.encodePath(supervisorId)}/history`,
+ );
+ return resp.data.map((vs: SupervisorHistoryEntry) =>
+ deepSet(vs, 'spec', cleanSpec(vs.spec, true)),
+ );
},
- initQuery: endpoint,
});
- const [diffIndex, setDiffIndex] = useState(-1);
if (historyState.loading) return <Loader />;
@@ -59,21 +64,21 @@ export const ShowHistory = React.memo(function ShowHistory(props: ShowHistoryPro
if (!historyData) return null;
return (
- <div className="show-history">
+ <div className="supervisor-history-panel">
<Tabs animate renderActiveTabPanelOnly vertical defaultSelectedTabId={0}>
{historyData.map((pastSupervisor, i) => (
<Tab
id={i}
key={i}
title={pastSupervisor.version}
+ panelClassName="panel"
panel={
<ShowValue
jsonValue={JSONBig.stringify(pastSupervisor.spec, undefined, 2)}
onDiffWithPrevious={i < historyData.length - 1 ? () => setDiffIndex(i) : undefined}
- downloadFilename={`${downloadFilenamePrefix}-version-${pastSupervisor.version}.json`}
+ downloadFilename={`supervisor-${supervisorId}-version-${pastSupervisor.version}.json`}
/>
}
- panelClassName="panel"
/>
))}
<Tabs.Expander />
diff --git a/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap b/web-console/src/dialogs/compaction-config-dialog/__snapshots__/compaction-config-dialog.spec.tsx.snap
similarity index 97%
rename from web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
rename to web-console/src/dialogs/compaction-config-dialog/__snapshots__/compaction-config-dialog.spec.tsx.snap
index c632071fe5..0d7c477442 100644
--- a/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/compaction-config-dialog/__snapshots__/compaction-config-dialog.spec.tsx.snap
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`CompactionDialog matches snapshot with compactionConfig (dynamic partitionsSpec) 1`] = `
+exports[`CompactionConfigDialog matches snapshot with compactionConfig (dynamic partitionsSpec) 1`] = `
<Blueprint4.Dialog
canOutsideClickClose={false}
- className="compaction-dialog"
+ className="compaction-config-dialog"
isOpen={true}
onClose={[Function]}
title="Compaction config: test1"
@@ -356,6 +356,12 @@ exports[`CompactionDialog matches snapshot with compactionConfig (dynamic partit
<div
className="bp4-dialog-footer-actions"
>
+ <Blueprint4.Button
+ className="history-button"
+ minimal={true}
+ onClick={[Function]}
+ text="History"
+ />
<Blueprint4.Button
intent="danger"
onClick={[Function]}
@@ -376,10 +382,10 @@ exports[`CompactionDialog matches snapshot with compactionConfig (dynamic partit
</Blueprint4.Dialog>
`;
-exports[`CompactionDialog matches snapshot with compactionConfig (hashed partitionsSpec) 1`] = `
+exports[`CompactionConfigDialog matches snapshot with compactionConfig (hashed partitionsSpec) 1`] = `
<Blueprint4.Dialog
canOutsideClickClose={false}
- className="compaction-dialog"
+ className="compaction-config-dialog"
isOpen={true}
onClose={[Function]}
title="Compaction config: test1"
@@ -732,6 +738,12 @@ exports[`CompactionDialog matches snapshot with compactionConfig (hashed partiti
<div
className="bp4-dialog-footer-actions"
>
+ <Blueprint4.Button
+ className="history-button"
+ minimal={true}
+ onClick={[Function]}
+ text="History"
+ />
<Blueprint4.Button
intent="danger"
onClick={[Function]}
@@ -752,10 +764,10 @@ exports[`CompactionDialog matches snapshot with compactionConfig (hashed partiti
</Blueprint4.Dialog>
`;
-exports[`CompactionDialog matches snapshot with compactionConfig (range partitionsSpec) 1`] = `
+exports[`CompactionConfigDialog matches snapshot with compactionConfig (range partitionsSpec) 1`] = `
<Blueprint4.Dialog
canOutsideClickClose={false}
- className="compaction-dialog"
+ className="compaction-config-dialog"
isOpen={true}
onClose={[Function]}
title="Compaction config: test1"
@@ -1108,6 +1120,12 @@ exports[`CompactionDialog matches snapshot with compactionConfig (range partitio
<div
className="bp4-dialog-footer-actions"
>
+ <Blueprint4.Button
+ className="history-button"
+ minimal={true}
+ onClick={[Function]}
+ text="History"
+ />
<Blueprint4.Button
intent="danger"
onClick={[Function]}
@@ -1128,10 +1146,10 @@ exports[`CompactionDialog matches snapshot with compactionConfig (range partitio
</Blueprint4.Dialog>
`;
-exports[`CompactionDialog matches snapshot without compactionConfig 1`] = `
+exports[`CompactionConfigDialog matches snapshot without compactionConfig 1`] = `
<Blueprint4.Dialog
canOutsideClickClose={false}
- className="compaction-dialog"
+ className="compaction-config-dialog"
isOpen={true}
onClose={[Function]}
title="Compaction config: test1"
@@ -1484,6 +1502,12 @@ exports[`CompactionDialog matches snapshot without compactionConfig 1`] = `
<div
className="bp4-dialog-footer-actions"
>
+ <Blueprint4.Button
+ className="history-button"
+ minimal={true}
+ onClick={[Function]}
+ text="History"
+ />
<Blueprint4.Button
onClick={[Function]}
text="Close"
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss b/web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.scss
similarity index 84%
rename from web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
rename to web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.scss
index 499df985c9..bdb6c04b42 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
+++ b/web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.scss
@@ -18,7 +18,7 @@
@import '../../variables';
-.compaction-dialog {
+.compaction-config-dialog {
&.#{$bp-ns}-dialog {
height: 80vh;
}
@@ -32,6 +32,17 @@
margin: 15px;
}
+ .#{$bp-ns}-dialog-footer-actions {
+ position: relative;
+
+ .history-button {
+ position: absolute;
+ top: 0;
+ left: 0;
+ margin: 0;
+ }
+ }
+
.content {
margin: 0 15px 10px 0;
padding: 0 5px 0 15px;
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx b/web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.spec.tsx
similarity index 91%
rename from web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
rename to web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.spec.tsx
index 20b4b01470..84d1566225 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
+++ b/web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.spec.tsx
@@ -20,12 +20,12 @@ import React from 'react';
import { shallow } from '../../utils/shallow-renderer';
-import { CompactionDialog } from './compaction-dialog';
+import { CompactionConfigDialog } from './compaction-config-dialog';
-describe('CompactionDialog', () => {
+describe('CompactionConfigDialog', () => {
it('matches snapshot without compactionConfig', () => {
const compactionDialog = shallow(
- <CompactionDialog
+ <CompactionConfigDialog
onClose={() => {}}
onSave={() => {}}
onDelete={() => {}}
@@ -38,7 +38,7 @@ describe('CompactionDialog', () => {
it('matches snapshot with compactionConfig (dynamic partitionsSpec)', () => {
const compactionDialog = shallow(
- <CompactionDialog
+ <CompactionConfigDialog
onClose={() => {}}
onSave={() => {}}
onDelete={() => {}}
@@ -54,7 +54,7 @@ describe('CompactionDialog', () => {
it('matches snapshot with compactionConfig (hashed partitionsSpec)', () => {
const compactionDialog = shallow(
- <CompactionDialog
+ <CompactionConfigDialog
onClose={() => {}}
onSave={() => {}}
onDelete={() => {}}
@@ -70,7 +70,7 @@ describe('CompactionDialog', () => {
it('matches snapshot with compactionConfig (range partitionsSpec)', () => {
const compactionDialog = shallow(
- <CompactionDialog
+ <CompactionConfigDialog
onClose={() => {}}
onSave={() => {}}
onDelete={() => {}}
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx b/web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.tsx
similarity index 85%
rename from web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
rename to web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.tsx
index f11132860c..7c70d22571 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
+++ b/web-console/src/dialogs/compaction-config-dialog/compaction-config-dialog.tsx
@@ -27,10 +27,11 @@ import {
compactionConfigHasLegacyInputSegmentSizeBytesSet,
} from '../../druid-models';
import { deepDelete, formatBytesCompact } from '../../utils';
+import { CompactionHistoryDialog } from '../compaction-history-dialog/compaction-history-dialog';
-import './compaction-dialog.scss';
+import './compaction-config-dialog.scss';
-export interface CompactionDialogProps {
+export interface CompactionConfigDialogProps {
onClose: () => void;
onSave: (compactionConfig: CompactionConfig) => void | Promise<void>;
onDelete: () => void;
@@ -38,9 +39,12 @@ export interface CompactionDialogProps {
compactionConfig: CompactionConfig | undefined;
}
-export const CompactionDialog = React.memo(function CompactionDialog(props: CompactionDialogProps) {
+export const CompactionConfigDialog = React.memo(function CompactionConfigDialog(
+ props: CompactionConfigDialogProps,
+) {
const { datasource, compactionConfig, onSave, onClose, onDelete } = props;
+ const [showHistory, setShowHistory] = useState(false);
const [currentTab, setCurrentTab] = useState<FormJsonTabs>('form');
const [currentConfig, setCurrentConfig] = useState<CompactionConfig>(
compactionConfig || {
@@ -53,9 +57,15 @@ export const CompactionDialog = React.memo(function CompactionDialog(props: Comp
const issueWithCurrentConfig = AutoForm.issueWithModel(currentConfig, COMPACTION_CONFIG_FIELDS);
const disableSubmit = Boolean(jsonError || issueWithCurrentConfig);
+ if (showHistory) {
+ return (
+ <CompactionHistoryDialog datasource={datasource} onClose={() => setShowHistory(false)} />
+ );
+ }
+
return (
<Dialog
- className="compaction-dialog"
+ className="compaction-config-dialog"
isOpen
onClose={onClose}
canOutsideClickClose={false}
@@ -100,6 +110,12 @@ export const CompactionDialog = React.memo(function CompactionDialog(props: Comp
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
+ <Button
+ className="history-button"
+ text="History"
+ minimal
+ onClick={() => setShowHistory(true)}
+ />
{compactionConfig && <Button text="Delete" intent={Intent.DANGER} onClick={onDelete} />}
<Button text="Close" onClick={onClose} />
<Button
diff --git a/web-console/src/components/show-history/show-history.scss b/web-console/src/dialogs/compaction-history-dialog/compaction-history-dialog.scss
similarity index 76%
rename from web-console/src/components/show-history/show-history.scss
rename to web-console/src/dialogs/compaction-history-dialog/compaction-history-dialog.scss
index e062642464..620e7f6ff2 100644
--- a/web-console/src/components/show-history/show-history.scss
+++ b/web-console/src/dialogs/compaction-history-dialog/compaction-history-dialog.scss
@@ -18,9 +18,11 @@
@import '../../variables';
-.show-history {
- position: relative;
- height: 100%;
+.compaction-history-dialog {
+ &.#{$bp-ns}-dialog {
+ width: 70vw;
+ height: 80vh;
+ }
.#{$bp-ns}-tabs {
position: relative;
@@ -30,9 +32,19 @@
.panel {
position: relative;
width: 100%;
+
+ .global-info {
+ position: absolute;
+ bottom: 10px;
+ left: 30px;
+ right: 10px;
+ width: auto;
+ white-space: pre;
+ background: $gray1;
+ }
}
- .#{$bp-ns}-tab-list {
- overflow-y: auto;
+ .loader {
+ position: relative;
}
}
diff --git a/web-console/src/dialogs/compaction-history-dialog/compaction-history-dialog.tsx b/web-console/src/dialogs/compaction-history-dialog/compaction-history-dialog.tsx
new file mode 100644
index 0000000000..4cdc916ee7
--- /dev/null
+++ b/web-console/src/dialogs/compaction-history-dialog/compaction-history-dialog.tsx
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Button, Callout, Classes, Code, Dialog, Tab, Tabs } from '@blueprintjs/core';
+import * as JSONBig from 'json-bigint-native';
+import React, { useState } from 'react';
+
+import { Loader, ShowValue } from '../../components';
+import type { CompactionConfig } from '../../druid-models';
+import { useQueryManager } from '../../hooks';
+import { Api } from '../../singletons';
+import { formatInteger, formatPercent } from '../../utils';
+import { DiffDialog } from '../diff-dialog/diff-dialog';
+
+import './compaction-history-dialog.scss';
+
+interface CompactionHistoryEntry {
+ auditTime: string;
+ auditInfo: any;
+ globalConfig?: GlobalConfig;
+ compactionConfig: CompactionConfig;
+}
+
+interface GlobalConfig {
+ compactionTaskSlotRatio: number;
+ maxCompactionTaskSlots: number;
+ useAutoScaleSlots: boolean;
+}
+
+function formatGlobalConfig(globalConfig: GlobalConfig): string {
+ return [
+ `compactionTaskSlotRatio: ${formatPercent(globalConfig.compactionTaskSlotRatio)}`,
+ `maxCompactionTaskSlots: ${formatInteger(globalConfig.maxCompactionTaskSlots)}`,
+ `useAutoScaleSlots: ${globalConfig.useAutoScaleSlots}`,
+ ].join('\n');
+}
+
+export interface CompactionHistoryDialogProps {
+ datasource: string;
+ onClose(): void;
+}
+
+export const CompactionHistoryDialog = React.memo(function CompactionHistoryDialog(
+ props: CompactionHistoryDialogProps,
+) {
+ const { datasource, onClose } = props;
+
+ const [diffIndex, setDiffIndex] = useState(-1);
+ const [historyState] = useQueryManager<string, CompactionHistoryEntry[]>({
+ initQuery: datasource,
+ processQuery: async datasource => {
+ try {
+ const resp = await Api.instance.get(
+ `/druid/coordinator/v1/config/compaction/${Api.encodePath(datasource)}/history?count=20`,
+ );
+ return resp.data;
+ } catch (e) {
+ if (e.response?.status === 404) return [];
+ throw e;
+ }
+ },
+ });
+
+ const historyData = historyState.data;
+ return (
+ <Dialog
+ className="compaction-history-dialog"
+ isOpen
+ onClose={onClose}
+ canOutsideClickClose={false}
+ title={`Compaction history: ${datasource}`}
+ >
+ <div className={Classes.DIALOG_BODY}>
+ {historyData ? (
+ historyData.length ? (
+ <Tabs animate renderActiveTabPanelOnly vertical defaultSelectedTabId={0}>
+ {historyData.map((historyEntry, i) => (
+ <Tab
+ id={i}
+ key={i}
+ title={historyEntry.auditTime}
+ panelClassName="panel"
+ panel={
+ <>
+ <ShowValue
+ jsonValue={JSONBig.stringify(historyEntry.compactionConfig, undefined, 2)}
+ onDiffWithPrevious={
+ i < historyData.length - 1 ? () => setDiffIndex(i) : undefined
+ }
+ downloadFilename={`compaction-history-${datasource}-version-${historyEntry.auditTime}.json`}
+ />
+ {historyEntry.globalConfig && (
+ <Callout className="global-info">
+ {formatGlobalConfig(historyEntry.globalConfig)}
+ </Callout>
+ )}
+ </>
+ }
+ />
+ ))}
+ <Tabs.Expander />
+ </Tabs>
+ ) : (
+ <div>
+ There is no compaction history for <Code>{datasource}</Code>.
+ </div>
+ )
+ ) : historyState.loading ? (
+ <Loader />
+ ) : (
+ <div>{historyState.getErrorMessage()}</div>
+ )}
+ </div>
+ <div className={Classes.DIALOG_FOOTER}>
+ <div className={Classes.DIALOG_FOOTER_ACTIONS}>
+ <Button text="Close" onClick={onClose} />
+ </div>
+ </div>
+ {diffIndex !== -1 && historyData && (
+ <DiffDialog
+ title="Compaction config diff"
+ versions={historyData.map(s => ({ label: s.auditTime, value: s.compactionConfig }))}
+ initLeftIndex={diffIndex + 1}
+ initRightIndex={diffIndex}
+ onClose={() => setDiffIndex(-1)}
+ />
+ )}
+ </Dialog>
+ );
+});
diff --git a/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap b/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
index 6ee82f354b..03cc0ac3ad 100644
--- a/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
@@ -112,7 +112,7 @@ exports[`HistoryDialog matches snapshot 1`] = `
role="tabpanel"
>
<div
- class="show-json"
+ class="show-value"
>
<div
class="top-actions"
diff --git a/web-console/src/dialogs/index.ts b/web-console/src/dialogs/index.ts
index 588257c84e..1f7d9b30ea 100644
--- a/web-console/src/dialogs/index.ts
+++ b/web-console/src/dialogs/index.ts
@@ -18,7 +18,7 @@
export * from './about-dialog/about-dialog';
export * from './async-action-dialog/async-action-dialog';
-export * from './compaction-dialog/compaction-dialog';
+export * from './compaction-config-dialog/compaction-config-dialog';
export * from './coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog';
export * from './diff-dialog/diff-dialog';
export * from './doctor-dialog/doctor-dialog';
diff --git a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
index 2262859664..02d9e3c28b 100644
--- a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
+++ b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
@@ -18,8 +18,7 @@
import React, { useState } from 'react';
-import { ShowJson } from '../../components';
-import { ShowHistory } from '../../components/show-history/show-history';
+import { ShowJson, SupervisorHistoryPanel } from '../../components';
import { cleanSpec } from '../../druid-models';
import { Api } from '../../singletons';
import { deepGet } from '../../utils';
@@ -96,12 +95,7 @@ export const SupervisorTableActionDialog = React.memo(function SupervisorTableAc
downloadFilename={`supervisor-payload-${supervisorId}.json`}
/>
)}
- {activeTab === 'history' && (
- <ShowHistory
- endpoint={`${supervisorEndpointBase}/history`}
- downloadFilenamePrefix={`supervisor-${supervisorId}`}
- />
- )}
+ {activeTab === 'history' && <SupervisorHistoryPanel supervisorId={supervisorId} />}
</TableActionDialog>
);
});
diff --git a/web-console/src/utils/sampler.ts b/web-console/src/utils/sampler.ts
index 46f456d0f0..1860d4fa20 100644
--- a/web-console/src/utils/sampler.ts
+++ b/web-console/src/utils/sampler.ts
@@ -16,6 +16,7 @@
* limitations under the License.
*/
+import { dedupe } from 'druid-query-toolkit';
import * as JSONBig from 'json-bigint-native';
import type {
@@ -91,18 +92,6 @@ export interface ExampleManifest {
spec: any;
}
-function dedupe(xs: string[]): string[] {
- const seen: Record<string, boolean> = {};
- return xs.filter(x => {
- if (seen[x]) {
- return false;
- } else {
- seen[x] = true;
- return true;
- }
- });
-}
-
export function getCacheRowsFromSampleResponse(sampleResponse: SampleResponse): CacheRows {
return filterMap(sampleResponse.data, d => d.input).slice(0, 20);
}
diff --git a/web-console/src/views/datasources-view/datasources-view.tsx b/web-console/src/views/datasources-view/datasources-view.tsx
index e109b02ac2..16a6aadf74 100644
--- a/web-console/src/views/datasources-view/datasources-view.tsx
+++ b/web-console/src/views/datasources-view/datasources-view.tsx
@@ -39,7 +39,7 @@ import {
} from '../../components';
import {
AsyncActionDialog,
- CompactionDialog,
+ CompactionConfigDialog,
KillDatasourceDialog,
RetentionDialog,
} from '../../dialogs';
@@ -233,7 +233,7 @@ interface RetentionDialogOpenOn {
readonly rules: Rule[];
}
-interface CompactionDialogOpenOn {
+interface CompactionConfigDialogOpenOn {
readonly datasource: string;
readonly compactionConfig?: CompactionConfig;
}
@@ -254,7 +254,7 @@ export interface DatasourcesViewState {
showUnused: boolean;
retentionDialogOpenOn?: RetentionDialogOpenOn;
- compactionDialogOpenOn?: CompactionDialogOpenOn;
+ compactionDialogOpenOn?: CompactionConfigDialogOpenOn;
datasourceToMarkAsUnusedAllSegmentsIn?: string;
datasourceToMarkAllNonOvershadowedSegmentsAsUsedIn?: string;
killDatasource?: string;
@@ -981,12 +981,12 @@ ORDER BY 1`;
);
}
- private renderCompactionDialog() {
+ private renderCompactionConfigDialog() {
const { datasourcesAndDefaultRulesState, compactionDialogOpenOn } = this.state;
if (!compactionDialogOpenOn || !datasourcesAndDefaultRulesState.data) return;
return (
- <CompactionDialog
+ <CompactionConfigDialog
datasource={compactionDialogOpenOn.datasource}
compactionConfig={compactionDialogOpenOn.compactionConfig}
onClose={() => this.setState({ compactionDialogOpenOn: undefined })}
@@ -1571,7 +1571,7 @@ ORDER BY 1`;
{this.renderUseUnuseActionByInterval()}
{this.renderKillAction()}
{this.renderRetentionDialog()}
- {this.renderCompactionDialog()}
+ {this.renderCompactionConfigDialog()}
{this.renderForceCompactAction()}
</div>
);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org