Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDS] TSVB Support #6298

Merged
merged 28 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b9434b1
Add MDS support to TSVB
huyaboo Mar 26, 2024
6a00949
Refactor datasource picker component
huyaboo Mar 26, 2024
910e93a
Allow picker to persist state
huyaboo Mar 27, 2024
9b9c681
Refactored picker component params
huyaboo Mar 27, 2024
7be618d
Add unit tests
huyaboo Mar 27, 2024
7b7da2f
Merge branch 'main' into tsvb
huyaboo Mar 29, 2024
cae4f7f
Add to CHANGELOG
huyaboo Mar 29, 2024
8d7522c
Merge branch 'main' into tsvb
huyaboo Apr 2, 2024
e2a738b
Refactor components to use hideLocalCluster
huyaboo Apr 2, 2024
62eedbe
Merge branch 'main' into tsvb
huyaboo Apr 2, 2024
44a06ee
Merge branch 'main' into tsvb
huyaboo Apr 4, 2024
9d4abc4
Merge branch 'main' into tsvb
huyaboo Apr 10, 2024
26cd786
Remove Picker wrapper
huyaboo Apr 4, 2024
c880943
Update selector component and rename field to index name
huyaboo Apr 10, 2024
080eb4c
Address comments
huyaboo Apr 10, 2024
aadcd35
Merge branch 'main' into tsvb
huyaboo Apr 11, 2024
64c45e8
Refactor to use different decideClient
huyaboo Apr 11, 2024
817e342
Add optional arg
huyaboo Apr 11, 2024
d4617d3
Merge branch 'main' into tsvb
huyaboo Apr 11, 2024
710eaf7
Merge branch 'main' into tsvb
huyaboo Apr 12, 2024
a0635bf
Merge branch 'main' into tsvb
huyaboo Apr 12, 2024
106a09e
Merge branch 'main' into tsvb
huyaboo Apr 15, 2024
f4f237f
Merge branch 'main' into tsvb
huyaboo Apr 15, 2024
2a611a1
Merge branch 'main' into tsvb
huyaboo Apr 16, 2024
1436a53
Remove hidelocalcluster as a setting
huyaboo Apr 16, 2024
a6300f4
Merge branch 'main' into tsvb
huyaboo Apr 16, 2024
76ed1a4
Fixed case where local cluster is disabled but the datasource id coul…
huyaboo Apr 16, 2024
fe2b794
Add test for create data source picker handler
huyaboo Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Workspace] Add permission control logic ([#6052](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6052))
- [Multiple Datasource] Add default icon for selectable component and make sure the default datasource shows automatically ([#6327](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6327))
- [Multiple Datasource] Pass selected data sources to plugin consumers when the multi-select component initially loads ([#6333](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6333))
- [Mulitple Datasource] Add multi data source support to TSVB ([#6298](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6298))
- [Multiple Datasource] Add installedPlugins list to data source saved object ([#6348](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6348))
- [Multiple Datasource] Add default icon in multi-selectable picker ([#6357](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6357))
- [Workspace] Add APIs to support plugin state in request ([#6303](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6303))
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export {
FieldDescriptor as IndexPatternFieldDescriptor,
shouldReadFieldFromDocValues, // used only in logstash_fields fixture
FieldDescriptor,
decideClient,
} from './index_patterns';

export {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/index_patterns/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@
export * from './utils';
export { IndexPatternsFetcher, FieldDescriptor, shouldReadFieldFromDocValues } from './fetcher';
export { IndexPatternsService, IndexPatternsServiceStart } from './index_patterns_service';
export { decideClient } from './routes';
2 changes: 1 addition & 1 deletion src/plugins/data/server/index_patterns/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export function registerRoutes(http: HttpServiceSetup) {
);
}

const decideClient = async (
export const decideClient = async (
context: RequestHandlerContext,
request: any
): Promise<LegacyAPICaller> => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface DataSourceSelectorProps {
dataSourceFilter?: (dataSource: SavedObject<DataSourceAttributes>) => boolean;
compressed?: boolean;
uiSettings?: IUiSettingsClient;
isClearable?: boolean;
}

interface DataSourceSelectorState {
Expand Down Expand Up @@ -202,6 +203,7 @@ export class DataSourceSelector extends React.Component<

return (
<EuiComboBox
isClearable={this.props.isClearable}
aria-label={
placeholderText
? i18n.translate('dataSourceSelectorComboBoxAriaLabel', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
* SPDX-License-Identifier: Apache-2.0
*/

export { DataSourceSelector } from './data_source_selector';
export { DataSourceSelector, DataSourceOption } from './data_source_selector';
2 changes: 1 addition & 1 deletion src/plugins/data_source_management/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function plugin() {
}

export { DataSourceManagementPluginStart } from './types';
export { DataSourceSelector } from './components/data_source_selector';
export { DataSourceSelector, DataSourceOption } from './components/data_source_selector';
export { DataSourceMenu } from './components/data_source_menu';
export { DataSourceManagementPlugin, DataSourceManagementPluginSetup } from './plugin';
export {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/vis_type_timeseries/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@

export const MAX_BUCKETS_SETTING = 'metrics:max_buckets';
export const INDEXES_SEPARATOR = ',';
export const DATA_SOURCE_ID_KEY = 'data_source_id';
1 change: 1 addition & 0 deletions src/plugins/vis_type_timeseries/common/vis_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ export const panel = schema.object({
ignore_global_filters: numberOptional,
ignore_global_filter: numberOptional,
index_pattern: stringRequired,
data_source_id: stringOptionalNullable,
interval: stringRequired,
isModelInvalid: schema.maybe(schema.boolean()),
legend_position: stringOptionalNullable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"server": true,
"ui": true,
"requiredPlugins": ["charts", "data", "expressions", "visualizations"],
"optionalPlugins": ["usageCollection"],
"optionalPlugins": ["usageCollection", "dataSourceManagement", "dataSource"],
"requiredBundles": ["opensearchDashboardsUtils", "opensearchDashboardsReact"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
EuiText,
} from '@elastic/eui';
import { FormattedMessage } from '@osd/i18n/react';
import { i18n } from '@osd/i18n';

function newAnnotation() {
return {
Expand Down Expand Up @@ -131,9 +132,13 @@ export class AnnotationsEditor extends Component {
label={
<FormattedMessage
id="visTypeTimeseries.annotationsEditor.indexPatternLabel"
defaultMessage="Index pattern (required)"
defaultMessage="Index name (required)"
bandinib-amzn marked this conversation as resolved.
Show resolved Hide resolved
/>
}
helpText={i18n.translate('visTypeTimeseries.indexPattern.searchByIndex', {
defaultMessage:
'Use an asterisk (*) to match multiple indices. Spaces and the characters , /, ?, ", <, >, | are not allowed.',
})}
fullWidth
>
<EuiFieldText
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ import {
EuiText,
} from '@elastic/eui';
import { FieldSelect } from './aggs/field_select';
import { createDataSourcePickerHandler } from './lib/create_data_source_change_handler';
import {
getSavedObjectsClient,
getNotifications,
getDataSourceManagementSetup,
} from '../../services';
import { createSelectHandler } from './lib/create_select_handler';
import { createTextHandler } from './lib/create_text_handler';
import { YesNo } from './yes_no';
Expand Down Expand Up @@ -112,6 +118,14 @@ export const IndexPattern = ({ fields, prefix, onChange, disabled, model: _model
};

const model = { ...defaults, ..._model };

const dataSourceManagementEnabled =
!!getDataSourceManagementSetup().dataSourceManagement || false;
const handleDataSourceSelectChange = createDataSourcePickerHandler(onChange);
const DataSourceSelector = dataSourceManagementEnabled
? getDataSourceManagementSetup().dataSourceManagement.ui.DataSourceSelector
: undefined;

const isDefaultIndexPatternUsed = model.default_index_pattern && !model[indexPatternName];
const intervalValidation = validateIntervalValue(model[intervalName]);
const selectedTimeRangeOption = timeRangeOptions.find(
Expand Down Expand Up @@ -157,18 +171,47 @@ export const IndexPattern = ({ fields, prefix, onChange, disabled, model: _model
</EuiFlexItem>
</EuiFlexGroup>
)}
{!!dataSourceManagementEnabled && (
<EuiFlexGroup>
<EuiFlexItem>
<EuiFormRow
id={htmlId('dataSource')}
label={i18n.translate('visTypeTimeseries.indexPattern.dataSourceLabel', {
defaultMessage: 'Data source',
})}
>
<DataSourceSelector
savedObjectsClient={getSavedObjectsClient().client}
notifications={getNotifications().toasts}
onSelectedDataSource={handleDataSourceSelectChange}
defaultOption={
model.data_source_id !== undefined ? [{ id: model.data_source_id }] : undefined
}
disabled={false}
fullWidth={false}
removePrepend={true}
isClearable={false}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
)}
<EuiFlexGroup>
<EuiFlexItem>
<EuiFormRow
id={htmlId('indexPattern')}
label={i18n.translate('visTypeTimeseries.indexPatternLabel', {
defaultMessage: 'Index pattern',
defaultMessage: 'Index name',
})}
helpText={
isDefaultIndexPatternUsed &&
i18n.translate('visTypeTimeseries.indexPattern.searchByDefaultIndex', {
defaultMessage: 'Default index pattern is used. To query all indexes use *',
})
isDefaultIndexPatternUsed
? i18n.translate('visTypeTimeseries.indexPattern.searchByDefaultIndex', {
defaultMessage: 'Default index pattern is used. To query all indexes use *',
})
: i18n.translate('visTypeTimeseries.indexPattern.searchByIndex', {
defaultMessage:
'Use an asterisk (*) to match multiple indices. Spaces and the characters , /, ?, ", <, >, | are not allowed.',
})
}
>
<EuiFieldText
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { createDataSourcePickerHandler } from './create_data_source_change_handler';

describe('createDataSourcePickerHandler()', () => {
let handleChange: jest.Mock<any, any>;
let changeHandler: (selectedOptions: []) => void;

beforeEach(() => {
handleChange = jest.fn();
changeHandler = createDataSourcePickerHandler(handleChange);
});

test.each([
{
id: undefined,
},
{},
])(
'calls handleChange() and sets data_source_id to undefined if id cannot be found or is undefined',
({ id }) => {
// @ts-ignore
changeHandler([{ id }]);
expect(handleChange.mock.calls.length).toEqual(1);
expect(handleChange.mock.calls[0][0]).toEqual({
data_source_id: undefined,
});
}
);

test.each([
{
id: '',
},
{
id: 'foo',
},
])('calls handleChange() function with partial and updates the data_source_id', ({ id }) => {
// @ts-ignore
changeHandler([{ id }]);
expect(handleChange.mock.calls.length).toEqual(1);
expect(handleChange.mock.calls[0][0]).toEqual({
data_source_id: id,
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import _ from 'lodash';

import { PanelSchema } from 'src/plugins/vis_type_timeseries/common/types';
import { DATA_SOURCE_ID_KEY } from '../../../../common/constants';

export const createDataSourcePickerHandler = (handleChange: (e: PanelSchema) => void) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a test for this function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test cases.

return (selectedOptions: []): void => {
return handleChange?.({
[DATA_SOURCE_ID_KEY]: _.get(selectedOptions, '[0].id', undefined),
} as PanelSchema);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { createBrushHandler } from '../lib/create_brush_handler';
import { fetchFields } from '../lib/fetch_fields';
import { extractIndexPatterns } from '../../../../../plugins/vis_type_timeseries/common/extract_index_patterns';
import { getSavedObjectsClient, getUISettings, getDataStart, getCoreStart } from '../../services';
import { DATA_SOURCE_ID_KEY } from '../../../common/constants';

import { CoreStartContextProvider } from '../contexts/query_input_bar_context';
import { OpenSearchDashboardsContextProvider } from '../../../../../plugins/opensearch_dashboards_react/public';
Expand Down Expand Up @@ -113,9 +114,13 @@ export class VisEditor extends Component {
}

if (this.props.isEditorMode) {
const dataSourceId = nextModel[DATA_SOURCE_ID_KEY] || undefined;
const extractedIndexPatterns = extractIndexPatterns(nextModel);
if (!isEqual(this.state.extractedIndexPatterns, extractedIndexPatterns)) {
fetchFields(extractedIndexPatterns).then((visFields) =>
if (
!isEqual(this.state.extractedIndexPatterns, extractedIndexPatterns) ||
!isEqual(this.state.model[DATA_SOURCE_ID_KEY], dataSourceId)
) {
fetchFields(extractedIndexPatterns, dataSourceId).then((visFields) =>
this.setState({
visFields,
extractedIndexPatterns,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,18 @@

import { i18n } from '@osd/i18n';
import { extractIndexPatterns } from '../../../common/extract_index_patterns';
import { DATA_SOURCE_ID_KEY } from '../../../common/constants';
import { getCoreStart } from '../../services';

export async function fetchFields(indexPatterns = ['*']) {
export async function fetchFields(indexPatterns = ['*'], dataSourceId = undefined) {
const patterns = Array.isArray(indexPatterns) ? indexPatterns : [indexPatterns];
try {
const indexFields = await Promise.all(
patterns.map((pattern) => {
return getCoreStart().http.get('/api/metrics/fields', {
query: {
index: pattern,
data_source: dataSourceId,
},
});
})
Expand All @@ -62,7 +64,8 @@ export async function fetchFields(indexPatterns = ['*']) {
}

export async function fetchIndexPatternFields({ params, fields = {} }) {
const dataSourceId = params[DATA_SOURCE_ID_KEY] || undefined;
const indexPatterns = extractIndexPatterns(params, fields);

return await fetchFields(indexPatterns);
return await fetchFields(indexPatterns, dataSourceId);
}
16 changes: 15 additions & 1 deletion src/plugins/vis_type_timeseries/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
CoreStart,
Plugin,
} from 'opensearch-dashboards/public';
import { DataSourceManagementPluginSetup } from 'src/plugins/data_source_management/public';
import { DataSourcePluginSetup } from 'src/plugins/data_source/public';
import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public';
import { VisualizationsSetup } from '../../visualizations/public';

Expand All @@ -49,6 +51,8 @@ import {
setCoreStart,
setDataStart,
setChartsSetup,
setDataSourceManagementSetup,
setNotifications,
} from './services';
import { DataPublicPluginStart } from '../../data/public';
import { ChartsPluginSetup } from '../../charts/public';
Expand All @@ -58,6 +62,8 @@ export interface MetricsPluginSetupDependencies {
expressions: ReturnType<ExpressionsPublicPlugin['setup']>;
visualizations: VisualizationsSetup;
charts: ChartsPluginSetup;
dataSourceManagement?: DataSourceManagementPluginSetup;
dataSource?: DataSourcePluginSetup;
}

/** @internal */
Expand All @@ -75,12 +81,19 @@ export class MetricsPlugin implements Plugin<Promise<void>, void> {

public async setup(
core: CoreSetup,
{ expressions, visualizations, charts }: MetricsPluginSetupDependencies
{
expressions,
visualizations,
charts,
dataSourceManagement,
dataSource,
}: MetricsPluginSetupDependencies
) {
expressions.registerFunction(createMetricsFn);
setUISettings(core.uiSettings);
setChartsSetup(charts);
visualizations.createReactVisualization(metricsVisDefinition);
setDataSourceManagementSetup({ dataSourceManagement });
}

public start(core: CoreStart, { data }: MetricsPluginStartDependencies) {
Expand All @@ -89,5 +102,6 @@ export class MetricsPlugin implements Plugin<Promise<void>, void> {
setFieldFormats(data.fieldFormats);
setDataStart(data);
setCoreStart(core);
setNotifications(core.notifications);
}
}
17 changes: 16 additions & 1 deletion src/plugins/vis_type_timeseries/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@
* under the License.
*/

import { I18nStart, SavedObjectsStart, IUiSettingsClient, CoreStart } from 'src/core/public';
import {
I18nStart,
SavedObjectsStart,
IUiSettingsClient,
CoreStart,
NotificationsStart,
} from 'src/core/public';
import { DataSourceManagementPluginSetup } from 'src/plugins/data_source_management/public';
import { createGetterSetter } from '../../opensearch_dashboards_utils/public';
import { ChartsPluginSetup } from '../../charts/public';
import { DataPublicPluginStart } from '../../data/public';
Expand All @@ -52,3 +59,11 @@ export const [getI18n, setI18n] = createGetterSetter<I18nStart>('I18n');
export const [getChartsSetup, setChartsSetup] = createGetterSetter<ChartsPluginSetup>(
'ChartsPluginSetup'
);

export const [getDataSourceManagementSetup, setDataSourceManagementSetup] = createGetterSetter<{
dataSourceManagement: DataSourceManagementPluginSetup | undefined;
}>('DataSourceManagementSetup');

export const [getNotifications, setNotifications] = createGetterSetter<NotificationsStart>(
'Notifications'
);
Loading
Loading