diff --git a/web-console/src/dialogs/retention-dialog/retention-dialog.tsx b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
index 677173cc6d3f..cc9645bd79f2 100644
--- a/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
+++ b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
@@ -129,7 +129,7 @@ ORDER BY 1`,
Druid uses rules to determine what data should be retained in the cluster. The rules are
evaluated in order from top to bottom. For more information please refer to the{' '}
-
+
documentation
.
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 5e3d9e500288..44ef05d5d59f 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
@@ -93,7 +93,7 @@ export const SupervisorTableActionDialog = React.memo(function SupervisorTableAc
{activeTab === 'spec' && (
cleanSpec(x, true)}
+ transform={cleanSpec}
downloadFilename={`supervisor-payload-${supervisorId}.json`}
/>
)}
diff --git a/web-console/src/druid-models/execution/execution.ts b/web-console/src/druid-models/execution/execution.ts
index 799de6f9c511..dcb5b2d1b939 100644
--- a/web-console/src/druid-models/execution/execution.ts
+++ b/web-console/src/druid-models/execution/execution.ts
@@ -18,6 +18,7 @@
import { Column, QueryResult, SqlExpression, SqlQuery, SqlWithQuery } from '@druid-toolkit/query';
+import { maybeGetClusterCapacity } from '../../helpers';
import {
deepGet,
deleteKeys,
@@ -192,8 +193,13 @@ export interface ExecutionValue {
}
export class Execution {
+ static USE_TASK_PAYLOAD = true;
+ static USE_TASK_REPORTS = true;
static INLINE_DATASOURCE_MARKER = '__query_select';
+ static getClusterCapacity: (() => Promise) | undefined =
+ maybeGetClusterCapacity;
+
static validAsyncState(status: string | undefined): status is AsyncState {
return oneOf(status, 'ACCEPTED', 'RUNNING', 'FINISHED', 'FAILED');
}
diff --git a/web-console/src/druid-models/filter/filter.tsx b/web-console/src/druid-models/filter/filter.tsx
index a7fd317197b3..41f0d09ca856 100644
--- a/web-console/src/druid-models/filter/filter.tsx
+++ b/web-console/src/druid-models/filter/filter.tsx
@@ -170,7 +170,7 @@ export const FILTERS_FIELDS: Field[] = [
<>
A Druid{' '}
-
+
JSON filter expression
{' '}
to apply to the data.
diff --git a/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx b/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
index 2705614571dc..d51fd34e901a 100644
--- a/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
+++ b/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
@@ -212,8 +212,10 @@ export function getIngestionTitle(ingestionType: IngestionComboTypeWithExtra): s
export function getIngestionImage(ingestionType: IngestionComboTypeWithExtra): string {
const parts = ingestionType.split(':');
- if (parts.length === 2) return parts[1];
- return ingestionType;
+ return parts[parts.length - 1]
+ .split(/(?=[A-Z])/)
+ .join('-')
+ .toLowerCase();
}
export function getIngestionDocLink(spec: Partial): string {
@@ -221,13 +223,13 @@ export function getIngestionDocLink(spec: Partial): string {
switch (type) {
case 'kafka':
- return `${getLink('DOCS')}/development/extensions-core/kafka-ingestion.html`;
+ return `${getLink('DOCS')}/ingestion/kafka-ingestion`;
case 'kinesis':
- return `${getLink('DOCS')}/development/extensions-core/kinesis-ingestion.html`;
+ return `${getLink('DOCS')}/ingestion/kinesis-ingestion`;
default:
- return `${getLink('DOCS')}/ingestion/native-batch.html#input-sources`;
+ return `${getLink('DOCS')}/ingestion/input-sources`;
}
}
@@ -476,16 +478,9 @@ export function normalizeSpec(spec: Partial): IngestionSpec {
/**
* Make sure that any extra junk in the spec other than 'type', 'spec', and 'context' is removed
* @param spec - the spec to clean
- * @param allowSuspended - allow keeping 'suspended' also
*/
-export function cleanSpec(
- spec: Partial,
- allowSuspended?: boolean,
-): Partial {
- return allowKeys(
- spec,
- ['type', 'spec', 'context'].concat(allowSuspended ? ['suspended'] : []) as any,
- ) as IngestionSpec;
+export function cleanSpec(spec: Partial): Partial {
+ return allowKeys(spec, ['type', 'spec', 'context', 'suspended']) as IngestionSpec;
}
export function upgradeSpec(spec: any, yolo = false): Partial {
@@ -583,7 +578,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
info: (
Druid connects to raw data through{' '}
-
+
inputSources
. You can change your selected inputSource here.
@@ -608,7 +603,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
For more information, refer to the documentation for{' '}
-
+
FileSystem#getPathMatcher
.
@@ -662,7 +657,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
required: true,
info: (
<>
-
+
inputSource.baseDir
Specifies the directory to search recursively for files to be ingested.
@@ -677,14 +672,12 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
suggestions: FILTER_SUGGESTIONS,
info: (
<>
-
+
inputSource.filter
A wildcard filter for files. See{' '}
-
+
here
{' '}
for format information. Files matching the filter criteria are considered for
@@ -726,8 +719,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
hideInMore: true,
info: (
- The{' '}
- filter {' '}
+ The filter {' '}
to apply to the data as part of querying.
),
@@ -787,7 +779,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
<>
JSON array of{' '}
-
+
S3 Objects
.
@@ -950,7 +942,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
<>
JSON array of{' '}
-
+
S3 Objects
.
@@ -1024,7 +1018,11 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
<>
JSON array of{' '}
-
+
Google Cloud Storage Objects
.
@@ -1091,11 +1089,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
placeholder: 'kafka_broker_host:9092',
info: (
<>
-
+
consumerProperties
@@ -1141,11 +1135,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
defaultValue: {},
info: (
<>
-
+
consumerProperties
A map of properties to be passed to the Kafka consumer.
@@ -1254,7 +1244,7 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
info: (
<>
The Amazon Kinesis stream endpoint for a region. You can find a list of endpoints{' '}
-
+
here
.
@@ -1884,7 +1874,9 @@ export function getSecondaryPartitionRelatedFormFields(
This should be the first dimension in your schema which would make it first in the
sort order. As{' '}
-
+
Partitioning and sorting are best friends!
@@ -2511,7 +2503,7 @@ export function guessSimpleInputFormat(
if (sampleDatum.startsWith('ORC')) {
return inputFormatFromType({ type: 'orc' });
}
- // Avro OCF 4 byte magic header: https://avro.apache.org/docs/current/spec.html#Object+Container+Files
+ // Avro OCF 4 byte magic header: https://avro.apache.org/docs/current/spec#Object+Container+Files
if (sampleDatum.startsWith('Obj\x01')) {
return inputFormatFromType({ type: 'avro_ocf' });
}
diff --git a/web-console/src/druid-models/input-format/input-format.tsx b/web-console/src/druid-models/input-format/input-format.tsx
index 7692a62a7a44..a5a1fbdfa073 100644
--- a/web-console/src/druid-models/input-format/input-format.tsx
+++ b/web-console/src/druid-models/input-format/input-format.tsx
@@ -76,7 +76,7 @@ function generateInputFormatFields(streaming: boolean) {
The parser used to parse the data.
For more information see{' '}
-
+
the documentation
.
@@ -329,7 +329,7 @@ export const KAFKA_METADATA_INPUT_FORMAT_FIELDS: Field[] = [
The parser used to parse the key of the Kafka message.
For more information see{' '}
-
+
the documentation
.
diff --git a/web-console/src/druid-models/input-source/input-source.tsx b/web-console/src/druid-models/input-source/input-source.tsx
index 174f8aba516b..4479150227d3 100644
--- a/web-console/src/druid-models/input-source/input-source.tsx
+++ b/web-console/src/druid-models/input-source/input-source.tsx
@@ -97,7 +97,7 @@ export type InputSourceDesc =
dataSource: string;
interval: string;
filter?: any;
- dimensions?: string[]; // ToDo: these are not in the docs https://druid.apache.org/docs/latest/ingestion/input-sources.html
+ dimensions?: string[]; // ToDo: these are not in the docs https://druid.apache.org/docs/latest/ingestion/input-sources
metrics?: string[];
maxInputSegmentBytesPerTask?: number;
}
@@ -264,9 +264,7 @@ export const INPUT_SOURCE_FIELDS: Field[] = [
required: true,
info: (
<>
-
- baseDir
-
+ baseDir
Specifies the directory to search recursively for files to be ingested.
>
),
@@ -280,12 +278,12 @@ export const INPUT_SOURCE_FIELDS: Field[] = [
suggestions: FILTER_SUGGESTIONS,
info: (
<>
-
+
filter
A wildcard filter for files. See{' '}
-
+
here
{' '}
for format information.
@@ -344,7 +342,7 @@ export const INPUT_SOURCE_FIELDS: Field[] = [
<>
JSON array of{' '}
-
+
S3 Objects
.
@@ -406,7 +404,7 @@ export const INPUT_SOURCE_FIELDS: Field[] = [
<>
JSON array of{' '}
-
+
S3 Objects
.
@@ -480,7 +478,9 @@ export const INPUT_SOURCE_FIELDS: Field[] = [
<>
JSON array of{' '}
-
+
Google Cloud Storage Objects
.
@@ -508,7 +508,7 @@ export const INPUT_SOURCE_FIELDS: Field[] = [
For more information, refer to the documentation for{' '}
-
+
FileSystem#getPathMatcher
.
diff --git a/web-console/src/druid-models/metric-spec/metric-spec.tsx b/web-console/src/druid-models/metric-spec/metric-spec.tsx
index 367f922ca48b..f8dbfd964439 100644
--- a/web-console/src/druid-models/metric-spec/metric-spec.tsx
+++ b/web-console/src/druid-models/metric-spec/metric-spec.tsx
@@ -201,7 +201,7 @@ export const METRIC_SPEC_FIELDS: Field[] = [
See the{' '}
-
+
DataSketches site
{' '}
for details.
@@ -307,7 +307,7 @@ export const METRIC_SPEC_FIELDS: Field[] = [
Must be a power of 2 from 2 to 32768. See the{' '}
-
+
Quantiles Accuracy
{' '}
for details.
@@ -385,7 +385,7 @@ export const METRIC_SPEC_FIELDS: Field[] = [
outlier handling modes
{' '}
diff --git a/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx b/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx
index 63ebb9381915..3c4060e5621e 100644
--- a/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx
+++ b/web-console/src/druid-models/overlord-dynamic-config/overlord-dynamic-config.tsx
@@ -20,6 +20,8 @@ import { Callout } from '@blueprintjs/core';
import React from 'react';
import type { Field } from '../../components';
+import { ExternalLink } from '../../components';
+import { getLink } from '../../links';
import { deepGet, oneOf } from '../../utils';
export interface OverlordDynamicConfig {
@@ -92,6 +94,11 @@ export const OVERLORD_DYNAMIC_CONFIG_FIELDS: Field[] = [
"datasource2": ["host3:port"]
}`}
+
+
+ Learn more
+
+
>
),
},
@@ -131,6 +138,11 @@ export const OVERLORD_DYNAMIC_CONFIG_FIELDS: Field[] = [
}
}`}
+
+
+ Learn more
+
+
>
),
},
diff --git a/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx b/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx
index a88ffc3d0ef8..07ef6ade3ff3 100644
--- a/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx
+++ b/web-console/src/druid-models/timestamp-spec/timestamp-spec.tsx
@@ -138,7 +138,7 @@ export const TIMESTAMP_SPEC_FIELDS: Field[] = [
info: (
Specify your timestamp format by using the suggestions menu or typing in a{' '}
-
+
format string
.
diff --git a/web-console/src/druid-models/transform-spec/transform-spec.tsx b/web-console/src/druid-models/transform-spec/transform-spec.tsx
index ffb90d2226ee..cf8224d90f1e 100644
--- a/web-console/src/druid-models/transform-spec/transform-spec.tsx
+++ b/web-console/src/druid-models/transform-spec/transform-spec.tsx
@@ -56,7 +56,7 @@ export const TRANSFORM_FIELDS: Field[] = [
info: (
<>
A valid Druid{' '}
- expression .
+ expression .
>
),
},
@@ -83,8 +83,8 @@ export function getTimestampExpressionFields(transforms: Transform[]): Field
A valid Druid{' '}
- expression {' '}
- that should output a millis timestamp. You most likely want to use the{' '}
+ expression that
+ should output a millis timestamp. You most likely want to use the{' '}
timestamp_parse function at the outer level.
>
),
diff --git a/web-console/src/helpers/capabilities.ts b/web-console/src/helpers/capabilities.ts
index ce8509072f2a..4b10a49c9652 100644
--- a/web-console/src/helpers/capabilities.ts
+++ b/web-console/src/helpers/capabilities.ts
@@ -38,7 +38,7 @@ export interface CapabilitiesValue {
multiStageQuery: boolean;
coordinator: boolean;
overlord: boolean;
- clusterCapacity?: number;
+ maxTaskSlots?: number;
}
export class Capabilities {
@@ -54,7 +54,7 @@ export class Capabilities {
private readonly multiStageQuery: boolean;
private readonly coordinator: boolean;
private readonly overlord: boolean;
- private readonly clusterCapacity?: number;
+ private readonly maxTaskSlots?: number;
static async detectQueryType(): Promise {
// Check SQL endpoint
@@ -171,7 +171,7 @@ export class Capabilities {
return new Capabilities({
...capabilities.valueOf(),
- clusterCapacity: capacity.totalTaskSlots,
+ maxTaskSlots: capacity.totalTaskSlots,
});
}
@@ -180,7 +180,7 @@ export class Capabilities {
this.multiStageQuery = value.multiStageQuery;
this.coordinator = value.coordinator;
this.overlord = value.overlord;
- this.clusterCapacity = value.clusterCapacity;
+ this.maxTaskSlots = value.maxTaskSlots;
}
public valueOf(): CapabilitiesValue {
@@ -189,7 +189,7 @@ export class Capabilities {
multiStageQuery: this.multiStageQuery,
coordinator: this.coordinator,
overlord: this.overlord,
- clusterCapacity: this.clusterCapacity,
+ maxTaskSlots: this.maxTaskSlots,
};
}
@@ -263,8 +263,8 @@ export class Capabilities {
return this.hasSql() || this.hasOverlordAccess();
}
- public getClusterCapacity(): number | undefined {
- return this.clusterCapacity;
+ public getMaxTaskSlots(): number | undefined {
+ return this.maxTaskSlots;
}
}
Capabilities.FULL = new Capabilities({
diff --git a/web-console/src/helpers/execution/sql-task-execution.ts b/web-console/src/helpers/execution/sql-task-execution.ts
index f0aa7dde54ce..ca7c0485bd4a 100644
--- a/web-console/src/helpers/execution/sql-task-execution.ts
+++ b/web-console/src/helpers/execution/sql-task-execution.ts
@@ -23,10 +23,6 @@ import type { AsyncStatusResponse, MsqTaskPayloadResponse, QueryContext } from '
import { Execution } from '../../druid-models';
import { Api } from '../../singletons';
import { deepGet, DruidError, IntermediateQueryState, QueryManager } from '../../utils';
-import { maybeGetClusterCapacity } from '../capacity';
-
-const USE_TASK_PAYLOAD = true;
-const USE_TASK_REPORTS = true;
// some executionMode has to be set on the /druid/v2/sql/statements API
function ensureExecutionModeIsSet(context: QueryContext | undefined): QueryContext {
@@ -161,7 +157,7 @@ export async function getTaskExecution(
let execution: Execution | undefined;
- if (USE_TASK_REPORTS) {
+ if (Execution.USE_TASK_REPORTS) {
let taskReport: any;
try {
taskReport = (
@@ -198,7 +194,7 @@ export async function getTaskExecution(
}
let taskPayload = taskPayloadOverride;
- if (USE_TASK_PAYLOAD && !taskPayload) {
+ if (Execution.USE_TASK_PAYLOAD && !taskPayload) {
try {
taskPayload = (
await Api.instance.get(`/druid/indexer/v1/task/${encodedId}`, {
@@ -229,8 +225,8 @@ export async function getTaskExecution(
}
}
- if (execution.hasPotentiallyStuckStage()) {
- const capacityInfo = await maybeGetClusterCapacity();
+ if (Execution.getClusterCapacity && execution.hasPotentiallyStuckStage()) {
+ const capacityInfo = await Execution.getClusterCapacity();
if (capacityInfo) {
execution = execution.changeCapacityInfo(capacityInfo);
}
diff --git a/web-console/src/helpers/spec-conversion.ts b/web-console/src/helpers/spec-conversion.ts
index 7e7673c73842..2c621f2466c2 100644
--- a/web-console/src/helpers/spec-conversion.ts
+++ b/web-console/src/helpers/spec-conversion.ts
@@ -46,8 +46,8 @@ import {
} from '../druid-models';
import { deepGet, filterMap, nonEmptyArray, oneOf } from '../utils';
-export function getSpecDatasourceName(spec: Partial): string {
- return deepGet(spec, 'spec.dataSchema.dataSource') || 'unknown_datasource';
+export function getSpecDatasourceName(spec: Partial): string | undefined {
+ return deepGet(spec, 'spec.dataSchema.dataSource');
}
function convertFilter(filter: any): SqlExpression {
diff --git a/web-console/src/hooks/use-query-manager.ts b/web-console/src/hooks/use-query-manager.ts
index a21d7b64691a..384443745838 100644
--- a/web-console/src/hooks/use-query-manager.ts
+++ b/web-console/src/hooks/use-query-manager.ts
@@ -58,7 +58,7 @@ export function useQueryManager(
// will be compatible with future React versions that may mount/unmount/remount
// the same component multiple times while.
//
- // See https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state
+ // See https://reactjs.org/docs/strict-mode#ensuring-reusable-state
// and https://github.com/reactwg/react-18/discussions/18
let myQueryManager = queryManager;
if (queryManager.isTerminated()) {
diff --git a/web-console/src/links.ts b/web-console/src/links.ts
index ccd26367969d..552ca5e81221 100644
--- a/web-console/src/links.ts
+++ b/web-console/src/links.ts
@@ -40,7 +40,7 @@ const DEFAULT_LINKS: Links = {
communityHref: 'https://druid.apache.org/community/',
slackHref: 'https://druid.apache.org/community/join-slack',
userGroup: 'https://groups.google.com/forum/#!forum/druid-user',
- developerGroup: 'https://lists.apache.org/list.html?dev@druid.apache.org',
+ developerGroup: 'https://lists.apache.org/list?dev@druid.apache.org',
};
const links = DEFAULT_LINKS;
@@ -76,13 +76,13 @@ export function getLink(linkName: LinkNames): string {
case 'DOCS':
return links.docsHref;
case 'DOCS_SQL':
- return `${links.docsHref}/querying/sql.html`;
+ return `${links.docsHref}/querying/sql`;
case 'DOCS_RUNE':
- return `${links.docsHref}/querying/querying.html`;
+ return `${links.docsHref}/querying/querying`;
case 'DOCS_API':
- return `${links.docsHref}/api-reference/api-reference.html`;
+ return `${links.docsHref}/api-reference/api-reference`;
case 'DOCS_MSQ_ERROR':
- return `${links.docsHref}/multi-stage-query/reference.html`;
+ return `${links.docsHref}/multi-stage-query/reference`;
case 'COMMUNITY':
return links.communityHref;
case 'SLACK':
diff --git a/web-console/src/utils/joda-to-regexp.ts b/web-console/src/utils/joda-to-regexp.ts
index 10ca006986a3..8c412dd8911d 100644
--- a/web-console/src/utils/joda-to-regexp.ts
+++ b/web-console/src/utils/joda-to-regexp.ts
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-// Refer to https://www.joda.org/joda-time/key_format.html
+// Refer to https://www.joda.org/joda-time/key_format
const TEXT = '\\w+';
const NUMBER_2_DIGIT = '[0-9]{2}';
const NUMBER_4_DIGIT = '[0-9]{4}';
diff --git a/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap b/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap
index c78b0a80f7ea..657e9e4a651a 100644
--- a/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap
+++ b/web-console/src/views/home-view/__snapshots__/home-view.spec.tsx.snap
@@ -7,8 +7,8 @@ exports[`HomeView matches snapshot (coordinator) 1`] = `
Azure Data Lake
diff --git a/web-console/src/views/load-data-view/info-messages.tsx b/web-console/src/views/load-data-view/info-messages.tsx
index ad9e96667db5..e3a5e7f3993b 100644
--- a/web-console/src/views/load-data-view/info-messages.tsx
+++ b/web-console/src/views/load-data-view/info-messages.tsx
@@ -38,9 +38,7 @@ export const ConnectMessage = React.memo(function ConnectMessage(props: ConnectM
Druid ingests raw data and converts it into a custom,{' '}
-
- indexed format
- {' '}
+ indexed format {' '}
that is optimized for analytic queries.
{inlineMode ? (
@@ -67,10 +65,10 @@ export const ParserMessage = React.memo(function ParserMessage() {
If you have nested data, you can ingest it as{' '}
- json {' '}
+ json {' '}
dimensions.
-
+
);
@@ -91,7 +89,7 @@ export const TimestampMessage = React.memo(function TimestampMessage() {
combine them into one by selecting Expression and defining a transform
expression.
-
+
);
@@ -103,12 +101,12 @@ export const TransformMessage = React.memo(function TransformMessage() {
Druid can perform per-row{' '}
-
+
transforms
{' '}
of column values allowing you to create new derived columns or alter existing column.
-
+
);
@@ -120,9 +118,9 @@ export const FilterMessage = React.memo(function FilterMessage() {
Druid can filter out unwanted data by applying per-row{' '}
- filters .
+ filters .
-
+
);
@@ -148,7 +146,7 @@ export const SchemaMessage = React.memo(function SchemaMessage(props: SchemaMess
change the type, click on the column header.
)}
-
+
);
@@ -164,7 +162,7 @@ export const PartitionMessage = React.memo(function PartitionMessage() {
Primary partitioning), and each time chunk contains one or more segments (
Secondary partitioning).
-
+
);
@@ -175,7 +173,7 @@ export const TuningMessage = React.memo(function TuningMessage() {
Fine tune how Druid will ingest data.
-
+
);
@@ -201,7 +199,7 @@ export const SpecMessage = React.memo(function SpecMessage() {
you modify any values in previous sections, this spec will automatically update.
Submit the spec to begin loading data into Druid.
-
+
);
diff --git a/web-console/src/views/load-data-view/load-data-view.scss b/web-console/src/views/load-data-view/load-data-view.scss
index 8532313b10bd..d5248c5190db 100644
--- a/web-console/src/views/load-data-view/load-data-view.scss
+++ b/web-console/src/views/load-data-view/load-data-view.scss
@@ -273,6 +273,7 @@ $actual-icon-height: 400px;
}
.control {
+ position: relative;
grid-area: ctrl;
overflow: auto;
padding: 0 5px;
@@ -320,4 +321,10 @@ $actual-icon-height: 400px;
.parse-metadata {
border-top: 1px solid $gray1;
}
+
+ .suspended-switch {
+ position: absolute;
+ bottom: 0;
+ right: 5px;
+ }
}
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index 5e907a242674..555ba6f4a09a 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -56,7 +56,7 @@ import {
Loader,
PopoverText,
} from '../../components';
-import { AlertDialog, AsyncActionDialog } from '../../dialogs';
+import { AlertDialog, AsyncActionDialog, DiffDialog } from '../../dialogs';
import type {
ArrayMode,
DimensionSpec,
@@ -146,6 +146,7 @@ import {
deepMove,
deepSet,
deepSetMulti,
+ deleteKeys,
EMPTY_ARRAY,
EMPTY_OBJECT,
filterMap,
@@ -427,6 +428,8 @@ export interface LoadDataViewState {
// for final step
existingDatasources?: string[];
submitting: boolean;
+ currentSupervisorSpec?: Partial;
+ showDiffWithCurrent: boolean;
}
export class LoadDataView extends React.PureComponent {
@@ -478,6 +481,7 @@ export class LoadDataView extends React.PureComponent
If you do not see your source of raw data here, you can try to ingest it by submitting a{' '}
-
+
JSON task or supervisor spec
.
@@ -1707,7 +1711,7 @@ export class LoadDataView extends React.PureComponent
@@ -2377,12 +2381,12 @@ export class LoadDataView extends React.PureComponent
Select whether or not you want to set an explicit list of{' '}
dimensions
{' '}
and{' '}
-
+
metrics
. Explicitly setting dimensions and metrics can lead to better compression and
@@ -2437,7 +2441,7 @@ export class LoadDataView extends React.PureComponent
If you enable{' '}
-
+
roll-up
, Druid will try to pre-aggregate data before indexing it to conserve storage.
@@ -2446,12 +2450,12 @@ export class LoadDataView extends React.PureComponent
If you enable rollup, you must specify which columns are{' '}
-
+
dimensions
{' '}
(fields you want to group and filter on), and which are{' '}
- metrics (fields
- you want to aggregate on).
+ metrics (fields you
+ want to aggregate on).
}
@@ -2708,7 +2712,7 @@ export class LoadDataView extends React.PureComponent
documentation
@@ -2743,7 +2747,7 @@ export class LoadDataView extends React.PureComponent
For more information refer to the{' '}
-
+
documentation
.
@@ -3407,6 +3409,8 @@ export class LoadDataView extends React.PureComponent('/druid/coordinator/v1/datasources'))
@@ -3415,13 +3419,26 @@ export class LoadDataView extends React.PureComponent | undefined;
+ const supervisorId = getSpecDatasourceName(spec);
+ if (isStreamingSpec(spec) && supervisorId) {
+ try {
+ currentSupervisorSpec = cleanSpec(
+ (await Api.instance.get(`/druid/indexer/v1/supervisor/${Api.encodePath(supervisorId)}`))
+ .data,
+ );
+ } catch {}
+ }
+
this.setState({
existingDatasources,
+ currentSupervisorSpec,
});
}
renderSpecStep() {
- const { spec, existingDatasources, submitting } = this.state;
+ const { spec, existingDatasources, submitting, currentSupervisorSpec, showDiffWithCurrent } =
+ this.state;
const issueWithSpec = getIssueWithSpec(spec);
const datasource = deepGet(spec, 'spec.dataSchema.dataSource');
@@ -3465,7 +3482,7 @@ export class LoadDataView extends React.PureComponent
documentation
@@ -3475,75 +3492,124 @@ export class LoadDataView extends React.PureComponent
)}
+ {isStreamingSpec(spec) && currentSupervisorSpec && (
+ {
+ this.setState({
+ showDiffWithCurrent: true,
+ });
+ }}
+ />
+ )}
+ {isStreamingSpec(spec) && (
+
+ this.updateSpec(
+ spec.suspended ? deleteKeys(spec, ['suspended']) : { ...spec, suspended: true },
+ )
+ }
+ />
+ )}