Tempo: Copy trace query to TraceQL tab (#79935)

* Copy trace query to TraceQL tab

* Remove datasourceType

* Update button position

* Update test

* Remove extra check

* Update text
This commit is contained in:
Joey 2024-01-04 16:10:09 +00:00 committed by GitHub
parent e508c83538
commit ef6b35ad3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 13 deletions

View File

@ -193,6 +193,8 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
query={query}
onChange={onChange}
onBlur={this.props.onBlur}
app={app}
onClearResults={this.onClearResults}
/>
)}
{query.queryType === 'serviceMap' && (

View File

@ -70,6 +70,7 @@ describe('TraceQLSearch', () => {
const onChange = (q: TempoQuery) => {
query = q;
};
const onClearResults = jest.fn();
beforeEach(() => {
jest.useFakeTimers();
@ -83,7 +84,9 @@ describe('TraceQLSearch', () => {
});
it('should update operator when new value is selected in operator input', async () => {
const { container } = render(<TraceQLSearch datasource={datasource} query={query} onChange={onChange} />);
const { container } = render(
<TraceQLSearch datasource={datasource} query={query} onChange={onChange} onClearResults={onClearResults} />
);
const minDurationOperator = container.querySelector(`input[aria-label="select min-duration operator"]`);
expect(minDurationOperator).not.toBeNull();
@ -101,7 +104,9 @@ describe('TraceQLSearch', () => {
});
it('should add new filter when new value is selected in the service name section', async () => {
const { container } = render(<TraceQLSearch datasource={datasource} query={query} onChange={onChange} />);
const { container } = render(
<TraceQLSearch datasource={datasource} query={query} onChange={onChange} onClearResults={onClearResults} />
);
const serviceNameValue = container.querySelector(`input[aria-label="select service-name value"]`);
expect(serviceNameValue).not.toBeNull();
expect(serviceNameValue).toBeInTheDocument();
@ -136,7 +141,9 @@ describe('TraceQLSearch', () => {
} as TempoDatasource;
datasource.languageProvider = new TempoLanguageProvider(datasource);
await act(async () => {
const { container } = render(<TraceQLSearch datasource={datasource} query={query} onChange={onChange} />);
const { container } = render(
<TraceQLSearch datasource={datasource} query={query} onChange={onChange} onClearResults={onClearResults} />
);
const serviceNameValue = container.querySelector(`input[aria-label="select service-name value"]`);
expect(serviceNameValue).toBeNull();
expect(serviceNameValue).not.toBeInTheDocument();
@ -145,7 +152,9 @@ describe('TraceQLSearch', () => {
it('should not render group by when feature toggle is not enabled', async () => {
await waitFor(() => {
render(<TraceQLSearch datasource={datasource} query={query} onChange={onChange} />);
render(
<TraceQLSearch datasource={datasource} query={query} onChange={onChange} onClearResults={onClearResults} />
);
const groupBy = screen.queryByText('Aggregate by');
expect(groupBy).toBeNull();
expect(groupBy).not.toBeInTheDocument();
@ -155,7 +164,9 @@ describe('TraceQLSearch', () => {
it('should render group by when feature toggle enabled', async () => {
config.featureToggles.metricsSummary = true;
await waitFor(() => {
render(<TraceQLSearch datasource={datasource} query={query} onChange={onChange} />);
render(
<TraceQLSearch datasource={datasource} query={query} onChange={onChange} onClearResults={onClearResults} />
);
const groupBy = screen.queryByText('Aggregate by');
expect(groupBy).not.toBeNull();
expect(groupBy).toBeInTheDocument();

View File

@ -1,10 +1,9 @@
import { css } from '@emotion/css';
import React, { useCallback, useEffect, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { EditorRow } from '@grafana/experimental';
import { config, FetchError, getTemplateSrv } from '@grafana/runtime';
import { Alert, HorizontalGroup, Select, useStyles2 } from '@grafana/ui';
import { CoreApp, GrafanaTheme2 } from '@grafana/data';
import { config, FetchError, getTemplateSrv, reportInteraction } from '@grafana/runtime';
import { Alert, Button, HorizontalGroup, Select, useStyles2 } from '@grafana/ui';
import { createErrorNotification } from '../../../../core/copy/appNotification';
import { notifyApp } from '../../../../core/reducers/appNotification';
@ -28,11 +27,13 @@ interface Props {
query: TempoQuery;
onChange: (value: TempoQuery) => void;
onBlur?: () => void;
onClearResults: () => void;
app?: CoreApp;
}
const hardCodedFilterIds = ['min-duration', 'max-duration', 'status'];
const TraceQLSearch = ({ datasource, query, onChange }: Props) => {
const TraceQLSearch = ({ datasource, query, onChange, onClearResults, app }: Props) => {
const styles = useStyles2(getStyles);
const [error, setError] = useState<Error | FetchError | null>(null);
@ -214,9 +215,30 @@ const TraceQLSearch = ({ datasource, query, onChange }: Props) => {
<GroupByField datasource={datasource} onChange={onChange} query={query} isTagsLoading={isTagsLoading} />
)}
</div>
<EditorRow>
<div className={styles.rawQueryContainer}>
<RawQuery query={templateSrv.replace(traceQlQuery)} lang={{ grammar: traceqlGrammar, name: 'traceql' }} />
</EditorRow>
<Button
variant="secondary"
size="sm"
onClick={() => {
reportInteraction('grafana_traces_copy_to_traceql_clicked', {
app: app ?? '',
grafana_version: config.buildInfo.version,
location: 'search_tab',
});
onClearResults();
const traceQlQuery = generateQueryFromFilters(query.filters || []);
onChange({
...query,
query: traceQlQuery,
queryType: 'traceql',
});
}}
>
Edit in TraceQL
</Button>
</div>
<TempoQueryBuilderOptions onChange={onChange} query={query} />
</div>
{error ? (
@ -242,4 +264,11 @@ const getStyles = (theme: GrafanaTheme2) => ({
flex-wrap: wrap;
flex-direction: column;
`,
rawQueryContainer: css({
alignItems: 'center',
backgroundColor: theme.colors.background.secondary,
display: 'flex',
justifyContent: 'space-between',
padding: theme.spacing(1),
}),
});

View File

@ -48,9 +48,9 @@ export function QueryEditor(props: Props) {
size="sm"
onClick={() => {
reportInteraction('grafana_traces_copy_to_traceql_clicked', {
datasourceType: 'tempo',
app: props.app ?? '',
grafana_version: config.buildInfo.version,
location: 'traceql_tab',
});
props.onClearResults();