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

[TSVB] Change the default mode from last value to entire timerange #93608

Merged
merged 33 commits into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d280d71
Make 'enter time range' value as default and add telemetry for 'last …
VladLasitsa Mar 4, 2021
c40435c
Fix telemetry schema
VladLasitsa Mar 4, 2021
e603ba8
Merge branch 'master' into 91506
kibanamachine Mar 5, 2021
1d97f64
Fix test
VladLasitsa Mar 5, 2021
dd4ec9a
Merge branch 'master' into 91506
kibanamachine Mar 9, 2021
aa3e14e
Add possibility count timeseries created from dashboard
VladLasitsa Mar 10, 2021
67b09cd
Merge remote-tracking branch 'upstream/master' into 91506
VladLasitsa Mar 11, 2021
022536d
Fix remark
VladLasitsa Mar 11, 2021
07d57eb
Fix remark
VladLasitsa Mar 11, 2021
9f9673b
Fix problem with time_range_mode
VladLasitsa Mar 11, 2021
74ace14
Merge remote-tracking branch 'upstream/master' into 91506
VladLasitsa Mar 11, 2021
537ec89
Merge branch 'master' into 91506
kibanamachine Mar 11, 2021
aa1fd20
Fix tests
VladLasitsa Mar 12, 2021
7ba6e76
Fix tests
VladLasitsa Mar 12, 2021
e1d2428
Fix tests for markdown and table
VladLasitsa Mar 12, 2021
01a4ef2
Merge branch 'master' into 91506
kibanamachine Mar 15, 2021
cf44f2b
Merge branch 'master' into 91506
kibanamachine Mar 15, 2021
e26f35e
Merge branch 'master' into 91506
kibanamachine Mar 17, 2021
7b09ec5
exclude TSVB which have type as timeseries
VladLasitsa Mar 17, 2021
708fe8b
Add description for field in schema in telemetry
VladLasitsa Mar 18, 2021
744d616
Fix telemetry schema
VladLasitsa Mar 18, 2021
22e5044
Merge branch 'master' into 91506
kibanamachine Mar 18, 2021
1dde0a7
Merge branch 'master' into 91506
kibanamachine Mar 22, 2021
c64d7ff
Merge branch 'master' into 91506
kibanamachine Mar 23, 2021
08a0c7b
Merge remote-tracking branch 'upstream/master' into 91506
VladLasitsa Mar 25, 2021
2726d4e
Fix some remarks
VladLasitsa Mar 25, 2021
b62b757
Added check for hits
VladLasitsa Mar 25, 2021
e98f15f
Merge branch 'master' into 91506
kibanamachine Mar 26, 2021
26b750b
fix CI
alexwizp Mar 26, 2021
1c24005
Merge branch 'master' into 91506
kibanamachine Mar 26, 2021
a39e0ac
fix CI
alexwizp Mar 29, 2021
b0955c7
Merge remote-tracking branch 'upstream/master' into 91506
VladLasitsa Mar 29, 2021
3852f53
Merge remote-tracking branch 'origin/91506' into 91506
VladLasitsa Mar 29, 2021
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
10 changes: 10 additions & 0 deletions src/plugins/telemetry/schema/oss_plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -9321,6 +9321,16 @@
}
}
},
"vis_type_timeseries": {
"properties": {
"timeseries_use_last_value_mode_total": {
"type": "long",
"_meta": {
"description": "Number of TSVB visualizations using \"last value\" as a time range"
}
}
}
},
"vis_type_vega": {
"properties": {
"vega_lib_specs_total": {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/vis_type_timeseries/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"server": true,
"ui": true,
"requiredPlugins": ["charts", "data", "expressions", "visualizations", "visualize"],
"optionalPlugins": ["usageCollection"],
"requiredBundles": ["kibanaUtils", "kibanaReact"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,20 @@ export const IndexPattern = ({
const handleTextChange = createTextHandler(onChange);

const timeRangeOptions = [
{
label: i18n.translate('visTypeTimeseries.indexPattern.timeRange.lastValue', {
defaultMessage: 'Last value',
}),
value: TIME_RANGE_DATA_MODES.LAST_VALUE,
disabled: !isTimerangeModeEnabled(TIME_RANGE_DATA_MODES.LAST_VALUE, uiRestrictions),
},
{
label: i18n.translate('visTypeTimeseries.indexPattern.timeRange.entireTimeRange', {
defaultMessage: 'Entire time range',
}),
value: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE,
disabled: !isTimerangeModeEnabled(TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE, uiRestrictions),
},
{
label: i18n.translate('visTypeTimeseries.indexPattern.timeRange.lastValue', {
defaultMessage: 'Last value',
}),
value: TIME_RANGE_DATA_MODES.LAST_VALUE,
disabled: !isTimerangeModeEnabled(TIME_RANGE_DATA_MODES.LAST_VALUE, uiRestrictions),
},
];

const defaults = {
Expand Down Expand Up @@ -139,6 +139,7 @@ export const IndexPattern = ({
})}
>
<EuiComboBox
data-test-subj="dataTimeRangeMode"
isClearable={false}
placeholder={i18n.translate(
'visTypeTimeseries.indexPattern.timeRange.selectTimeRange',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,13 +321,21 @@ class GaugePanelConfigUi extends Component {
return (
<>
<EuiTabs size="s">
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
<EuiTab
isSelected={selectedTab === 'data'}
onClick={() => this.switchTab('data')}
data-test-subj="gaugeEditorDataBtn"
>
<FormattedMessage
id="visTypeTimeseries.gauge.dataTab.dataButtonLabel"
defaultMessage="Data"
/>
</EuiTab>
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
<EuiTab
isSelected={selectedTab === 'options'}
onClick={() => this.switchTab('options')}
data-test-subj="gaugeEditorPanelOptionsBtn"
>
<FormattedMessage
id="visTypeTimeseries.gauge.optionsTab.panelOptionsButtonLabel"
defaultMessage="Panel options"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ export class MetricPanelConfig extends Component {
return (
<>
<EuiTabs size="s">
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
<EuiTab
isSelected={selectedTab === 'data'}
onClick={() => this.switchTab('data')}
data-test-subj="metricEditorDataBtn"
>
<FormattedMessage
id="visTypeTimeseries.metric.dataTab.dataButtonLabel"
defaultMessage="Data"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,21 @@ export class TablePanelConfig extends Component {
return (
<>
<EuiTabs size="s">
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
<EuiTab
data-test-subj="tableEditorDataBtn"
isSelected={selectedTab === 'data'}
onClick={() => this.switchTab('data')}
>
<FormattedMessage
id="visTypeTimeseries.table.dataTab.columnsButtonLabel"
defaultMessage="Columns"
/>
</EuiTab>
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
<EuiTab
data-test-subj="tableEditorPanelOptionsBtn"
isSelected={selectedTab === 'options'}
onClick={() => this.switchTab('options')}
>
<FormattedMessage
id="visTypeTimeseries.table.optionsTab.panelOptionsButtonLabel"
defaultMessage="Panel options"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,21 @@ export class TopNPanelConfig extends Component {
return (
<>
<EuiTabs size="s">
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
<EuiTab
isSelected={selectedTab === 'data'}
onClick={() => this.switchTab('data')}
data-test-subj="topNEditorDataBtn"
>
<FormattedMessage
id="visTypeTimeseries.topN.dataTab.dataButtonLabel"
defaultMessage="Data"
/>
</EuiTab>
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
<EuiTab
isSelected={selectedTab === 'options'}
onClick={() => this.switchTab('options')}
data-test-subj="topNEditorPanelOptionsBtn"
>
<FormattedMessage
id="visTypeTimeseries.topN.optionsTab.panelOptionsButtonLabel"
defaultMessage="Panel options"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Storage } from '../../../../../plugins/kibana_utils/public';
import { VisEditorVisualization } from './vis_editor_visualization';
import { PanelConfig } from './panel_config';
import { extractIndexPatterns } from '../../../common/extract_index_patterns';
import { TIME_RANGE_DATA_MODES, TIME_RANGE_MODE_KEY } from '../../../common/timerange_data_modes';
import { VisPicker } from './vis_picker';
import { fetchFields, VisFields } from '../lib/fetch_fields';
import { getDataStart, getCoreStart } from '../../services';
Expand Down Expand Up @@ -64,7 +65,16 @@ export class VisEditor extends Component<TimeseriesEditorProps, TimeseriesEditor
this.state = {
autoApply: true,
dirty: false,
model: this.props.vis.params,
model: {
// we should set default value for 'time_range_mode' in model so that when user save visualization
// we set right mode in savedObject
// ternary operator needed because old visualization have 'time_range_mode' as undefined for 'last_value'
// but for creating new visaulization we should use 'entire_timerange' as default.
[TIME_RANGE_MODE_KEY]: this.props.vis.title
? TIME_RANGE_DATA_MODES.LAST_VALUE
: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE,
...this.props.vis.params,
},
extractedIndexPatterns: [''],
};

Expand Down
6 changes: 6 additions & 0 deletions src/plugins/vis_type_timeseries/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {
} from './lib/search_strategies';
import { TimeseriesVisData, VisPayload } from '../common/types';

import { registerTimeseriesUsageCollector } from './usage_collector';

export interface LegacySetup {
server: Server;
}
Expand Down Expand Up @@ -117,6 +119,10 @@ export class VisTypeTimeseriesPlugin implements Plugin<VisTypeTimeseriesSetup> {
visDataRoutes(router, framework);
fieldsRoutes(router, framework);

if (plugins.usageCollection) {
registerTimeseriesUsageCollector(plugins.usageCollection, globalConfig$);
}

return {
getVisData: async (
requestContext: VisTypeTimeseriesRequestHandlerContext,
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/vis_type_timeseries/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Side Public License, v 1.
*/

import { Observable } from 'rxjs';
import { SharedGlobalConfig } from 'kibana/server';
import type { IRouter, IUiSettingsClient, KibanaRequest } from 'src/core/server';
import type {
DataRequestHandlerContext,
Expand All @@ -15,6 +17,8 @@ import type {
import { VisPayload } from '../common/types';
import { SearchStrategyRegistry } from './lib/search_strategies';

export type ConfigObservable = Observable<SharedGlobalConfig>;

export type VisTypeTimeseriesRequestHandlerContext = DataRequestHandlerContext;
export type VisTypeTimeseriesRouter = IRouter<VisTypeTimeseriesRequestHandlerContext>;
export type VisTypeTimeseriesVisDataRequest = KibanaRequest<{}, {}, VisPayload>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export const mockStats = { somestat: 1 };
export const mockGetStats = jest.fn().mockResolvedValue(mockStats);

jest.doMock('./get_usage_collector', () => ({
getStats: mockGetStats,
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { getStats } from './get_usage_collector';
import { createCollectorFetchContextMock } from 'src/plugins/usage_collection/server/mocks';
import { TIME_RANGE_DATA_MODES } from '../../common/timerange_data_modes';

const mockedSavedObjects = [
{
_id: 'visualization:timeseries-123',
_source: {
type: 'visualization',
visualization: {
visState: JSON.stringify({
type: 'metrics',
title: 'TSVB visualization 1',
params: {
time_range_mode: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE,
},
}),
},
},
},
{
_id: 'visualization:timeseries-321',
_source: {
type: 'visualization',
visualization: {
visState: JSON.stringify({
type: 'metrics',
title: 'TSVB visualization 2',
params: {
time_range_mode: TIME_RANGE_DATA_MODES.LAST_VALUE,
},
}),
},
},
},
{
_id: 'visualization:timeseries-456',
_source: {
type: 'visualization',
visualization: {
visState: JSON.stringify({
type: 'metrics',
title: 'TSVB visualization 3',
params: {
time_range_mode: undefined,
},
}),
},
},
},
];

const mockedSavedObjectsByValue = [
{
attributes: {
panelsJSON: JSON.stringify({
type: 'visualization',
embeddableConfig: {
savedVis: {
type: 'metrics',
params: {
time_range_mode: TIME_RANGE_DATA_MODES.LAST_VALUE,
},
},
},
}),
},
},
{
attributes: {
panelsJSON: JSON.stringify({
type: 'visualization',
embeddableConfig: {
savedVis: {
type: 'metrics',
params: {
time_range_mode: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE,
},
},
},
}),
},
},
];

const getMockCollectorFetchContext = (hits?: unknown[], savedObjectsByValue: unknown[] = []) => {
const fetchParamsMock = createCollectorFetchContextMock();

fetchParamsMock.esClient.search = jest.fn().mockResolvedValue({ body: { hits: { hits } } });
fetchParamsMock.soClient.find = jest.fn().mockResolvedValue({
saved_objects: savedObjectsByValue,
});
return fetchParamsMock;
};

describe('Timeseries visualization usage collector', () => {
const mockIndex = 'mock_index';

test('Returns undefined when no results found (undefined)', async () => {
const mockCollectorFetchContext = getMockCollectorFetchContext([], []);
const result = await getStats(
mockCollectorFetchContext.esClient,
mockCollectorFetchContext.soClient,
mockIndex
);

expect(result).toBeUndefined();
});

test('Returns undefined when no timeseries saved objects found', async () => {
const mockCollectorFetchContext = getMockCollectorFetchContext(
[
{
_id: 'visualization:myvis-123',
_source: {
type: 'visualization',
visualization: { visState: '{"type": "area"}' },
},
},
],
[
{
attributes: {
panelsJSON: JSON.stringify({
type: 'visualization',
embeddableConfig: {
savedVis: {
type: 'area',
},
},
}),
},
},
]
);
const result = await getStats(
mockCollectorFetchContext.esClient,
mockCollectorFetchContext.soClient,
mockIndex
);

expect(result).toBeUndefined();
});

test('Summarizes visualizations response data', async () => {
const mockCollectorFetchContext = getMockCollectorFetchContext(
mockedSavedObjects,
mockedSavedObjectsByValue
);
const result = await getStats(
mockCollectorFetchContext.esClient,
mockCollectorFetchContext.soClient,
mockIndex
);

expect(result).toMatchObject({
timeseries_use_last_value_mode_total: 3,
});
});
});
Loading