Tempo: Remove traceqlSearch feature toggle (#72029)

* Remove feature flag from registry.go

* Remove usages of toggle

* Refactor and cleanup Tempo's query field components

* Added deprecation alert

* Mark nativeSearch fields as deprecated

* Also show deprecated search tab if queryType is nativeSearch

* Update deprecation message to list grafana version

* Fix merge conflict

* Remove mention of toggle from docs
This commit is contained in:
Andre Pereira 2023-07-24 16:26:10 +01:00 committed by GitHub
parent 7f4d8de6f5
commit bd59a27b99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 130 additions and 138 deletions

View File

@ -4572,11 +4572,11 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"public/app/plugins/datasource/tempo/QueryEditor/QueryField.tsx:5381": [
"public/app/plugins/datasource/tempo/LokiSearch.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/tempo/QueryEditor/ServiceGraphSection.tsx:5381": [
"public/app/plugins/datasource/tempo/ServiceGraphSection.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],

View File

@ -95,7 +95,6 @@ Experimental features might be changed or removed without prior notice.
| `lokiQuerySplittingConfig` | Give users the option to configure split durations for Loki queries |
| `individualCookiePreferences` | Support overriding cookie preferences per user |
| `onlyExternalOrgRoleSync` | Prohibits a user from changing organization roles synced with external auth providers |
| `traceqlSearch` | Enables the 'TraceQL Search' tab for the Tempo datasource which provides a UI to generate TraceQL queries |
| `timeSeriesTable` | Enable time series table transformer & sparkline cell type |
| `prometheusResourceBrowserCache` | Displays browser caching options in Prometheus data source configuration |
| `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy |

View File

@ -16,13 +16,6 @@ labels:
# Create TraceQL queries using Search
{{% admonition type="note" %}}
This new Search query type is available as an experimental feature.
This feature is under active development and is not production ready.
To try this feature, enable the `traceqlSearch` feature flag in Grafana (read [documentation](/docs/grafana/latest/setup-grafana/configure-grafana/feature-toggles/)).
Grafana Cloud users have this feature.
{{% /admonition %}}
Using the Search tab in Explore, you can use the query builders drop-downs to compose TraceQL queries. The selections you make automatically generate a [TraceQL query](/docs/tempo/latest/traceql).
To access **Search**, select your Tempo data source, and then choose **Explore** and select **Query type** > **Search**.

View File

@ -65,7 +65,6 @@ export interface FeatureToggles {
lokiQuerySplittingConfig?: boolean;
individualCookiePreferences?: boolean;
onlyExternalOrgRoleSync?: boolean;
traceqlSearch?: boolean;
prometheusMetricEncyclopedia?: boolean;
timeSeriesTable?: boolean;
prometheusResourceBrowserCache?: boolean;

View File

@ -20,11 +20,11 @@ export interface TempoQuery extends common.DataQuery {
*/
limit?: number;
/**
* Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
* @deprecated Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
*/
maxDuration?: string;
/**
* Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
* @deprecated Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
*/
minDuration?: string;
/**
@ -32,7 +32,7 @@ export interface TempoQuery extends common.DataQuery {
*/
query: string;
/**
* Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
* @deprecated Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
*/
search?: string;
/**
@ -44,11 +44,11 @@ export interface TempoQuery extends common.DataQuery {
*/
serviceMapQuery?: string;
/**
* Query traces by service name
* @deprecated Query traces by service name
*/
serviceName?: string;
/**
* Query traces by span name
* @deprecated Query traces by span name
*/
spanName?: string;
/**

View File

@ -322,13 +322,6 @@ var (
Stage: FeatureStageExperimental,
Owner: grafanaAuthnzSquad,
},
{
Name: "traceqlSearch",
Description: "Enables the 'TraceQL Search' tab for the Tempo datasource which provides a UI to generate TraceQL queries",
Stage: FeatureStageExperimental,
FrontendOnly: true,
Owner: grafanaObservabilityTracesAndProfilingSquad,
},
{
Name: "prometheusMetricEncyclopedia",
Description: "Adds the metrics explorer component to the Prometheus query builder as an option in metric select",

View File

@ -46,7 +46,6 @@ lokiQuerySplitting,GA,@grafana/observability-logs,false,false,false,true
lokiQuerySplittingConfig,experimental,@grafana/observability-logs,false,false,false,true
individualCookiePreferences,experimental,@grafana/backend-platform,false,false,false,false
onlyExternalOrgRoleSync,experimental,@grafana/grafana-authnz-team,false,false,false,false
traceqlSearch,experimental,@grafana/observability-traces-and-profiling,false,false,false,true
prometheusMetricEncyclopedia,GA,@grafana/observability-metrics,false,false,false,true
timeSeriesTable,experimental,@grafana/app-o11y,false,false,false,true
prometheusResourceBrowserCache,experimental,@grafana/observability-metrics,false,false,false,true

1 Name Stage Owner requiresDevMode RequiresLicense RequiresRestart FrontendOnly
46 lokiQuerySplittingConfig experimental @grafana/observability-logs false false false true
47 individualCookiePreferences experimental @grafana/backend-platform false false false false
48 onlyExternalOrgRoleSync experimental @grafana/grafana-authnz-team false false false false
traceqlSearch experimental @grafana/observability-traces-and-profiling false false false true
49 prometheusMetricEncyclopedia GA @grafana/observability-metrics false false false true
50 timeSeriesTable experimental @grafana/app-o11y false false false true
51 prometheusResourceBrowserCache experimental @grafana/observability-metrics false false false true

View File

@ -195,10 +195,6 @@ const (
// Prohibits a user from changing organization roles synced with external auth providers
FlagOnlyExternalOrgRoleSync = "onlyExternalOrgRoleSync"
// FlagTraceqlSearch
// Enables the 'TraceQL Search' tab for the Tempo datasource which provides a UI to generate TraceQL queries
FlagTraceqlSearch = "traceqlSearch"
// FlagPrometheusMetricEncyclopedia
// Adds the metrics explorer component to the Prometheus query builder as an option in metric select
FlagPrometheusMetricEncyclopedia = "prometheusMetricEncyclopedia"

View File

@ -89,10 +89,10 @@ type TempoQuery struct {
// Defines the maximum number of traces that are returned from Tempo
Limit *int64 `json:"limit,omitempty"`
// Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
// @deprecated Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
MaxDuration *string `json:"maxDuration,omitempty"`
// Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
// @deprecated Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
MinDuration *string `json:"minDuration,omitempty"`
// TraceQL query or trace ID
@ -107,7 +107,7 @@ type TempoQuery struct {
// By default, the UI will assign A->Z; however setting meaningful names may be useful.
RefId string `json:"refId"`
// Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
// @deprecated Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
Search *string `json:"search,omitempty"`
// Use service.namespace in addition to service.name to uniquely identify a service.
@ -116,10 +116,10 @@ type TempoQuery struct {
// Filters to be included in a PromQL query to select data for the service graph. Example: {client="app",service="app"}
ServiceMapQuery *string `json:"serviceMapQuery,omitempty"`
// Query traces by service name
// @deprecated Query traces by service name
ServiceName *string `json:"serviceName,omitempty"`
// Query traces by span name
// @deprecated Query traces by span name
SpanName *string `json:"spanName,omitempty"`
// Use the streaming API to get partial results as they are available

View File

@ -0,0 +1,57 @@
import React from 'react';
import useAsync from 'react-use/lib/useAsync';
import { InlineLabel } from '@grafana/ui';
import { LokiQueryField } from '../loki/components/LokiQueryField';
import { LokiDatasource } from '../loki/datasource';
import { LokiQuery } from '../loki/types';
import { TempoQuery } from './types';
import { getDS } from './utils';
interface LokiSearchProps {
logsDatasourceUid?: string;
onChange: (value: LokiQuery) => void;
onRunQuery: () => void;
query: TempoQuery;
}
export function LokiSearch({ logsDatasourceUid, onChange, onRunQuery, query }: LokiSearchProps) {
const dsState = useAsync(() => getDS(logsDatasourceUid), [logsDatasourceUid]);
if (dsState.loading) {
return null;
}
const ds = dsState.value as LokiDatasource;
if (ds) {
return (
<>
<InlineLabel>Tempo uses {ds.name} to find traces.</InlineLabel>
<LokiQueryField
datasource={ds}
onChange={onChange}
onRunQuery={onRunQuery}
query={query.linkedQuery ?? ({ refId: 'linked' } as LokiQuery)}
history={[]}
/>
</>
);
}
if (!logsDatasourceUid) {
return <div className="text-warning">Please set up a Loki search datasource in the datasource settings.</div>;
}
if (logsDatasourceUid && !ds) {
return (
<div className="text-warning">
Loki search datasource is configured but the data source no longer exists. Please configure existing data source
to use the search.
</div>
);
}
return null;
}

View File

@ -107,6 +107,10 @@ const NativeSearch = ({ datasource, query, onChange, onBlur, onRunQuery }: Props
return (
<>
<div className={styles.container}>
<Alert title="Deprecated query type" severity="warning">
This query type has been deprecated and will be removed in Grafana v10.3. Please migrate to another Tempo
query type.
</Alert>
<InlineFieldRow>
<InlineField label="Service Name" labelWidth={14} grow>
<Select

View File

@ -1,16 +0,0 @@
import { DataSourceApi } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
export async function getDS(uid?: string): Promise<DataSourceApi | undefined> {
if (!uid) {
return undefined;
}
const dsSrv = getDataSourceSrv();
try {
return await dsSrv.get(uid);
} catch (error) {
console.error('Failed to load data source', error);
return undefined;
}
}

View File

@ -1,6 +1,5 @@
import { css } from '@emotion/css';
import React from 'react';
import useAsync from 'react-use/lib/useAsync';
import { QueryEditorProps, SelectableValue } from '@grafana/data';
import { config, reportInteraction } from '@grafana/runtime';
@ -10,32 +9,29 @@ import {
HorizontalGroup,
InlineField,
InlineFieldRow,
InlineLabel,
Modal,
RadioButtonGroup,
Themeable2,
withTheme2,
} from '@grafana/ui';
import { LokiQueryField } from '../../loki/components/LokiQueryField';
import { LokiDatasource } from '../../loki/datasource';
import { LokiQuery } from '../../loki/types';
import TraceQLSearch from '../SearchTraceQLEditor/TraceQLSearch';
import { TempoQueryType } from '../dataquery.gen';
import { TempoDatasource } from '../datasource';
import { QueryEditor } from '../traceql/QueryEditor';
import { TempoQuery } from '../types';
import { LokiQuery } from '../loki/types';
import NativeSearch from './NativeSearch';
import { LokiSearch } from './LokiSearch';
import NativeSearch from './NativeSearch/NativeSearch';
import TraceQLSearch from './SearchTraceQLEditor/TraceQLSearch';
import { ServiceGraphSection } from './ServiceGraphSection';
import { getDS } from './utils';
import { TempoQueryType } from './dataquery.gen';
import { TempoDatasource } from './datasource';
import { QueryEditor } from './traceql/QueryEditor';
import { TempoQuery } from './types';
interface Props extends QueryEditorProps<TempoDatasource, TempoQuery>, Themeable2 {}
interface State {
uploadModalOpen: boolean;
}
const DEFAULT_QUERY_TYPE: TempoQueryType = config.featureToggles.traceqlSearch ? 'traceqlSearch' : 'traceql';
const DEFAULT_QUERY_TYPE: TempoQueryType = 'traceqlSearch';
class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
constructor(props: Props) {
@ -88,18 +84,11 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
const graphDatasourceUid = datasource.serviceMap?.datasourceUid;
let queryTypeOptions: Array<SelectableValue<TempoQueryType>> = [
{ value: 'traceqlSearch', label: 'Search' },
{ value: 'traceql', label: 'TraceQL' },
{ value: 'serviceMap', label: 'Service Graph' },
];
if (config.featureToggles.traceqlSearch) {
queryTypeOptions.unshift({ value: 'traceqlSearch', label: 'Search' });
}
if (!config.featureToggles.traceqlSearch && !datasource?.search?.hide) {
queryTypeOptions.unshift({ value: 'nativeSearch', label: 'Search' });
}
if (logsDatasourceUid) {
if (datasource?.search?.hide) {
// Place at beginning as Search if no native search
@ -110,6 +99,18 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
}
}
// Show the deprecated search option if any of the deprecated search fields are set
if (
query.spanName ||
query.serviceName ||
query.search ||
query.maxDuration ||
query.minDuration ||
query.queryType === 'nativeSearch'
) {
queryTypeOptions.unshift({ value: 'nativeSearch', label: '[Deprecated] Search' });
}
return (
<>
<Modal
@ -169,7 +170,7 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
</InlineField>
</InlineFieldRow>
{query.queryType === 'search' && (
<SearchSection
<LokiSearch
logsDatasourceUid={logsDatasourceUid}
query={query}
onRunQuery={this.onRunLinkedQuery}
@ -209,49 +210,4 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
}
}
interface SearchSectionProps {
logsDatasourceUid?: string;
onChange: (value: LokiQuery) => void;
onRunQuery: () => void;
query: TempoQuery;
}
function SearchSection({ logsDatasourceUid, onChange, onRunQuery, query }: SearchSectionProps) {
const dsState = useAsync(() => getDS(logsDatasourceUid), [logsDatasourceUid]);
if (dsState.loading) {
return null;
}
const ds = dsState.value as LokiDatasource;
if (ds) {
return (
<>
<InlineLabel>Tempo uses {ds.name} to find traces.</InlineLabel>
<LokiQueryField
datasource={ds}
onChange={onChange}
onRunQuery={onRunQuery}
query={query.linkedQuery ?? ({ refId: 'linked' } as LokiQuery)}
history={[]}
/>
</>
);
}
if (!logsDatasourceUid) {
return <div className="text-warning">Please set up a Loki search datasource in the datasource settings.</div>;
}
if (logsDatasourceUid && !ds) {
return (
<div className="text-warning">
Loki search datasource is configured but the data source no longer exists. Please configure existing data source
to use the search.
</div>
);
}
return null;
}
export const TempoQueryField = withTheme2(TempoQueryFieldComponent);

View File

@ -5,11 +5,11 @@ import useAsync from 'react-use/lib/useAsync';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, InlineField, InlineFieldRow, useStyles2 } from '@grafana/ui';
import { AdHocFilter } from '../../../../features/variables/adhoc/picker/AdHocFilter';
import { AdHocVariableFilter } from '../../../../features/variables/types';
import { PrometheusDatasource } from '../../prometheus/datasource';
import { TempoQuery } from '../types';
import { AdHocFilter } from '../../../features/variables/adhoc/picker/AdHocFilter';
import { AdHocVariableFilter } from '../../../features/variables/types';
import { PrometheusDatasource } from '../prometheus/datasource';
import { TempoQuery } from './types';
import { getDS } from './utils';
export function ServiceGraphSection({

View File

@ -14,7 +14,6 @@ import { SpanBarSection } from 'app/features/explore/TraceView/components/settin
import { LokiSearchSettings } from './LokiSearchSettings';
import { QuerySettings } from './QuerySettings';
import { SearchSettings } from './SearchSettings';
import { ServiceGraphSettings } from './ServiceGraphSettings';
import { TraceQLSearchSettings } from './TraceQLSearchSettings';
@ -88,11 +87,7 @@ export const ConfigEditor = ({ options, onOptionsChange }: Props) => {
/>
}
>
{config.featureToggles.traceqlSearch ? (
<TraceQLSearchSettings options={options} onOptionsChange={onOptionsChange} />
) : (
<SearchSettings options={options} onOptionsChange={onOptionsChange} />
)}
<TraceQLSearchSettings options={options} onOptionsChange={onOptionsChange} />
</ConfigSubSection>
<Divider hideLine={true} />

View File

@ -28,19 +28,19 @@ composableKinds: DataQuery: {
#TempoQuery: common.DataQuery & {
// TraceQL query or trace ID
query: string
// Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
// @deprecated Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
search?: string
// Query traces by service name
// @deprecated Query traces by service name
serviceName?: string
// Query traces by span name
// @deprecated Query traces by span name
spanName?: string
// Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
// @deprecated Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
minDuration?: string
// Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
// @deprecated Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
maxDuration?: string
// Filters to be included in a PromQL query to select data for the service graph. Example: {client="app",service="app"}
serviceMapQuery?: string
// Use service.namespace in addition to service.name to uniquely identify a service.
// Use service.namespace in addition to service.name to uniquely identify a service.
serviceMapIncludeNamespace?: bool
// Defines the maximum number of traces that are returned from Tempo
limit?: int64

View File

@ -17,11 +17,11 @@ export interface TempoQuery extends common.DataQuery {
*/
limit?: number;
/**
* Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
* @deprecated Define the maximum duration to select traces. Use duration format, for example: 1.2s, 100ms
*/
maxDuration?: string;
/**
* Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
* @deprecated Define the minimum duration to select traces. Use duration format, for example: 1.2s, 100ms
*/
minDuration?: string;
/**
@ -29,7 +29,7 @@ export interface TempoQuery extends common.DataQuery {
*/
query: string;
/**
* Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
* @deprecated Logfmt query to filter traces by their tags. Example: http.status_code=200 error=true
*/
search?: string;
/**
@ -41,11 +41,11 @@ export interface TempoQuery extends common.DataQuery {
*/
serviceMapQuery?: string;
/**
* Query traces by service name
* @deprecated Query traces by service name
*/
serviceName?: string;
/**
* Query traces by span name
* @deprecated Query traces by span name
*/
spanName?: string;
/**

View File

@ -2,7 +2,7 @@ import { DataSourcePlugin, DashboardLoadedEvent } from '@grafana/data';
import { getAppEvents } from '@grafana/runtime';
import CheatSheet from './CheatSheet';
import { TempoQueryField } from './QueryEditor/QueryField';
import { TempoQueryField } from './QueryField';
import { ConfigEditor } from './configuration/ConfigEditor';
import { TempoDatasource } from './datasource';
import { onDashboardLoadedHandler } from './tracking';

View File

@ -1,5 +1,22 @@
import { DataSourceApi } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
export const getErrorMessage = (message: string | undefined, prefix?: string) => {
const err = message ? ` (${message})` : '';
let errPrefix = prefix ? prefix : 'Error';
return `${errPrefix}${err}. Please check the server logs for more details.`;
};
export async function getDS(uid?: string): Promise<DataSourceApi | undefined> {
if (!uid) {
return undefined;
}
const dsSrv = getDataSourceSrv();
try {
return await dsSrv.get(uid);
} catch (error) {
console.error('Failed to load data source', error);
return undefined;
}
}