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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 29 additions and 17 deletions

View File

@ -59,7 +59,7 @@ Clicking anywhere on the span row shows span details.
##### Node graph
You can optionally expand the node graph for the displayed trace. Depending on the data source, this can show spans of the trace as nodes in the graph, or as some additional context like service map based on the current trace.
You can optionally expand the node graph for the displayed trace. Depending on the data source, this can show spans of the trace as nodes in the graph, or as some additional context like service graph based on the current trace.
![Node graph](/static/img/docs/explore/explore-trace-view-node-graph-8-0.png 'Node graph')

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];
}