clean up default values and add infos (#8567)

This commit is contained in:
Vadim Ogievetsky 2019-09-21 21:00:21 -07:00 committed by Fangjin Yang
parent aeac0d4fd3
commit 868bb42301
9 changed files with 314 additions and 53 deletions

View File

@ -105,7 +105,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
class="bp3-form-content"
>
<div
class="bp3-control-group bp3-numeric-input"
class="bp3-control-group bp3-fill bp3-numeric-input"
>
<div
class="bp3-input-group"

View File

@ -54,7 +54,7 @@ export interface AutoFormProps<T> {
model: T | undefined;
onChange: (newModel: T) => void;
showCustom?: (model: T) => boolean;
updateJSONValidity?: (jsonValidity: boolean) => void;
updateJsonValidity?: (jsonValidity: boolean) => void;
large?: boolean;
}
@ -169,6 +169,7 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
min={0}
stepSize={1000}
majorStepSize={1000000}
fill
large={large}
disabled={AutoForm.evaluateFunctor(field.disabled, model)}
/>
@ -235,19 +236,19 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
}
private renderJSONInput(field: Field<T>): JSX.Element {
const { model, updateJSONValidity } = this.props;
const { model, updateJsonValidity } = this.props;
const { jsonInputsValidity } = this.state;
const updateInputValidity = (e: any) => {
if (updateJSONValidity) {
if (updateJsonValidity) {
const newJSONInputValidity = Object.assign({}, jsonInputsValidity, { [field.name]: e });
this.setState({
jsonInputsValidity: newJSONInputValidity,
});
const allJSONValid: boolean = Object.keys(newJSONInputValidity).every(
const allJsonValid: boolean = Object.keys(newJSONInputValidity).every(
property => newJSONInputValidity[property] === true,
);
updateJSONValidity(allJSONValid);
updateJsonValidity(allJsonValid);
}
};

View File

@ -64,7 +64,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"
@ -81,7 +109,7 @@ exports[`compaction dialog matches snapshot 1`] = `
min="0"
style="padding-right: 10px;"
type="text"
value=""
value="419430400"
/>
</div>
<div
@ -149,7 +177,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"
@ -166,7 +222,7 @@ exports[`compaction dialog matches snapshot 1`] = `
min="0"
style="padding-right: 10px;"
type="text"
value=""
value="150"
/>
</div>
<div
@ -234,7 +290,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"
@ -246,7 +330,7 @@ exports[`compaction dialog matches snapshot 1`] = `
class="bp3-input"
style="padding-right: 10px;"
type="text"
value=""
value="P1D"
/>
</div>
</div>
@ -261,7 +345,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"
@ -278,7 +390,7 @@ exports[`compaction dialog matches snapshot 1`] = `
min="0"
style="padding-right: 10px;"
type="text"
value=""
value="419430400"
/>
</div>
<div
@ -346,7 +458,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"
@ -452,7 +592,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"
@ -469,7 +637,7 @@ exports[`compaction dialog matches snapshot 1`] = `
min="0"
style="padding-right: 10px;"
type="text"
value=""
value="25"
/>
</div>
<div
@ -537,7 +705,35 @@ exports[`compaction dialog matches snapshot 1`] = `
<span
class="bp3-text-muted"
>
<span
class="bp3-popover-wrapper"
>
<span
class="bp3-popover-target"
>
<span
class="bp3-icon bp3-icon-info-sign"
icon="info-sign"
>
<svg
data-icon="info-sign"
height="14"
viewBox="0 0 16 16"
width="14"
>
<desc>
info-sign
</desc>
<path
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
fill-rule="evenodd"
/>
</svg>
</span>
</span>
</span>
</span>
</label>
<div
class="bp3-form-content"

View File

@ -19,7 +19,7 @@
import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
import React from 'react';
import { AutoForm } from '../../components';
import { AutoForm, ExternalLink } from '../../components';
import './compaction-dialog.scss';
@ -33,7 +33,7 @@ export interface CompactionDialogProps {
export interface CompactionDialogState {
currentConfig?: Record<string, any>;
allJSONValid: boolean;
allJsonValid: boolean;
}
export class CompactionDialog extends React.PureComponent<
@ -45,27 +45,17 @@ export class CompactionDialog extends React.PureComponent<
constructor(props: CompactionDialogProps) {
super(props);
this.state = {
allJSONValid: true,
allJsonValid: true,
};
}
componentDidMount(): void {
const { datasource, compactionConfig } = this.props;
let config: Record<string, any> = {
dataSource: datasource,
inputSegmentSizeBytes: 419430400,
maxNumSegmentsToCompact: 150,
skipOffsetFromLatest: 'P1D',
targetCompactionSizeBytes: CompactionDialog.DEFAULT_TARGET_COMPACTION_SIZE_BYTES,
taskContext: null,
taskPriority: 25,
tuningConfig: null,
};
if (compactionConfig !== undefined) {
config = compactionConfig;
}
this.setState({
currentConfig: config,
currentConfig: compactionConfig || {
dataSource: datasource,
},
});
}
@ -73,12 +63,14 @@ export class CompactionDialog extends React.PureComponent<
const { onSave } = this.props;
const { currentConfig } = this.state;
if (!currentConfig) return;
onSave(currentConfig);
};
render(): JSX.Element {
const { onClose, onDelete, datasource, compactionConfig } = this.props;
const { currentConfig, allJSONValid } = this.state;
const { currentConfig, allJsonValid } = this.state;
return (
<Dialog
className="compaction-dialog"
@ -92,35 +84,88 @@ export class CompactionDialog extends React.PureComponent<
{
name: 'inputSegmentSizeBytes',
type: 'number',
defaultValue: 419430400,
info: (
<p>
Maximum number of total segment bytes processed per compaction task. Since a time
chunk must be processed in its entirety, if the segments for a particular time
chunk have a total size in bytes greater than this parameter, compaction will not
run for that time chunk. Because each compaction task runs with a single thread,
setting this value too far above 12GB will result in compaction tasks taking an
excessive amount of time.
</p>
),
},
{
name: 'maxNumSegmentsToCompact',
type: 'number',
defaultValue: 150,
info: (
<p>
Maximum number of segments to compact together per compaction task. Since a time
chunk must be processed in its entirety, if a time chunk has a total number of
segments greater than this parameter, compaction will not run for that time chunk.
</p>
),
},
{
name: 'skipOffsetFromLatest',
type: 'string',
defaultValue: 'P1D',
info: (
<p>
The offset for searching segments to be compacted. Strongly recommended to set for
realtime dataSources.
</p>
),
},
{
name: 'targetCompactionSizeBytes',
type: 'number',
defaultValue: CompactionDialog.DEFAULT_TARGET_COMPACTION_SIZE_BYTES,
info: (
<p>
The target segment size, for each segment, after compaction. The actual sizes of
compacted segments might be slightly larger or smaller than this value. Each
compaction task may generate more than one output segment, and it will try to keep
each output segment close to this configured size.
</p>
),
},
{
name: 'taskContext',
type: 'json',
info: (
<p>
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/tasks.html#task-context">
Task context
</ExternalLink>{' '}
for compaction tasks.
</p>
),
},
{
name: 'taskPriority',
type: 'number',
defaultValue: 25,
info: <p>Priority of the compaction task.</p>,
},
{
name: 'tuningConfig',
type: 'json',
info: (
<p>
<ExternalLink href="https://druid.apache.org/docs/latest/configuration/index.html#compact-task-tuningconfig">
Tuning config
</ExternalLink>{' '}
for compaction tasks.
</p>
),
},
]}
model={currentConfig}
onChange={m => this.setState({ currentConfig: m })}
updateJSONValidity={e => this.setState({ allJSONValid: e })}
updateJsonValidity={e => this.setState({ allJsonValid: e })}
/>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
@ -135,7 +180,7 @@ export class CompactionDialog extends React.PureComponent<
text="Submit"
intent={Intent.PRIMARY}
onClick={this.handleSubmit}
disabled={!currentConfig || !allJSONValid}
disabled={!currentConfig || !allJsonValid}
/>
</div>
</div>

View File

@ -133,6 +133,12 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
</p>
<AutoForm
fields={[
{
name: 'maxSegmentsToMove',
type: 'number',
defaultValue: 5,
info: <>The maximum number of segments that can be moved at any given time.</>,
},
{
name: 'balancerComputeThreads',
type: 'number',
@ -148,6 +154,7 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
{
name: 'emitBalancingStats',
type: 'boolean',
defaultValue: false,
info: (
<>
Boolean flag for whether or not we should emit balancing stats. This is an
@ -158,6 +165,7 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
{
name: 'killAllDataSources',
type: 'boolean',
defaultValue: false,
info: (
<>
Send kill tasks for ALL dataSources if property{' '}
@ -205,12 +213,6 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
</>
),
},
{
name: 'maxSegmentsToMove',
type: 'number',
defaultValue: 5,
info: <>The maximum number of segments that can be moved at any given time.</>,
},
{
name: 'mergeBytesLimit',
type: 'size-bytes',

View File

@ -34,7 +34,7 @@ export interface OverlordDynamicConfigDialogProps {
export interface OverlordDynamicConfigDialogState {
dynamicConfig?: Record<string, any>;
allJSONValid: boolean;
allJsonValid: boolean;
historyRecords: any[];
}
@ -47,7 +47,7 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
constructor(props: OverlordDynamicConfigDialogProps) {
super(props);
this.state = {
allJSONValid: true,
allJsonValid: true,
historyRecords: [],
};
@ -115,7 +115,7 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
render(): JSX.Element {
const { onClose } = this.props;
const { dynamicConfig, allJSONValid, historyRecords } = this.state;
const { dynamicConfig, allJsonValid, historyRecords } = this.state;
return (
<SnitchDialog
@ -123,7 +123,7 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
onSave={this.saveConfig}
onClose={onClose}
title="Overlord dynamic config"
saveDisabled={!allJSONValid}
saveDisabled={!allJsonValid}
historyRecords={historyRecords}
>
<p>
@ -147,7 +147,7 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
]}
model={dynamicConfig}
onChange={m => this.setState({ dynamicConfig: m })}
updateJSONValidity={e => this.setState({ allJSONValid: e })}
updateJsonValidity={e => this.setState({ allJsonValid: e })}
/>
</SnitchDialog>
);

View File

@ -787,6 +787,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
type: 'string-array',
placeholder:
'https://example.com/path/to/file1.ext, https://example.com/path/to/file2.ext',
required: true,
info: (
<p>
The full URI of your file. To ingest from multiple URIs, use commas to separate each
@ -818,6 +819,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
label: 'Base directory',
type: 'string',
placeholder: '/path/to/files/',
required: true,
info: (
<>
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/firehose.html#localfirehose">
@ -831,7 +833,8 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
name: 'firehose.filter',
label: 'File filter',
type: 'string',
defaultValue: '*.*',
required: true,
suggestions: ['*', '*.json', '*.json.gz', '*.csv', '*.tsv'],
info: (
<>
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/firehose.html#localfirehose">
@ -856,6 +859,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
name: 'firehose.dataSource',
label: 'Datasource',
type: 'string',
required: true,
info: <p>The datasource to fetch rows from.</p>,
},
{
@ -868,6 +872,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
`${CURRENT_YEAR}-01-01/${CURRENT_YEAR + 1}-01-01`,
`${CURRENT_YEAR}/${CURRENT_YEAR + 1}`,
],
required: true,
info: (
<p>
A String representing ISO-8601 Interval. This defines the time range to fetch the data
@ -930,6 +935,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
label: 'S3 URIs',
type: 'string-array',
placeholder: 's3://your-bucket/some-file1.ext, s3://your-bucket/some-file2.ext',
required: true,
defined: ioConfig => !deepGet(ioConfig, 'firehose.prefixes'),
info: (
<>
@ -946,6 +952,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
label: 'S3 prefixes',
type: 'string-array',
placeholder: 's3://your-bucket/some-path1, s3://your-bucket/some-path2',
required: true,
defined: ioConfig => !deepGet(ioConfig, 'firehose.uris'),
info: (
<>
@ -963,6 +970,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
name: 'firehose.blobs',
label: 'Google blobs',
type: 'json',
required: true,
info: (
<>
<p>
@ -983,6 +991,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
name: 'consumerProperties.{bootstrap.servers}',
label: 'Bootstrap servers',
type: 'string',
required: true,
info: (
<>
<ExternalLink href="https://druid.apache.org/docs/latest/development/extensions-core/kafka-ingestion#kafkasupervisorioconfig">
@ -998,6 +1007,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
{
name: 'topic',
type: 'string',
required: true,
defined: (i: IoConfig) => i.type === 'kafka',
},
{
@ -1021,6 +1031,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
name: 'stream',
type: 'string',
placeholder: 'your-kinesis-stream',
required: true,
info: <>The Kinesis stream to read.</>,
},
{
@ -1051,6 +1062,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
'kinesis.us-gov-east-1.amazonaws.com',
'kinesis.us-gov-west-1.amazonaws.com',
],
required: true,
info: (
<>
The Amazon Kinesis stream endpoint for a region. You can find a list of endpoints{' '}
@ -1987,6 +1999,10 @@ export function updateIngestionType(
if (firehoseType) {
newSpec = deepSet(newSpec, 'ioConfig.firehose', { type: firehoseType });
if (firehoseType === 'local') {
newSpec = deepSet(newSpec, 'ioConfig.firehose.filter', '*');
}
}
if (!deepGet(spec, 'dataSchema.dataSource')) {

View File

@ -158,7 +158,7 @@ exports[`load data view matches snapshot 1`] = `
icon="manually-entered-data"
key="spec"
onClick={[Function]}
text="Edit JSON spec"
text="Edit spec"
/>
</Blueprint3.ButtonGroup>
</div>

View File

@ -232,7 +232,7 @@ const VIEW_TITLE: Record<Step, string> = {
partition: 'Partition',
tuning: 'Tune',
publish: 'Publish',
spec: 'Edit JSON spec',
spec: 'Edit spec',
loading: 'Loading',
};
@ -2788,6 +2788,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
name: 'ioConfig.appendToExisting',
label: 'Append to existing',
type: 'boolean',
defaultValue: false,
defined: spec => !deepGet(spec, 'tuningConfig.forceGuaranteedRollup'),
info: (
<>
@ -2809,8 +2810,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
name: 'tuningConfig.logParseExceptions',
label: 'Log parse exceptions',
type: 'boolean',
disabled: parallel,
defaultValue: false,
disabled: parallel,
info: (
<>
If true, log an error message when a parsing exception occurs, containing