mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tempo: Separate trace to logs and loki search datasource config (#46655)
* Tempo: Separate trace to logs and loki search datasource config * Add getLokiSearchDS util and tests
This commit is contained in:
parent
1cfb9a4a19
commit
0da40b7f09
@ -156,7 +156,6 @@ datasources:
|
|||||||
spanEndTimeShift: '1h'
|
spanEndTimeShift: '1h'
|
||||||
filterByTraceID: false
|
filterByTraceID: false
|
||||||
filterBySpanID: false
|
filterBySpanID: false
|
||||||
lokiSearch: true
|
|
||||||
secureJsonData:
|
secureJsonData:
|
||||||
basicAuthPassword: my_password
|
basicAuthPassword: my_password
|
||||||
```
|
```
|
||||||
|
@ -57,6 +57,12 @@ This is a configuration for the beta Node Graph visualization. The Node Graph is
|
|||||||
|
|
||||||
-- **Enable Node Graph -** Enables the Node Graph visualization.
|
-- **Enable Node Graph -** Enables the Node Graph visualization.
|
||||||
|
|
||||||
|
### Loki Search
|
||||||
|
|
||||||
|
This is a configuration for the Loki search query type.
|
||||||
|
|
||||||
|
-- **Data source -** The Loki instance in which you want to search traces. You must configure derived fields in the Loki instance.
|
||||||
|
|
||||||
## Query traces
|
## Query traces
|
||||||
|
|
||||||
You can query and display traces from Tempo via [Explore]({{< relref "../explore/_index.md" >}}).
|
You can query and display traces from Tempo via [Explore]({{< relref "../explore/_index.md" >}}).
|
||||||
@ -81,7 +87,7 @@ You must also configure your Tempo data source to use this feature.Refer to the
|
|||||||
|
|
||||||
### Loki search
|
### Loki search
|
||||||
|
|
||||||
You can search for traces if you set up the trace to logs setting in the data source configuration page. To find traces to visualize, use the [Loki query editor]({{< relref "loki.md#loki-query-editor" >}}). To get search results, you must have [derived fields]({{< relref "loki.md#derived-fields" >}}) configured, which point to this data source.
|
To find traces to visualize, use the [Loki query editor]({{< relref "loki.md#loki-query-editor" >}}). To get search results, you must have [derived fields]({{< relref "loki.md#derived-fields" >}}) configured, which point to this data source.
|
||||||
|
|
||||||
{{< figure src="/static/img/docs/tempo/query-editor-search.png" class="docs-image--no-shadow" max-width="750px" caption="Screenshot of the Tempo query editor showing the search tab" >}}
|
{{< figure src="/static/img/docs/tempo/query-editor-search.png" class="docs-image--no-shadow" max-width="750px" caption="Screenshot of the Tempo query editor showing the search tab" >}}
|
||||||
|
|
||||||
@ -197,11 +203,12 @@ datasources:
|
|||||||
spanEndTimeShift: '1h'
|
spanEndTimeShift: '1h'
|
||||||
filterByTraceID: false
|
filterByTraceID: false
|
||||||
filterBySpanID: false
|
filterBySpanID: false
|
||||||
lokiSearch: true
|
|
||||||
serviceMap:
|
serviceMap:
|
||||||
datasourceUid: 'prometheus'
|
datasourceUid: 'prometheus'
|
||||||
search:
|
search:
|
||||||
hide: false
|
hide: false
|
||||||
nodeGraph:
|
nodeGraph:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
lokiSearch:
|
||||||
|
datasourceUid: 'loki'
|
||||||
```
|
```
|
||||||
|
@ -20,7 +20,7 @@ export interface TraceToLogsOptions {
|
|||||||
spanEndTimeShift?: string;
|
spanEndTimeShift?: string;
|
||||||
filterByTraceID?: boolean;
|
filterByTraceID?: boolean;
|
||||||
filterBySpanID?: boolean;
|
filterBySpanID?: boolean;
|
||||||
lokiSearch?: boolean;
|
lokiSearch?: boolean; // legacy
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TraceToLogsData extends DataSourceJsonData {
|
export interface TraceToLogsData extends DataSourceJsonData {
|
||||||
@ -205,22 +205,6 @@ export function TraceToLogsSettings({ options, onOptionsChange }: Props) {
|
|||||||
/>
|
/>
|
||||||
</InlineField>
|
</InlineField>
|
||||||
</InlineFieldRow>
|
</InlineFieldRow>
|
||||||
|
|
||||||
<InlineFieldRow>
|
|
||||||
<InlineField label="Loki Search" labelWidth={26} grow tooltip="Use this logs data source to search for traces.">
|
|
||||||
<InlineSwitch
|
|
||||||
id="lokiSearch"
|
|
||||||
defaultChecked={true}
|
|
||||||
value={options.jsonData.tracesToLogs?.lokiSearch}
|
|
||||||
onChange={(event: React.SyntheticEvent<HTMLInputElement>) =>
|
|
||||||
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToLogs', {
|
|
||||||
...options.jsonData.tracesToLogs,
|
|
||||||
lokiSearch: event.currentTarget.checked,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</InlineField>
|
|
||||||
</InlineFieldRow>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,11 @@ import {
|
|||||||
Themeable2,
|
Themeable2,
|
||||||
withTheme2,
|
withTheme2,
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { TraceToLogsOptions } from 'app/core/components/TraceToLogs/TraceToLogsSettings';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { LokiQueryField } from '../../loki/components/LokiQueryField';
|
import { LokiQueryField } from '../../loki/components/LokiQueryField';
|
||||||
import { LokiQuery } from '../../loki/types';
|
import { LokiQuery } from '../../loki/types';
|
||||||
import { TempoDatasource, TempoQuery, TempoQueryType } from '../datasource';
|
import { TempoDatasource, TempoQuery, TempoQueryType } from '../datasource';
|
||||||
import LokiDatasource from '../../loki/datasource';
|
import LokiDatasource from '../../loki/datasource';
|
||||||
import { PrometheusDatasource } from '../../prometheus/datasource';
|
|
||||||
import useAsync from 'react-use/lib/useAsync';
|
import useAsync from 'react-use/lib/useAsync';
|
||||||
import NativeSearch from './NativeSearch';
|
import NativeSearch from './NativeSearch';
|
||||||
import { getDS } from './utils';
|
import { getDS } from './utils';
|
||||||
@ -28,43 +26,12 @@ interface Props extends QueryEditorProps<TempoDatasource, TempoQuery>, Themeable
|
|||||||
|
|
||||||
const DEFAULT_QUERY_TYPE: TempoQueryType = 'traceId';
|
const DEFAULT_QUERY_TYPE: TempoQueryType = 'traceId';
|
||||||
|
|
||||||
interface State {
|
class TempoQueryFieldComponent extends React.PureComponent<Props> {
|
||||||
linkedDatasourceUid?: string;
|
|
||||||
linkedDatasource?: LokiDatasource;
|
|
||||||
serviceMapDatasourceUid?: string;
|
|
||||||
serviceMapDatasource?: PrometheusDatasource;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
|
|
||||||
state = {
|
|
||||||
linkedDatasourceUid: undefined,
|
|
||||||
linkedDatasource: undefined,
|
|
||||||
serviceMapDatasourceUid: undefined,
|
|
||||||
serviceMapDatasource: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const { datasource } = this.props;
|
|
||||||
// Find query field from linked datasource
|
|
||||||
const tracesToLogsOptions: TraceToLogsOptions = datasource.tracesToLogs || {};
|
|
||||||
const linkedDatasourceUid = tracesToLogsOptions.datasourceUid;
|
|
||||||
|
|
||||||
const serviceMapDsUid = datasource.serviceMap?.datasourceUid;
|
|
||||||
|
|
||||||
// Check status of linked data sources so we can show warnings if needed.
|
|
||||||
const [logsDs, serviceMapDs] = await Promise.all([getDS(linkedDatasourceUid), getDS(serviceMapDsUid)]);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
linkedDatasourceUid: linkedDatasourceUid,
|
|
||||||
linkedDatasource: logsDs as LokiDatasource,
|
|
||||||
serviceMapDatasourceUid: serviceMapDsUid,
|
|
||||||
serviceMapDatasource: serviceMapDs as PrometheusDatasource,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set initial query type to ensure traceID field appears
|
// Set initial query type to ensure traceID field appears
|
||||||
if (!this.props.query.queryType) {
|
if (!this.props.query.queryType) {
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
@ -98,9 +65,9 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { query, onChange, datasource } = this.props;
|
const { query, onChange, datasource } = this.props;
|
||||||
// Find query field from linked datasource
|
|
||||||
const tracesToLogsOptions: TraceToLogsOptions = datasource.tracesToLogs || {};
|
const logsDatasourceUid = datasource.getLokiSearchDS();
|
||||||
const logsDatasourceUid = tracesToLogsOptions.datasourceUid;
|
|
||||||
const graphDatasourceUid = datasource.serviceMap?.datasourceUid;
|
const graphDatasourceUid = datasource.serviceMap?.datasourceUid;
|
||||||
|
|
||||||
const queryTypeOptions: Array<SelectableValue<TempoQueryType>> = [
|
const queryTypeOptions: Array<SelectableValue<TempoQueryType>> = [
|
||||||
@ -116,7 +83,7 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
|
|||||||
queryTypeOptions.unshift({ value: 'nativeSearch', label: 'Search - Beta' });
|
queryTypeOptions.unshift({ value: 'nativeSearch', label: 'Search - Beta' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logsDatasourceUid && tracesToLogsOptions?.lokiSearch !== false) {
|
if (logsDatasourceUid) {
|
||||||
if (!config.featureToggles.tempoSearch) {
|
if (!config.featureToggles.tempoSearch) {
|
||||||
// Place at beginning as Search if no native search
|
// Place at beginning as Search if no native search
|
||||||
queryTypeOptions.unshift({ value: 'search', label: 'Search' });
|
queryTypeOptions.unshift({ value: 'search', label: 'Search' });
|
||||||
@ -161,7 +128,7 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
|
|||||||
)}
|
)}
|
||||||
{query.queryType === 'search' && (
|
{query.queryType === 'search' && (
|
||||||
<SearchSection
|
<SearchSection
|
||||||
linkedDatasourceUid={logsDatasourceUid}
|
logsDatasourceUid={logsDatasourceUid}
|
||||||
query={query}
|
query={query}
|
||||||
onRunQuery={this.onRunLinkedQuery}
|
onRunQuery={this.onRunLinkedQuery}
|
||||||
onChange={this.onChangeLinkedQuery}
|
onChange={this.onChangeLinkedQuery}
|
||||||
@ -217,13 +184,13 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface SearchSectionProps {
|
interface SearchSectionProps {
|
||||||
linkedDatasourceUid?: string;
|
logsDatasourceUid?: string;
|
||||||
onChange: (value: LokiQuery) => void;
|
onChange: (value: LokiQuery) => void;
|
||||||
onRunQuery: () => void;
|
onRunQuery: () => void;
|
||||||
query: TempoQuery;
|
query: TempoQuery;
|
||||||
}
|
}
|
||||||
function SearchSection({ linkedDatasourceUid, onChange, onRunQuery, query }: SearchSectionProps) {
|
function SearchSection({ logsDatasourceUid, onChange, onRunQuery, query }: SearchSectionProps) {
|
||||||
const dsState = useAsync(() => getDS(linkedDatasourceUid), [linkedDatasourceUid]);
|
const dsState = useAsync(() => getDS(logsDatasourceUid), [logsDatasourceUid]);
|
||||||
if (dsState.loading) {
|
if (dsState.loading) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -246,15 +213,15 @@ function SearchSection({ linkedDatasourceUid, onChange, onRunQuery, query }: Sea
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!linkedDatasourceUid) {
|
if (!logsDatasourceUid) {
|
||||||
return <div className="text-warning">Please set up a Traces-to-logs datasource in the datasource settings.</div>;
|
return <div className="text-warning">Please set up a Loki search datasource in the datasource settings.</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (linkedDatasourceUid && !ds) {
|
if (logsDatasourceUid && !ds) {
|
||||||
return (
|
return (
|
||||||
<div className="text-warning">
|
<div className="text-warning">
|
||||||
Traces-to-logs datasource is configured but the data source no longer exists. Please configure existing data
|
Loki search datasource is configured but the data source no longer exists. Please configure existing data source
|
||||||
source to use the search.
|
to use the search.
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import { ServiceGraphSettings } from './ServiceGraphSettings';
|
|||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { SearchSettings } from './SearchSettings';
|
import { SearchSettings } from './SearchSettings';
|
||||||
import { NodeGraphSettings } from 'app/core/components/NodeGraphSettings';
|
import { NodeGraphSettings } from 'app/core/components/NodeGraphSettings';
|
||||||
|
import { LokiSearchSettings } from './LokiSearchSettings';
|
||||||
|
|
||||||
export type Props = DataSourcePluginOptionsEditorProps;
|
export type Props = DataSourcePluginOptionsEditorProps;
|
||||||
|
|
||||||
@ -35,6 +36,9 @@ export const ConfigEditor: React.FC<Props> = ({ options, onOptionsChange }) => {
|
|||||||
<div className="gf-form-group">
|
<div className="gf-form-group">
|
||||||
<NodeGraphSettings options={options} onOptionsChange={onOptionsChange} />
|
<NodeGraphSettings options={options} onOptionsChange={onOptionsChange} />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="gf-form-group">
|
||||||
|
<LokiSearchSettings options={options} onOptionsChange={onOptionsChange} />
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import { DataSourcePluginOptionsEditorProps, GrafanaTheme, updateDatasourcePluginJsonDataOption } from '@grafana/data';
|
||||||
|
import { DataSourcePicker } from '@grafana/runtime';
|
||||||
|
import { Button, InlineField, InlineFieldRow, useStyles } from '@grafana/ui';
|
||||||
|
import React from 'react';
|
||||||
|
import { TempoJsonData } from '../datasource';
|
||||||
|
|
||||||
|
interface Props extends DataSourcePluginOptionsEditorProps<TempoJsonData> {}
|
||||||
|
|
||||||
|
export function LokiSearchSettings({ options, onOptionsChange }: Props) {
|
||||||
|
const styles = useStyles(getStyles);
|
||||||
|
|
||||||
|
// Default to the trace to logs datasource if configured and loki search was enabled
|
||||||
|
// but only if jsonData.lokiSearch hasn't been set
|
||||||
|
const legacyDatasource =
|
||||||
|
options.jsonData.tracesToLogs?.lokiSearch !== false ? options.jsonData.tracesToLogs?.datasourceUid : undefined;
|
||||||
|
if (legacyDatasource && options.jsonData.lokiSearch === undefined) {
|
||||||
|
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'lokiSearch', {
|
||||||
|
datasourceUid: legacyDatasource,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={css({ width: '100%' })}>
|
||||||
|
<h3 className="page-heading">Loki Search</h3>
|
||||||
|
|
||||||
|
<div className={styles.infoText}>
|
||||||
|
Select a Loki datasource to search for traces. Derived fields must be configured in the Loki data source.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<InlineFieldRow className={styles.row}>
|
||||||
|
<InlineField tooltip="The Loki data source with the service graph data" label="Data source" labelWidth={26}>
|
||||||
|
<DataSourcePicker
|
||||||
|
inputId="loki-search-data-source-picker"
|
||||||
|
pluginId="loki"
|
||||||
|
current={options.jsonData.lokiSearch?.datasourceUid}
|
||||||
|
noDefault={true}
|
||||||
|
width={40}
|
||||||
|
onChange={(ds) =>
|
||||||
|
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'lokiSearch', {
|
||||||
|
datasourceUid: ds.uid,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</InlineField>
|
||||||
|
{options.jsonData.lokiSearch?.datasourceUid ? (
|
||||||
|
<Button
|
||||||
|
type={'button'}
|
||||||
|
variant={'secondary'}
|
||||||
|
size={'sm'}
|
||||||
|
fill={'text'}
|
||||||
|
onClick={() => {
|
||||||
|
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'lokiSearch', {
|
||||||
|
datasourceUid: undefined,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</InlineFieldRow>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme) => ({
|
||||||
|
infoText: css`
|
||||||
|
label: infoText;
|
||||||
|
padding-bottom: ${theme.spacing.md};
|
||||||
|
color: ${theme.colors.textSemiWeak};
|
||||||
|
`,
|
||||||
|
|
||||||
|
row: css`
|
||||||
|
label: row;
|
||||||
|
align-items: baseline;
|
||||||
|
`,
|
||||||
|
});
|
@ -223,6 +223,55 @@ describe('Tempo data source', () => {
|
|||||||
'Service Name: frontend, Span Name: /config, Search: root.http.status_code=500, Min Duration: 1ms, Max Duration: 100s, Limit: 10'
|
'Service Name: frontend, Span Name: /config, Search: root.http.status_code=500, Min Duration: 1ms, Max Duration: 100s, Limit: 10'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should get loki search datasource', () => {
|
||||||
|
// 1. Get lokiSearch.datasource if present
|
||||||
|
const ds1 = new TempoDatasource({
|
||||||
|
...defaultSettings,
|
||||||
|
jsonData: {
|
||||||
|
lokiSearch: {
|
||||||
|
datasourceUid: 'loki-1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const lokiDS1 = ds1.getLokiSearchDS();
|
||||||
|
expect(lokiDS1).toBe('loki-1');
|
||||||
|
|
||||||
|
// 2. Get traceToLogs.datasource
|
||||||
|
const ds2 = new TempoDatasource({
|
||||||
|
...defaultSettings,
|
||||||
|
jsonData: {
|
||||||
|
tracesToLogs: {
|
||||||
|
lokiSearch: true,
|
||||||
|
datasourceUid: 'loki-2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const lokiDS2 = ds2.getLokiSearchDS();
|
||||||
|
expect(lokiDS2).toBe('loki-2');
|
||||||
|
|
||||||
|
// 3. Return undefined if neither is available
|
||||||
|
const ds3 = new TempoDatasource(defaultSettings);
|
||||||
|
const lokiDS3 = ds3.getLokiSearchDS();
|
||||||
|
expect(lokiDS3).toBe(undefined);
|
||||||
|
|
||||||
|
// 4. Return undefined if lokiSearch is undefined, even if traceToLogs is present
|
||||||
|
// since this indicates the user cleared the fallback setting
|
||||||
|
const ds4 = new TempoDatasource({
|
||||||
|
...defaultSettings,
|
||||||
|
jsonData: {
|
||||||
|
tracesToLogs: {
|
||||||
|
lokiSearch: true,
|
||||||
|
datasourceUid: 'loki-2',
|
||||||
|
},
|
||||||
|
lokiSearch: {
|
||||||
|
datasourceUid: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const lokiDS4 = ds4.getLokiSearchDS();
|
||||||
|
expect(lokiDS4).toBe(undefined);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const backendSrvWithPrometheus = {
|
const backendSrvWithPrometheus = {
|
||||||
|
@ -45,6 +45,9 @@ export interface TempoJsonData extends DataSourceJsonData {
|
|||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
};
|
};
|
||||||
nodeGraph?: NodeGraphOptions;
|
nodeGraph?: NodeGraphOptions;
|
||||||
|
lokiSearch?: {
|
||||||
|
datasourceUid?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TempoQuery extends DataQuery {
|
export interface TempoQuery extends DataQuery {
|
||||||
@ -81,6 +84,9 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
|||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
};
|
};
|
||||||
nodeGraph?: NodeGraphOptions;
|
nodeGraph?: NodeGraphOptions;
|
||||||
|
lokiSearch?: {
|
||||||
|
datasourceUid?: string;
|
||||||
|
};
|
||||||
uploadedJson?: string | ArrayBuffer | null = null;
|
uploadedJson?: string | ArrayBuffer | null = null;
|
||||||
|
|
||||||
constructor(private instanceSettings: DataSourceInstanceSettings<TempoJsonData>) {
|
constructor(private instanceSettings: DataSourceInstanceSettings<TempoJsonData>) {
|
||||||
@ -89,6 +95,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
|||||||
this.serviceMap = instanceSettings.jsonData.serviceMap;
|
this.serviceMap = instanceSettings.jsonData.serviceMap;
|
||||||
this.search = instanceSettings.jsonData.search;
|
this.search = instanceSettings.jsonData.search;
|
||||||
this.nodeGraph = instanceSettings.jsonData.nodeGraph;
|
this.nodeGraph = instanceSettings.jsonData.nodeGraph;
|
||||||
|
this.lokiSearch = instanceSettings.jsonData.lokiSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
query(options: DataQueryRequest<TempoQuery>): Observable<DataQueryResponse> {
|
query(options: DataQueryRequest<TempoQuery>): Observable<DataQueryResponse> {
|
||||||
@ -100,11 +107,13 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
|||||||
return of({ data: [], state: LoadingState.Done });
|
return of({ data: [], state: LoadingState.Done });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logsDatasourceUid = this.getLokiSearchDS();
|
||||||
|
|
||||||
// Run search queries on linked datasource
|
// Run search queries on linked datasource
|
||||||
if (this.tracesToLogs?.datasourceUid && targets.search?.length > 0) {
|
if (logsDatasourceUid && targets.search?.length > 0) {
|
||||||
const dsSrv = getDatasourceSrv();
|
const dsSrv = getDatasourceSrv();
|
||||||
subQueries.push(
|
subQueries.push(
|
||||||
from(dsSrv.get(this.tracesToLogs.datasourceUid)).pipe(
|
from(dsSrv.get(logsDatasourceUid)).pipe(
|
||||||
mergeMap((linkedDatasource: DataSourceApi) => {
|
mergeMap((linkedDatasource: DataSourceApi) => {
|
||||||
// Wrap linked query into a data request based on original request
|
// Wrap linked query into a data request based on original request
|
||||||
const linkedRequest: DataQueryRequest = { ...options, targets: targets.search.map((t) => t.linkedQuery!) };
|
const linkedRequest: DataQueryRequest = { ...options, targets: targets.search.map((t) => t.linkedQuery!) };
|
||||||
@ -300,6 +309,15 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
|||||||
const ds = await getDatasourceSrv().get(this.serviceMap!.datasourceUid);
|
const ds = await getDatasourceSrv().get(this.serviceMap!.datasourceUid);
|
||||||
return ds.getTagValues!({ key });
|
return ds.getTagValues!({ key });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get linked loki search datasource. Fall back to legacy loki search/trace to logs config
|
||||||
|
getLokiSearchDS = (): string | undefined => {
|
||||||
|
const legacyLogsDatasourceUid =
|
||||||
|
this.tracesToLogs?.lokiSearch !== false && this.lokiSearch === undefined
|
||||||
|
? this.tracesToLogs?.datasourceUid
|
||||||
|
: undefined;
|
||||||
|
return this.lokiSearch?.datasourceUid ?? legacyLogsDatasourceUid;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryServiceMapPrometheus(request: DataQueryRequest<PromQuery>, datasourceUid: string) {
|
function queryServiceMapPrometheus(request: DataQueryRequest<PromQuery>, datasourceUid: string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user