Explore: Rename Service Map to Service Graph and improve error handling (#40407)

* Handle error response from linked datasource

* Update response format

* Rename to service graph in the UI and docs
This commit is contained in:
Connor Lindsey
2021-10-13 14:41:42 -06:00
committed by GitHub
parent 8de30ccf9a
commit 2b2b70503e
8 changed files with 29 additions and 17 deletions

View File

@@ -96,7 +96,7 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
];
if (config.featureToggles.tempoServiceGraph) {
queryTypeOptions.push({ value: 'serviceMap', label: 'Service Map' });
queryTypeOptions.push({ value: 'serviceMap', label: 'Service Graph' });
}
if (config.featureToggles.tempoSearch && !datasource?.search?.hide) {
@@ -179,13 +179,13 @@ class TempoQueryFieldComponent extends React.PureComponent<Props, State> {
</InlineField>
</InlineFieldRow>
)}
{query.queryType === 'serviceMap' && <ServiceMapSection graphDatasourceUid={graphDatasourceUid} />}
{query.queryType === 'serviceMap' && <ServiceGraphSection graphDatasourceUid={graphDatasourceUid} />}
</>
);
}
}
function ServiceMapSection({ graphDatasourceUid }: { graphDatasourceUid?: string }) {
function ServiceGraphSection({ graphDatasourceUid }: { graphDatasourceUid?: string }) {
const dsState = useAsync(() => getDS(graphDatasourceUid), [graphDatasourceUid]);
if (dsState.loading) {
return null;

View File

@@ -2,7 +2,7 @@ import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { DataSourceHttpSettings } from '@grafana/ui';
import { TraceToLogsSettings } from 'app/core/components/TraceToLogsSettings';
import React from 'react';
import { ServiceMapSettings } from './ServiceMapSettings';
import { ServiceGraphSettings } from './ServiceGraphSettings';
import { config } from '@grafana/runtime';
import { SearchSettings } from './SearchSettings';
import { NodeGraphSettings } from 'app/core/components/NodeGraphSettings';
@@ -24,7 +24,7 @@ export const ConfigEditor: React.FC<Props> = ({ options, onOptionsChange }) => {
</div>
{config.featureToggles.tempoServiceGraph && (
<div className="gf-form-group">
<ServiceMapSettings options={options} onOptionsChange={onOptionsChange} />
<ServiceGraphSettings options={options} onOptionsChange={onOptionsChange} />
</div>
)}
{config.featureToggles.tempoSearch && (

View File

@@ -7,19 +7,23 @@ import { TempoJsonData } from '../datasource';
interface Props extends DataSourcePluginOptionsEditorProps<TempoJsonData> {}
export function ServiceMapSettings({ options, onOptionsChange }: Props) {
export function ServiceGraphSettings({ options, onOptionsChange }: Props) {
const styles = useStyles(getStyles);
return (
<div className={css({ width: '100%' })}>
<h3 className="page-heading">Service map</h3>
<h3 className="page-heading">Service Graph</h3>
<div className={styles.infoText}>
To allow querying service map data you have to select a Prometheus instance where the data is stored.
To allow querying service graph data you have to select a Prometheus instance where the data is stored.
</div>
<InlineFieldRow className={styles.row}>
<InlineField tooltip="The Prometheus data source with the service map data" label="Data source" labelWidth={26}>
<InlineField
tooltip="The Prometheus data source with the service graph data"
label="Data source"
labelWidth={26}
>
<DataSourcePicker
pluginId="prometheus"
current={options.jsonData.serviceMap?.datasourceUid}

View File

@@ -80,7 +80,7 @@ describe('Tempo data source', () => {
]);
});
it('runs service map queries', async () => {
it('runs service graph queries', async () => {
const ds = new TempoDatasource({
...defaultSettings,
jsonData: {
@@ -209,7 +209,7 @@ const backendSrvWithPrometheus = {
if (uid === 'prom') {
return {
query() {
return of({ data: [totalsPromMetric] }, { data: [secondsPromMetric] });
return of({ data: [totalsPromMetric, secondsPromMetric] });
},
};
}

View File

@@ -283,10 +283,18 @@ function serviceMapQuery(request: DataQueryRequest<TempoQuery>, datasourceUid: s
// Just collect all the responses first before processing into node graph data
toArray(),
map((responses: DataQueryResponse[]) => {
const errorRes = responses.find((res) => !!res.error);
if (errorRes) {
throw new Error(errorRes.error!.message);
}
return {
data: mapPromMetricsToServiceMap(responses, request.range),
state: LoadingState.Done,
};
}),
catchError((error) => {
return of({ error: { message: error.message }, data: [] });
})
);
}

View File

@@ -59,12 +59,12 @@ describe('createGraphFrames', () => {
});
describe('mapPromMetricsToServiceMap', () => {
it('transforms prom metrics to service map', async () => {
it('transforms prom metrics to service graph', async () => {
const range = {
from: dateTime('2000-01-01T00:00:00'),
to: dateTime('2000-01-01T00:01:00'),
};
const [nodes, edges] = mapPromMetricsToServiceMap([{ data: [totalsPromMetric] }, { data: [secondsPromMetric] }], {
const [nodes, edges] = mapPromMetricsToServiceMap([{ data: [totalsPromMetric, secondsPromMetric] }], {
...range,
raw: range,
});

View File

@@ -185,9 +185,9 @@ function createServiceMapDataFrames() {
}
function getMetricFrames(responses: DataQueryResponse[]) {
const responsesMap = groupBy(responses, (r) => r.data[0].refId);
const totalsDFView = new DataFrameView(responsesMap[totalsMetric][0].data[0]);
const secondsDFView = new DataFrameView(responsesMap[secondsMetric][0].data[0]);
const responsesMap = groupBy(responses[0].data, (data) => data.refId);
const totalsDFView = new DataFrameView(responsesMap[totalsMetric][0]);
const secondsDFView = new DataFrameView(responsesMap[secondsMetric][0]);
return [totalsDFView, secondsDFView];
}