Files
grafana/public/app/plugins/datasource/tempo/QueryField.tsx
David 59c754823f Tempo: Search for Traces by querying Loki directly from Tempo (#33308)
* Loki query from Tempo UI

- add query type selector to tempo
- introduce linkedDatasource concept that runs queries on behalf of another datasource
- Tempo uses Loki's query field and Loki's derived fields to find a trace matcher
- Tempo uses the trace-to-logs mechanism to determine which dataource is linked

Loki data loads successfully via tempo

Extracted result transformers

Skip null values

Show trace on list id click

Query type selector

Use linked field trace regexp

* Review feedback
2021-05-10 17:12:19 +02:00

125 lines
4.0 KiB
TypeScript

import { DataQuery, DataSourceApi, ExploreQueryFieldProps } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { getDataSourceSrv } from '@grafana/runtime';
import { InlineField, InlineFieldRow, InlineLabel, LegacyForms, RadioButtonGroup } from '@grafana/ui';
import { TraceToLogsOptions } from 'app/core/components/TraceToLogsSettings';
import React from 'react';
import { LokiQueryField } from '../loki/components/LokiQueryField';
import { TempoDatasource, TempoQuery, TempoQueryType } from './datasource';
type Props = ExploreQueryFieldProps<TempoDatasource, TempoQuery>;
const DEFAULT_QUERY_TYPE: TempoQueryType = 'traceId';
interface State {
linkedDatasource?: DataSourceApi;
}
export class TempoQueryField extends React.PureComponent<Props, State> {
state = {
linkedDatasource: undefined,
};
linkedQuery: DataQuery;
constructor(props: Props) {
super(props);
this.linkedQuery = { refId: 'linked' };
}
async componentDidMount() {
const { datasource } = this.props;
// Find query field from linked datasource
const tracesToLogsOptions: TraceToLogsOptions = datasource.tracesToLogs || {};
const linkedDatasourceUid = tracesToLogsOptions.datasourceUid;
if (linkedDatasourceUid) {
const dsSrv = getDataSourceSrv();
const linkedDatasource = await dsSrv.get(linkedDatasourceUid);
this.setState({
linkedDatasource,
});
}
}
onChangeLinkedQuery = (value: DataQuery) => {
const { query, onChange } = this.props;
this.linkedQuery = value;
onChange({
...query,
linkedQuery: this.linkedQuery,
});
};
onRunLinkedQuery = () => {
this.props.onRunQuery();
};
render() {
const { query, onChange, range } = this.props;
const { linkedDatasource } = this.state;
const absoluteTimeRange = { from: range!.from!.valueOf(), to: range!.to!.valueOf() }; // Range here is never optional
return (
<>
<InlineFieldRow>
<InlineField label="Query type">
<RadioButtonGroup<TempoQueryType>
options={[
{ value: 'search', label: 'Search' },
{ value: 'traceId', label: 'TraceID' },
]}
value={query.queryType || DEFAULT_QUERY_TYPE}
onChange={(v) =>
onChange({
...query,
queryType: v,
})
}
size="md"
/>
</InlineField>
</InlineFieldRow>
{query.queryType === 'search' && linkedDatasource && (
<>
<InlineLabel>
Tempo uses {((linkedDatasource as unknown) as DataSourceApi).name} to find traces.
</InlineLabel>
<LokiQueryField
datasource={linkedDatasource!}
onChange={this.onChangeLinkedQuery}
onRunQuery={this.onRunLinkedQuery}
query={this.linkedQuery as any}
history={[]}
absoluteRange={absoluteTimeRange}
/>
</>
)}
{query.queryType === 'search' && !linkedDatasource && (
<div className="text-warning">Please set up a Traces-to-logs datasource in the datasource settings.</div>
)}
{query.queryType !== 'search' && (
<LegacyForms.FormField
label="Trace ID"
labelWidth={4}
inputEl={
<div className="slate-query-field__wrapper">
<div className="slate-query-field" aria-label={selectors.components.QueryField.container}>
<input
style={{ width: '100%' }}
value={query.query || ''}
onChange={(e) =>
onChange({
...query,
query: e.currentTarget.value,
queryType: 'traceId',
linkedQuery: undefined,
})
}
/>
</div>
</div>
}
/>
)}
</>
);
}
}