mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Add support for HDR percentiles in TSVB visualizations (#78306)
* Add support for HDR percentiles in TSVB visualizations Closes: #64238 * remove extra console.log * fix CI * fix PR comments * fix layout * remove legacy injectI18n * fix localization issues Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
a8c080be28
commit
59d83e6955
12 changed files with 254 additions and 156 deletions
|
@ -104,6 +104,7 @@ export const metricsItems = schema.object({
|
|||
})
|
||||
)
|
||||
),
|
||||
numberOfSignificantValueDigits: numberOptional,
|
||||
percentiles: schema.maybe(
|
||||
schema.arrayOf(
|
||||
schema.object({
|
||||
|
|
|
@ -24,10 +24,11 @@ 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 { createNumberHandler } from '../lib/create_number_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiSpacer,
|
||||
EuiFlexGroup,
|
||||
EuiFlexGrid,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiFormRow,
|
||||
|
@ -35,6 +36,7 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public';
|
||||
import { Percentiles, newPercentile } from './percentile_ui';
|
||||
import { PercentileHdr } from './percentile_hdr';
|
||||
|
||||
const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM];
|
||||
|
||||
|
@ -46,6 +48,8 @@ export function PercentileAgg(props) {
|
|||
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
const handleNumberChange = createNumberHandler(handleChange);
|
||||
|
||||
const indexPattern =
|
||||
(series.override_index_pattern && series.series_index_pattern) || panel.index_pattern;
|
||||
|
||||
|
@ -66,7 +70,7 @@ export function PercentileAgg(props) {
|
|||
siblings={props.siblings}
|
||||
dragHandleProps={props.dragHandleProps}
|
||||
>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexGrid gutterSize="s" columns={2}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
|
@ -103,11 +107,25 @@ export function PercentileAgg(props) {
|
|||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<Percentiles onChange={handleChange} name="percentiles" model={model} panel={panel} />
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.percents"
|
||||
defaultMessage="Percents"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Percentiles onChange={handleChange} name="percentiles" model={model} panel={panel} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<PercentileHdr
|
||||
value={model.numberOfSignificantValueDigits}
|
||||
onChange={handleNumberChange('numberOfSignificantValueDigits')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGrid>
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiFieldNumber, EuiFormRow, EuiIconTip } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export interface PercentileHdrProps {
|
||||
value: number | undefined;
|
||||
onChange: () => void;
|
||||
}
|
||||
|
||||
export const PercentileHdr = ({ value, onChange }: PercentileHdrProps) => (
|
||||
<EuiFormRow
|
||||
label={
|
||||
<>
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentileHdr.numberOfSignificantValueDigits"
|
||||
defaultMessage="Number of significant value digits (HDR histogram)"
|
||||
/>{' '}
|
||||
<EuiIconTip
|
||||
position="right"
|
||||
content={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentileHdr.numberOfSignificantValueDigits.hint"
|
||||
defaultMessage="HDR Histogram (High Dynamic Range Histogram) is an alternative implementation that can be useful when calculating percentile ranks for latency measurements as it can be faster than the t-digest implementation with the trade-off of a larger memory footprint. Number of significant value digits parameter specifies the resolution of values for the histogram in number of significant digits"
|
||||
/>
|
||||
}
|
||||
type="questionInCircle"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber min={1} value={value || ''} onChange={onChange} />
|
||||
</EuiFormRow>
|
||||
);
|
|
@ -18,15 +18,8 @@
|
|||
*/
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { get } from 'lodash';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFieldNumber,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
|
||||
|
||||
import { AddDeleteButtons } from '../../add_delete_buttons';
|
||||
|
||||
|
@ -50,8 +43,6 @@ export const MultiValueRow = ({
|
|||
disableAdd,
|
||||
disableDelete,
|
||||
}: MultiValueRowProps) => {
|
||||
const htmlId = htmlIdGenerator();
|
||||
|
||||
const onFieldNumberChange = (event: ChangeEvent<HTMLInputElement>) =>
|
||||
onChange({
|
||||
...model,
|
||||
|
@ -59,17 +50,9 @@ export const MultiValueRow = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<div className="tvbAggRow__multiValueRow">
|
||||
<EuiFlexGroup responsive={false} alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel htmlFor={htmlId('value')}>
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.multivalueRow.valueLabel"
|
||||
defaultMessage="Value:"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiPanel paddingSize="s" className="tvbAggRow__multiValueRow">
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFieldNumber
|
||||
value={model.value === '' ? '' : Number(model.value)}
|
||||
placeholder="0"
|
||||
|
@ -82,11 +65,11 @@ export const MultiValueRow = ({
|
|||
onDelete={() => onDelete(model)}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
</div>
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiFormRow,
|
||||
EuiSpacer,
|
||||
EuiFlexGrid,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { AggSelect } from '../agg_select';
|
||||
|
@ -34,12 +34,16 @@ import { FieldSelect } from '../field_select';
|
|||
import { createChangeHandler } from '../../lib/create_change_handler';
|
||||
// @ts-ignore
|
||||
import { createSelectHandler } from '../../lib/create_select_handler';
|
||||
// @ts-ignore
|
||||
import { createNumberHandler } from '../../lib/create_number_handler';
|
||||
|
||||
import { AggRow } from '../agg_row';
|
||||
import { PercentileRankValues } from './percentile_rank_values';
|
||||
|
||||
import { IFieldType, KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
|
||||
import { MetricsItemsSchema, PanelSchema, SeriesItemsSchema } from '../../../../../common/types';
|
||||
import { DragHandleProps } from '../../../../types';
|
||||
import { PercentileHdr } from '../percentile_hdr';
|
||||
|
||||
const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM];
|
||||
|
||||
|
@ -67,6 +71,7 @@ export const PercentileRankAgg = (props: PercentileRankAggProps) => {
|
|||
const isTablePanel = panel.type === 'table';
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
const handleNumberChange = createNumberHandler(handleChange);
|
||||
|
||||
const handlePercentileRankValuesChange = (values: MetricsItemsSchema['values']) => {
|
||||
handleChange({
|
||||
|
@ -84,7 +89,7 @@ export const PercentileRankAgg = (props: PercentileRankAggProps) => {
|
|||
siblings={props.siblings}
|
||||
dragHandleProps={props.dragHandleProps}
|
||||
>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexGrid gutterSize="s" columns={2}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
|
@ -121,17 +126,32 @@ export const PercentileRankAgg = (props: PercentileRankAggProps) => {
|
|||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
{model.values && (
|
||||
<PercentileRankValues
|
||||
disableAdd={isTablePanel}
|
||||
disableDelete={isTablePanel}
|
||||
showOnlyLastRow={isTablePanel}
|
||||
model={model.values}
|
||||
onChange={handlePercentileRankValuesChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentileRank.values"
|
||||
defaultMessage="Values"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<PercentileRankValues
|
||||
disableAdd={isTablePanel}
|
||||
disableDelete={isTablePanel}
|
||||
showOnlyLastRow={isTablePanel}
|
||||
model={model.values!}
|
||||
onChange={handlePercentileRankValuesChange}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<PercentileHdr
|
||||
value={model.numberOfSignificantValueDigits}
|
||||
onChange={handleNumberChange('numberOfSignificantValueDigits')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGrid>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import React from 'react';
|
||||
import { last } from 'lodash';
|
||||
|
||||
import { EuiFlexGroup } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { MultiValueRow } from './multi_value_row';
|
||||
|
||||
interface PercentileRankValuesProps {
|
||||
|
@ -52,19 +52,20 @@ export const PercentileRankValues = (props: PercentileRankValuesProps) => {
|
|||
disableDeleteRow: boolean;
|
||||
disableAddRow: boolean;
|
||||
}) => (
|
||||
<MultiValueRow
|
||||
key={`percentileRankValue__item${rowModel.id}`}
|
||||
onAdd={onAddValue}
|
||||
onChange={onChangeValue}
|
||||
onDelete={onDeleteValue}
|
||||
disableDelete={disableDeleteRow}
|
||||
disableAdd={disableAddRow}
|
||||
model={rowModel}
|
||||
/>
|
||||
<EuiFlexItem key={`percentileRankValue__item${rowModel.id}`}>
|
||||
<MultiValueRow
|
||||
onAdd={onAddValue}
|
||||
onChange={onChangeValue}
|
||||
onDelete={onDeleteValue}
|
||||
disableDelete={disableDeleteRow}
|
||||
disableAdd={disableAddRow}
|
||||
model={rowModel}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="column" responsive={false} gutterSize="xs">
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
{showOnlyLastRow &&
|
||||
renderRow({
|
||||
rowModel: {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import _ from 'lodash';
|
||||
import { collectionActions } from '../lib/collection_actions';
|
||||
import { AddDeleteButtons } from '../add_delete_buttons';
|
||||
|
@ -27,17 +28,19 @@ import {
|
|||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiFieldNumber,
|
||||
EuiFormRow,
|
||||
EuiFlexGrid,
|
||||
EuiPanel,
|
||||
} from '@elastic/eui';
|
||||
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const newPercentile = (opts) => {
|
||||
return _.assign({ id: uuid.v1(), mode: 'line', shade: 0.2 }, opts);
|
||||
};
|
||||
|
||||
class PercentilesUi extends Component {
|
||||
export class Percentiles extends Component {
|
||||
handleTextChange(item, name) {
|
||||
return (e) => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
|
@ -50,22 +53,31 @@ class PercentilesUi extends Component {
|
|||
renderRow = (row, i, items) => {
|
||||
const defaults = { value: '', percentile: '', shade: '' };
|
||||
const model = { ...defaults, ...row };
|
||||
const { intl, panel } = this.props;
|
||||
const { panel } = this.props;
|
||||
const flexItemStyle = { minWidth: 100 };
|
||||
|
||||
const percentileFieldNumber = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFieldNumber
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'visTypeTimeseries.percentile.percentileAriaLabel',
|
||||
defaultMessage: 'Percentile',
|
||||
})}
|
||||
placeholder={0}
|
||||
max={100}
|
||||
min={0}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'value')}
|
||||
value={model.value === '' ? '' : Number(model.value)}
|
||||
/>
|
||||
<EuiFlexItem style={flexItemStyle}>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.percentile"
|
||||
defaultMessage="Percentile"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
aria-label={i18n.translate('visTypeTimeseries.percentile.percentileAriaLabel', {
|
||||
defaultMessage: 'Percentile',
|
||||
})}
|
||||
placeholder={0}
|
||||
max={100}
|
||||
min={0}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'value')}
|
||||
value={model.value === '' ? '' : Number(model.value)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
|
@ -77,99 +89,103 @@ class PercentilesUi extends Component {
|
|||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
|
||||
const modeOptions = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'visTypeTimeseries.percentile.modeOptions.lineLabel',
|
||||
label: i18n.translate('visTypeTimeseries.percentile.modeOptions.lineLabel', {
|
||||
defaultMessage: 'Line',
|
||||
}),
|
||||
value: 'line',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'visTypeTimeseries.percentile.modeOptions.bandLabel',
|
||||
label: i18n.translate('visTypeTimeseries.percentile.modeOptions.bandLabel', {
|
||||
defaultMessage: 'Band',
|
||||
}),
|
||||
value: 'band',
|
||||
},
|
||||
];
|
||||
const optionsStyle = {};
|
||||
const optionsStyle = {
|
||||
...flexItemStyle,
|
||||
};
|
||||
if (model.mode === 'line') {
|
||||
optionsStyle.display = 'none';
|
||||
}
|
||||
const labelStyle = { marginBottom: 0 };
|
||||
|
||||
const htmlId = htmlIdGenerator(model.id);
|
||||
const selectedModeOption = modeOptions.find((option) => {
|
||||
return model.mode === option.value;
|
||||
});
|
||||
return (
|
||||
<EuiFlexItem key={model.id}>
|
||||
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
|
||||
{percentileFieldNumber}
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('mode')}>
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.modeLabel"
|
||||
defaultMessage="Mode:"
|
||||
<EuiPanel>
|
||||
<EuiFlexGroup key={model.id} alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGrid columns={2}>
|
||||
{percentileFieldNumber}
|
||||
<EuiFlexItem style={flexItemStyle}>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.modeLabel"
|
||||
defaultMessage="Mode:"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={this.handleTextChange(model, 'mode')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle}>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.fillToLabel"
|
||||
defaultMessage="Fill to:"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('fillTo')}
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'percentile')}
|
||||
value={Number(model.percentile)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle}>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.shadeLabel"
|
||||
defaultMessage="Shade (0 to 1):"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('shade')}
|
||||
step={0.1}
|
||||
onChange={this.handleTextChange(model, 'shade')}
|
||||
value={Number(model.shade)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGrid>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={this.handleTextChange(model, 'mode')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('fillTo')}>
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.fillToLabel"
|
||||
defaultMessage="Fill to:"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('fillTo')}
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'percentile')}
|
||||
value={Number(model.percentile)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('shade')}>
|
||||
<FormattedMessage
|
||||
id="visTypeTimeseries.percentile.shadeLabel"
|
||||
defaultMessage="Shade (0 to 1):"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('shade')}
|
||||
style={optionsStyle}
|
||||
step={0.1}
|
||||
onChange={this.handleTextChange(model, 'shade')}
|
||||
value={Number(model.shade)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
};
|
||||
|
@ -192,15 +208,13 @@ class PercentilesUi extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
PercentilesUi.defaultProps = {
|
||||
Percentiles.defaultProps = {
|
||||
name: 'percentile',
|
||||
};
|
||||
|
||||
PercentilesUi.propTypes = {
|
||||
Percentiles.propTypes = {
|
||||
name: PropTypes.string,
|
||||
model: PropTypes.object,
|
||||
panel: PropTypes.object,
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
||||
export const Percentiles = injectI18n(PercentilesUi);
|
||||
|
|
|
@ -43,7 +43,6 @@ export async function getSeriesData(req, panel) {
|
|||
(acc, items) => acc.concat(items),
|
||||
[]
|
||||
);
|
||||
|
||||
const data = await searchStrategy.search(req, searches);
|
||||
|
||||
const handleResponseBodyFn = handleResponseBody(panel);
|
||||
|
|
|
@ -64,6 +64,16 @@ function extendStatsBucket(bucket, metrics) {
|
|||
return body;
|
||||
}
|
||||
|
||||
function getPercentileHdrParam(bucket) {
|
||||
return bucket.numberOfSignificantValueDigits
|
||||
? {
|
||||
hdr: {
|
||||
number_of_significant_value_digits: bucket.numberOfSignificantValueDigits,
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export const bucketTransform = {
|
||||
count: () => {
|
||||
return {
|
||||
|
@ -139,13 +149,14 @@ export const bucketTransform = {
|
|||
bucket.percentiles.filter((p) => p.percentile).map((p) => p.percentile)
|
||||
);
|
||||
}
|
||||
const agg = {
|
||||
|
||||
return {
|
||||
percentiles: {
|
||||
field: bucket.field,
|
||||
percents,
|
||||
...getPercentileHdrParam(bucket),
|
||||
},
|
||||
};
|
||||
return agg;
|
||||
},
|
||||
|
||||
percentile_rank: (bucket) => {
|
||||
|
@ -155,6 +166,7 @@ export const bucketTransform = {
|
|||
percentile_ranks: {
|
||||
field: bucket.field,
|
||||
values: (bucket.values || []).map((value) => (isEmpty(value) ? 0 : value)),
|
||||
...getPercentileHdrParam(bucket),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
@ -32,7 +32,7 @@ export function percentileRank(resp, panel, series, meta) {
|
|||
}
|
||||
|
||||
getSplits(resp, panel, series, meta).forEach((split) => {
|
||||
(metric.values || []).forEach((percentileRank) => {
|
||||
(metric.values || []).forEach((percentileRank, index) => {
|
||||
const data = split.timeseries.buckets.map((bucket) => [
|
||||
bucket.key,
|
||||
getAggValue(bucket, {
|
||||
|
@ -43,7 +43,7 @@ export function percentileRank(resp, panel, series, meta) {
|
|||
|
||||
results.push({
|
||||
data,
|
||||
id: `${split.id}:${percentileRank}`,
|
||||
id: `${split.id}:${percentileRank}:${index}`,
|
||||
label: `${split.label} (${percentileRank || 0})`,
|
||||
color: split.color,
|
||||
...getDefaultDecoration(series),
|
||||
|
|
|
@ -3817,7 +3817,6 @@
|
|||
"visTypeTimeseries.movingAverage.period": "期間",
|
||||
"visTypeTimeseries.movingAverage.windowSizeHint": "ウィンドウは、必ず、期間のサイズの 2 倍以上でなければなりません",
|
||||
"visTypeTimeseries.movingAverage.windowSizeLabel": "ウィンドウサイズ",
|
||||
"visTypeTimeseries.multivalueRow.valueLabel": "値:",
|
||||
"visTypeTimeseries.noButtonLabel": "いいえ",
|
||||
"visTypeTimeseries.noDataDescription": "選択されたメトリックに表示するデータがありません",
|
||||
"visTypeTimeseries.percentile.aggregationLabel": "集約",
|
||||
|
|
|
@ -3818,7 +3818,6 @@
|
|||
"visTypeTimeseries.movingAverage.period": "期间",
|
||||
"visTypeTimeseries.movingAverage.windowSizeHint": "窗口必须始终至少是期间大小的两倍",
|
||||
"visTypeTimeseries.movingAverage.windowSizeLabel": "窗口大小",
|
||||
"visTypeTimeseries.multivalueRow.valueLabel": "值:",
|
||||
"visTypeTimeseries.noButtonLabel": "否",
|
||||
"visTypeTimeseries.noDataDescription": "所选指标没有可显示的数据",
|
||||
"visTypeTimeseries.percentile.aggregationLabel": "聚合",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue