Skip to content

Commit

Permalink
KQL support in filter ratio in TSVB
Browse files Browse the repository at this point in the history
  • Loading branch information
DianaDerevyankina committed Aug 14, 2020
1 parent 7bd014a commit 33cc09e
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 16 deletions.
14 changes: 12 additions & 2 deletions src/plugins/vis_type_timeseries/common/vis_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,18 @@ export const metricsItems = schema.object({
field: stringOptionalNullable,
id: stringRequired,
metric_agg: stringOptionalNullable,
numerator: stringOptionalNullable,
denominator: stringOptionalNullable,
numerator: schema.maybe(
schema.object({
language: schema.string(),
query: schema.string(),
})
),
denominator: schema.maybe(
schema.object({
language: schema.string(),
query: schema.string(),
})
),
sigma: stringOptionalNullable,
unit: stringOptionalNullable,
model_type: stringOptionalNullable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ import { FieldSelect } from './field_select';
import { AggRow } from './agg_row';
import { createChangeHandler } from '../lib/create_change_handler';
import { createSelectHandler } from '../lib/create_select_handler';
import { createTextHandler } from '../lib/create_text_handler';
import {
htmlIdGenerator,
EuiFlexGroup,
EuiFlexItem,
EuiFormLabel,
EuiFieldText,
EuiSpacer,
EuiFormRow,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public';
import { getSupportedFieldsByMetricType } from '../lib/get_supported_fields_by_metric_type';
import { getDefaultQueryLanguage } from '../lib/get_default_query_language';
import { QueryBarWrapper } from '../query_bar_wrapper';

const isFieldHistogram = (fields, indexPattern, field) => {
const indexFields = fields[indexPattern];
Expand All @@ -51,13 +51,13 @@ export const FilterRatioAgg = (props) => {

const handleChange = createChangeHandler(props.onChange, props.model);
const handleSelectChange = createSelectHandler(handleChange);
const handleTextChange = createTextHandler(handleChange);
const handleQueryChange = (name, value) => handleChange?.({ [name]: value });
const indexPattern =
(series.override_index_pattern && series.series_index_pattern) || panel.index_pattern;

const defaults = {
numerator: '*',
denominator: '*',
numerator: { query: '', language: getDefaultQueryLanguage() },
denominator: { query: '', language: getDefaultQueryLanguage() },
metric_agg: 'count',
};

Expand Down Expand Up @@ -101,7 +101,14 @@ export const FilterRatioAgg = (props) => {
/>
}
>
<EuiFieldText onChange={handleTextChange('numerator')} value={model.numerator} />
<QueryBarWrapper
query={{
language: model.numerator.language || getDefaultQueryLanguage(),
query: model.numerator.query || '',
}}
onChange={(query) => handleQueryChange('numerator', query)}
indexPatterns={[indexPattern]}
/>
</EuiFormRow>
</EuiFlexItem>

Expand All @@ -115,7 +122,14 @@ export const FilterRatioAgg = (props) => {
/>
}
>
<EuiFieldText onChange={handleTextChange('denominator')} value={model.denominator} />
<QueryBarWrapper
query={{
language: model.denominator.language || getDefaultQueryLanguage(),
query: model.denominator.query || '',
}}
onChange={(query) => handleQueryChange('denominator', query)}
indexPatterns={[indexPattern]}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,23 @@
const filter = (metric) => metric.type === 'filter_ratio';
import { bucketTransform } from '../../helpers/bucket_transform';
import { overwrite } from '../../helpers';
import { esQuery } from '../../../../../../data/server';

export function ratios(req, panel, series) {
export function ratios(req, panel, series, esQueryConfig, indexPatternObject) {
return (next) => (doc) => {
const filters = !panel.ignore_global_filter ? req.payload.filters : [];
if (series.metrics.some(filter)) {
series.metrics.filter(filter).forEach((metric) => {
overwrite(doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-numerator.filter`, {
query_string: { query: metric.numerator || '*', analyze_wildcard: true },
});
overwrite(doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-denominator.filter`, {
query_string: { query: metric.denominator || '*', analyze_wildcard: true },
});
overwrite(
doc,
`aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-numerator.filter`,
esQuery.buildEsQuery(indexPatternObject, metric.numerator, filters, esQueryConfig)
);
overwrite(
doc,
`aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-denominator.filter`,
esQuery.buildEsQuery(indexPatternObject, metric.denominator, filters, esQueryConfig)
);

let numeratorPath = `${metric.id}-numerator>_count`;
let denominatorPath = `${metric.id}-denominator>_count`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1544,4 +1544,38 @@ describe('migration visualization', () => {
expect(series[0].split_color_mode).toBeUndefined();
});
});

describe('7.10.0 tsvb filter_ratio migration', () => {
const migrate = (doc: any) =>
visualizationSavedObjectTypeMigrations['7.10.0'](
doc as Parameters<SavedObjectMigrationFn>[0],
savedObjectMigrationContext
);

const testDoc1 = {
attributes: {
title: 'My Vis',
description: 'This is my super cool vis.',
visState: `{"type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries",
"series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417",
"type":"filter_ratio","numerator":"Filter Bytes Test:>1000","denominator":"Filter Bytes Test:<1000"}]}]}}`,
},
};

it('should replace numerator string with a query object', () => {
const migratedTestDoc1 = migrate(testDoc1);
const metric = JSON.parse(migratedTestDoc1.attributes.visState).params.series[0].metrics[0];

expect(metric.numerator).toHaveProperty('query');
expect(metric.numerator).toHaveProperty('language');
});

it('should replace denominator string with a query object', () => {
const migratedTestDoc1 = migrate(testDoc1);
const metric = JSON.parse(migratedTestDoc1.attributes.visState).params.series[0].metrics[0];

expect(metric.denominator).toHaveProperty('query');
expect(metric.denominator).toHaveProperty('language');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,45 @@ const migratePercentileRankAggregation: SavedObjectMigrationFn<any, any> = (doc)
return doc;
};

// [TSVB] Replace string query with object
const migrateFilterRatioQuery: SavedObjectMigrationFn<any, any> = (doc) => {
const visStateJSON = get(doc, 'attributes.visState');
let visState;

if (visStateJSON) {
try {
visState = JSON.parse(visStateJSON);
} catch (e) {
// Let it go, the data is invalid and we'll leave it as is
}
if (visState && visState.type === 'metrics') {
const series: any[] = get(visState, 'params.series') || [];

series.forEach((part) => {
(part.metrics || []).forEach((metric: any) => {
if (metric.type === 'filter_ratio') {
if (metric.numerator && typeof metric.numerator === 'string') {
metric.numerator = { query: metric.numerator, language: 'lucene' };
}
if (metric.denominator && typeof metric.denominator === 'string') {
metric.denominator = { query: metric.denominator, language: 'lucene' };
}
}
});
});

return {
...doc,
attributes: {
...doc.attributes,
visState: JSON.stringify(visState),
},
};
}
}
return doc;
};

// [TSVB] Remove stale opperator key
const migrateOperatorKeyTypo: SavedObjectMigrationFn<any, any> = (doc) => {
const visStateJSON = get(doc, 'attributes.visState');
Expand Down Expand Up @@ -713,4 +752,5 @@ export const visualizationSavedObjectTypeMigrations = {
'7.4.2': flow(transformSplitFiltersStringToQueryObject),
'7.7.0': flow(migrateOperatorKeyTypo, migrateSplitByChartRow),
'7.8.0': flow(migrateTsvbDefaultColorPalettes),
'7.10.0': flow(migrateFilterRatioQuery),
};

0 comments on commit 33cc09e

Please sign in to comment.