mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tempo: Limit tags and tag values (#98306)
* Limit tags and tag values API response * Add tag limit setting in datasource * Add docs * Update limit options * Update docs
This commit is contained in:
parent
9bdeca8d10
commit
1f19fc8e0f
@ -333,6 +333,10 @@ You can choose one of three options:
|
||||
| **Duration** | _(Default)_ Displays the span duration on the span bar row. |
|
||||
| **Tag** | Displays the span tag on the span bar row. You must also specify which tag key to use to get the tag value, such as `component`. |
|
||||
|
||||
### Tag limit
|
||||
|
||||
The **Tag limit** setting modifies the max number of tags and tag values to retrieve from Tempo. Default: 5000
|
||||
|
||||
### Private data source connect
|
||||
|
||||
[//]: # 'Shared content for authentication section procedure in data sources'
|
||||
|
@ -8,10 +8,11 @@ import { Alert, HorizontalGroup, InputActionMeta, Select, useStyles2 } from '@gr
|
||||
|
||||
import { TraceqlFilter, TraceqlSearchScope } from '../dataquery.gen';
|
||||
import { TempoDatasource } from '../datasource';
|
||||
import { OPTIONS_LIMIT } from '../language_provider';
|
||||
import { TempoQuery } from '../types';
|
||||
|
||||
import InlineSearchField from './InlineSearchField';
|
||||
import { maxOptions, withTemplateVariableOptions } from './SearchField';
|
||||
import { withTemplateVariableOptions } from './SearchField';
|
||||
import { replaceAt } from './utils';
|
||||
|
||||
interface Props {
|
||||
@ -46,11 +47,11 @@ export const GroupByField = (props: Props) => {
|
||||
() => (f: TraceqlFilter) => {
|
||||
const tags = datasource!.languageProvider.getMetricsSummaryTags(f.scope);
|
||||
if (tagQuery.length === 0) {
|
||||
return tags.slice(0, maxOptions);
|
||||
return tags.slice(0, OPTIONS_LIMIT);
|
||||
}
|
||||
|
||||
const queryLowerCase = tagQuery.toLowerCase();
|
||||
return tags.filter((tag) => tag.toLowerCase().includes(queryLowerCase)).slice(0, maxOptions);
|
||||
return tags.filter((tag) => tag.toLowerCase().includes(queryLowerCase)).slice(0, OPTIONS_LIMIT);
|
||||
},
|
||||
[datasource, tagQuery]
|
||||
);
|
||||
|
@ -10,16 +10,11 @@ import { Select, HorizontalGroup, useStyles2, InputActionMeta } from '@grafana/u
|
||||
|
||||
import { TraceqlFilter, TraceqlSearchScope } from '../dataquery.gen';
|
||||
import { TempoDatasource } from '../datasource';
|
||||
import { OPTIONS_LIMIT } from '../language_provider';
|
||||
import { operators as allOperators, stringOperators, numberOperators, keywordOperators } from '../traceql/traceql';
|
||||
|
||||
import { filterScopedTag, operatorSelectableValue } from './utils';
|
||||
|
||||
const getStyles = () => ({
|
||||
dropdown: css({
|
||||
boxShadow: 'none',
|
||||
}),
|
||||
});
|
||||
|
||||
interface Props {
|
||||
filter: TraceqlFilter;
|
||||
datasource: TempoDatasource;
|
||||
@ -119,11 +114,11 @@ const SearchField = ({
|
||||
|
||||
const tagOptions = useMemo(() => {
|
||||
if (tagQuery.length === 0) {
|
||||
return formatTagOptions(tags.slice(0, maxOptions), filter.tag);
|
||||
return formatTagOptions(tags.slice(0, OPTIONS_LIMIT), filter.tag);
|
||||
}
|
||||
|
||||
const queryLowerCase = tagQuery.toLowerCase();
|
||||
const filterdOptions = tags.filter((tag) => tag.toLowerCase().includes(queryLowerCase)).slice(0, maxOptions);
|
||||
const filterdOptions = tags.filter((tag) => tag.toLowerCase().includes(queryLowerCase)).slice(0, OPTIONS_LIMIT);
|
||||
return formatTagOptions(filterdOptions, filter.tag);
|
||||
}, [filter.tag, tagQuery, tags]);
|
||||
|
||||
@ -133,7 +128,7 @@ const SearchField = ({
|
||||
}
|
||||
|
||||
if (tagValuesQuery.length === 0) {
|
||||
return options.slice(0, maxOptions);
|
||||
return options.slice(0, OPTIONS_LIMIT);
|
||||
}
|
||||
|
||||
const queryLowerCase = tagValuesQuery.toLowerCase();
|
||||
@ -144,7 +139,7 @@ const SearchField = ({
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.slice(0, maxOptions);
|
||||
.slice(0, OPTIONS_LIMIT);
|
||||
}, [tagValuesQuery, options]);
|
||||
|
||||
return (
|
||||
@ -239,6 +234,8 @@ const SearchField = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchField;
|
||||
|
||||
/**
|
||||
* Add to a list of options the current template variables.
|
||||
*
|
||||
@ -250,7 +247,8 @@ export const withTemplateVariableOptions = (options: SelectableValue[] | undefin
|
||||
return [...(options || []), ...templateVariables.map((v) => ({ label: `$${v.name}`, value: `$${v.name}` }))];
|
||||
};
|
||||
|
||||
// Limit maximum options in select dropdowns for performance reasons
|
||||
export const maxOptions = 1000;
|
||||
|
||||
export default SearchField;
|
||||
const getStyles = () => ({
|
||||
dropdown: css({
|
||||
boxShadow: 'none',
|
||||
}),
|
||||
});
|
||||
|
@ -3,8 +3,8 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import { DataQuery, SelectableValue } from '@grafana/data';
|
||||
import { InlineField, InlineFieldRow, InputActionMeta, Select } from '@grafana/ui';
|
||||
|
||||
import { maxOptions } from './SearchTraceQLEditor/SearchField';
|
||||
import { TempoDatasource } from './datasource';
|
||||
import { OPTIONS_LIMIT } from './language_provider';
|
||||
|
||||
export enum TempoVariableQueryType {
|
||||
LabelNames,
|
||||
@ -46,7 +46,7 @@ export const TempoVariableQueryEditor = ({ onChange, query, datasource }: TempoV
|
||||
|
||||
const options = useMemo(() => {
|
||||
if (labelQuery.length === 0) {
|
||||
return labelOptions.slice(0, maxOptions);
|
||||
return labelOptions.slice(0, OPTIONS_LIMIT);
|
||||
}
|
||||
|
||||
const queryLowerCase = labelQuery.toLowerCase();
|
||||
@ -57,7 +57,7 @@ export const TempoVariableQueryEditor = ({ onChange, query, datasource }: TempoV
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.slice(0, maxOptions);
|
||||
.slice(0, OPTIONS_LIMIT);
|
||||
}, [labelQuery, labelOptions]);
|
||||
|
||||
const onQueryTypeChange = (newType: SelectableValue<TempoVariableQueryType>) => {
|
||||
|
@ -24,6 +24,7 @@ import { SecureSocksProxySettings, useStyles2, Divider, Stack } from '@grafana/u
|
||||
import { QuerySettings } from './QuerySettings';
|
||||
import { ServiceGraphSettings } from './ServiceGraphSettings';
|
||||
import { StreamingSection } from './StreamingSection';
|
||||
import { TagLimitSection } from './TagLimitSettings';
|
||||
import { TraceQLSearchSettings } from './TraceQLSearchSettings';
|
||||
|
||||
export type ConfigEditorProps = DataSourcePluginOptionsEditorProps;
|
||||
@ -118,6 +119,8 @@ const ConfigEditor = ({ options, onOptionsChange }: ConfigEditorProps) => {
|
||||
</ConfigSubSection>
|
||||
|
||||
<SpanBarSection options={options} onOptionsChange={onOptionsChange} />
|
||||
|
||||
<TagLimitSection options={options} onOptionsChange={onOptionsChange} />
|
||||
</Stack>
|
||||
</ConfigSection>
|
||||
</div>
|
||||
|
@ -0,0 +1,71 @@
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import {
|
||||
DataSourceJsonData,
|
||||
DataSourcePluginOptionsEditorProps,
|
||||
GrafanaTheme2,
|
||||
updateDatasourcePluginJsonDataOption,
|
||||
} from '@grafana/data';
|
||||
import { ConfigDescriptionLink, ConfigSubSection } from '@grafana/experimental';
|
||||
import { InlineField, InlineFieldRow, Input, useStyles2 } from '@grafana/ui';
|
||||
|
||||
export interface TagLimitOptions extends DataSourceJsonData {
|
||||
tagLimit?: number;
|
||||
}
|
||||
|
||||
interface Props extends DataSourcePluginOptionsEditorProps<TagLimitOptions> {}
|
||||
|
||||
export default function TagLimitSettings({ options, onOptionsChange }: Props) {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div className={css({ width: '100%' })}>
|
||||
<InlineFieldRow className={styles.row}>
|
||||
<InlineField
|
||||
label="Max tags and tag values"
|
||||
labelWidth={26}
|
||||
tooltip="Specify the max number of tags and tag values to display in the Tempo editor. Default: 5000"
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="5000"
|
||||
onChange={(v) =>
|
||||
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tagLimit', v.currentTarget.value)
|
||||
}
|
||||
value={options.jsonData.tagLimit || ''}
|
||||
width={40}
|
||||
/>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const TagLimitSection = ({ options, onOptionsChange }: DataSourcePluginOptionsEditorProps) => {
|
||||
return (
|
||||
<ConfigSubSection
|
||||
title="Tag limit"
|
||||
description={
|
||||
<ConfigDescriptionLink
|
||||
description="Specify the limit for tags and tag values."
|
||||
suffix={'/#tag-limit'}
|
||||
feature="the tag limit"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<TagLimitSettings options={options} onOptionsChange={onOptionsChange} />
|
||||
</ConfigSubSection>
|
||||
);
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
infoText: css({
|
||||
label: 'infoText',
|
||||
paddingBottom: theme.spacing(2),
|
||||
color: theme.colors.text.secondary,
|
||||
}),
|
||||
row: css({
|
||||
label: 'row',
|
||||
alignItems: 'baseline',
|
||||
}),
|
||||
});
|
@ -37,6 +37,7 @@ import { BarGaugeDisplayMode, TableCellDisplayMode, VariableFormatID } from '@gr
|
||||
import { generateQueryFromAdHocFilters, getTagWithoutScope, interpolateFilters } from './SearchTraceQLEditor/utils';
|
||||
import { TempoVariableQuery, TempoVariableQueryType } from './VariableQueryEditor';
|
||||
import { PrometheusDatasource, PromQuery } from './_importedDependencies/datasources/prometheus/types';
|
||||
import { TagLimitOptions } from './configuration/TagLimitSettings';
|
||||
import { SearchTableType, TraceqlFilter, TraceqlSearchScope } from './dataquery.gen';
|
||||
import {
|
||||
defaultTableFilter,
|
||||
@ -109,6 +110,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
||||
};
|
||||
uploadedJson?: string | null = null;
|
||||
spanBar?: SpanBarOptions;
|
||||
tagLimit?: TagLimitOptions;
|
||||
languageProvider: TempoLanguageProvider;
|
||||
|
||||
streamingEnabled?: {
|
||||
@ -119,7 +121,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
||||
tempoVersion?: string | null;
|
||||
|
||||
constructor(
|
||||
private instanceSettings: DataSourceInstanceSettings<TempoJsonData>,
|
||||
public instanceSettings: DataSourceInstanceSettings<TempoJsonData>,
|
||||
private readonly templateSrv: TemplateSrv = getTemplateSrv()
|
||||
) {
|
||||
super(instanceSettings);
|
||||
|
@ -14,6 +14,12 @@ import { TempoDatasource } from './datasource';
|
||||
import { intrinsicsV1 } from './traceql/traceql';
|
||||
import { Scope } from './types';
|
||||
|
||||
// Limit maximum tags retrieved from the backend
|
||||
export const TAGS_LIMIT = 5000;
|
||||
|
||||
// Limit maximum options in select dropdowns
|
||||
export const OPTIONS_LIMIT = 1000;
|
||||
|
||||
export default class TempoLanguageProvider extends LanguageProvider {
|
||||
datasource: TempoDatasource;
|
||||
tagsV1?: string[];
|
||||
@ -40,10 +46,14 @@ export default class TempoLanguageProvider extends LanguageProvider {
|
||||
return this.startTask;
|
||||
};
|
||||
|
||||
getTagsLimit = () => {
|
||||
return this.datasource.instanceSettings.jsonData?.tagLimit || TAGS_LIMIT;
|
||||
};
|
||||
|
||||
async fetchTags() {
|
||||
let v1Resp, v2Resp;
|
||||
try {
|
||||
v2Resp = await this.request('/api/v2/search/tags', []);
|
||||
v2Resp = await this.request('/api/v2/search/tags', { limit: this.getTagsLimit() });
|
||||
} catch (error) {
|
||||
v1Resp = await this.request('/api/search/tags', []);
|
||||
}
|
||||
@ -150,7 +160,9 @@ export default class TempoLanguageProvider extends LanguageProvider {
|
||||
const encodedTag = this.encodeTag(tag);
|
||||
const response = await this.request(
|
||||
`/api/v2/search/tag/${encodedTag}/values`,
|
||||
query ? { q: getTemplateSrv().replace(query, {}, VariableFormatID.Pipe) } : {}
|
||||
query
|
||||
? { q: getTemplateSrv().replace(query, {}, VariableFormatID.Pipe), limit: this.getTagsLimit() }
|
||||
: { limit: this.getTagsLimit() }
|
||||
);
|
||||
let options: Array<SelectableValue<string>> = [];
|
||||
if (response && response.tagValues) {
|
||||
|
@ -16,6 +16,7 @@ export interface TempoJsonData extends DataSourceJsonData {
|
||||
spanBar?: {
|
||||
tag: string;
|
||||
};
|
||||
tagLimit?: number;
|
||||
traceQuery?: {
|
||||
timeShiftEnabled?: boolean;
|
||||
spanStartTimeShift?: string;
|
||||
|
Loading…
Reference in New Issue
Block a user