Tempo: Update service graph view and docs (#64875)

Update service graph view and docs
This commit is contained in:
Joey 2023-03-22 08:37:44 +00:00 committed by GitHub
parent 0740d4e911
commit b1a7e1d33d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 24 deletions

View File

@ -3,5 +3,4 @@ This devenv docker-compose.yaml will allow you to;
- view traces
- upload/download trace JSON files
- view service graphs
- view the APM table
- search traces via Loki

View File

@ -20,6 +20,7 @@ import {
setDataSourceSrv,
TemplateSrv,
} from '@grafana/runtime';
import { BarGaugeDisplayMode, TableCellDisplayMode } from '@grafana/schema';
import {
DEFAULT_LIMIT,
@ -27,7 +28,7 @@ import {
buildExpr,
buildLinkExpr,
getRateAlignedValues,
makeApmRequest,
makeServiceGraphViewRequest,
makeTempoLink,
getFieldConfig,
} from './datasource';
@ -436,7 +437,7 @@ describe('Tempo data source', () => {
});
});
describe('Tempo apm table', () => {
describe('Tempo service graph view', () => {
it('runs service graph queries', async () => {
const ds = new TempoDatasource({
...defaultSettings,
@ -454,7 +455,7 @@ describe('Tempo apm table', () => {
expect(response.data).toHaveLength(3);
expect(response.state).toBe(LoadingState.Done);
// APM table
// Service Graph view
expect(response.data[0].fields[0].name).toBe('Name');
expect(response.data[0].fields[0].values.toArray().length).toBe(2);
expect(response.data[0].fields[0].values.toArray()[0]).toBe('HTTP Client');
@ -477,7 +478,8 @@ describe('Tempo apm table', () => {
expect(response.data[0].fields[2].values.toArray()[0]).toBe(12.75164671814457);
expect(response.data[0].fields[2].values.toArray()[1]).toBe(12.121331111401608);
expect(response.data[0].fields[2].config.color.mode).toBe('continuous-BlPu');
expect(response.data[0].fields[2].config.custom.displayMode).toBe('lcd-gauge');
expect(response.data[0].fields[2].config.custom.cellOptions.mode).toBe(BarGaugeDisplayMode.Lcd);
expect(response.data[0].fields[2].config.custom.cellOptions.type).toBe(TableCellDisplayMode.Gauge);
expect(response.data[0].fields[2].config.decimals).toBe(3);
expect(response.data[0].fields[3].name).toBe('Error Rate');
@ -497,7 +499,8 @@ describe('Tempo apm table', () => {
expect(response.data[0].fields[4].values[0]).toBe(3.75164671814457);
expect(response.data[0].fields[4].values[1]).toBe(3.121331111401608);
expect(response.data[0].fields[4].config.color.mode).toBe('continuous-RdYlGr');
expect(response.data[0].fields[4].config.custom.displayMode).toBe('lcd-gauge');
expect(response.data[0].fields[4].config.custom.cellOptions.mode).toBe(BarGaugeDisplayMode.Lcd);
expect(response.data[0].fields[4].config.custom.cellOptions.type).toBe(TableCellDisplayMode.Gauge);
expect(response.data[0].fields[4].config.decimals).toBe(3);
expect(response.data[0].fields[5].name).toBe('Duration (p90)');
@ -696,12 +699,12 @@ describe('Tempo apm table', () => {
expect(value.toString()).toBe('0,0.6789,0.1234,0,0.4321');
});
it('should make apm request correctly', () => {
const apmRequest = makeApmRequest([
it('should make service graph view request correctly', () => {
const request = makeServiceGraphViewRequest([
'topk(5, sum(rate(traces_spanmetrics_calls_total{service="app"}[$__range])) by (span_name))"',
'histogram_quantile(.9, sum(rate(traces_spanmetrics_latency_bucket{status_code="STATUS_CODE_ERROR",service="app",service="app",span_name=~"HTTP Client"}[$__range])) by (le))',
]);
expect(apmRequest).toEqual([
expect(request).toEqual([
{
refId: 'topk(5, sum(rate(traces_spanmetrics_calls_total{service="app"}[$__range])) by (span_name))"',
expr: 'topk(5, sum(rate(traces_spanmetrics_calls_total{service="app"}[$__range])) by (span_name))"',

View File

@ -24,6 +24,7 @@ import {
TemplateSrv,
getTemplateSrv,
} from '@grafana/runtime';
import { BarGaugeDisplayMode, TableCellDisplayMode } from '@grafana/schema';
import { NodeGraphOptions } from 'app/core/components/NodeGraphSettings';
import { TraceToLogsOptions } from 'app/core/components/TraceToLogs/TraceToLogsSettings';
import { serializeParams } from 'app/core/utils/fetch';
@ -552,7 +553,7 @@ function rateQuery(
datasourceUid: string
) {
const serviceMapRequest = makePromServiceMapRequest(request);
serviceMapRequest.targets = makeApmRequest([buildExpr(rateMetric, defaultTableFilter, request)]);
serviceMapRequest.targets = makeServiceGraphViewRequest([buildExpr(rateMetric, defaultTableFilter, request)]);
return queryPrometheus(serviceMapRequest, datasourceUid).pipe(
toArray(),
@ -577,23 +578,23 @@ function errorAndDurationQuery(
datasourceUid: string,
tempoDatasourceUid: string
) {
let apmMetrics = [];
let serviceGraphViewMetrics = [];
let errorRateBySpanName = '';
let durationsBySpanName: string[] = [];
const spanNames = rateResponse.data[0][0]?.fields[1]?.values.toArray() ?? [];
if (spanNames.length > 0) {
errorRateBySpanName = buildExpr(errorRateMetric, 'span_name=~"' + spanNames.join('|') + '"', request);
apmMetrics.push(errorRateBySpanName);
serviceGraphViewMetrics.push(errorRateBySpanName);
spanNames.map((name: string) => {
const metric = buildExpr(durationMetric, 'span_name=~"' + name + '"', request);
durationsBySpanName.push(metric);
apmMetrics.push(metric);
serviceGraphViewMetrics.push(metric);
});
}
const serviceMapRequest = makePromServiceMapRequest(request);
serviceMapRequest.targets = makeApmRequest(apmMetrics);
serviceMapRequest.targets = makeServiceGraphViewRequest(serviceGraphViewMetrics);
return queryPrometheus(serviceMapRequest, datasourceUid).pipe(
// Just collect all the responses first before processing into node graph data
@ -604,7 +605,7 @@ function errorAndDurationQuery(
throw new Error(errorRes.error!.message);
}
const apmTable = getApmTable(
const serviceGraphView = getServiceGraphView(
request,
rateResponse,
errorAndDurationResponse[0],
@ -614,7 +615,7 @@ function errorAndDurationQuery(
tempoDatasourceUid
);
if (apmTable.fields.length === 0) {
if (serviceGraphView.fields.length === 0) {
return {
data: [rateResponse.data[1], rateResponse.data[2]],
state: LoadingState.Done,
@ -622,7 +623,7 @@ function errorAndDurationQuery(
}
return {
data: [apmTable, rateResponse.data[1], rateResponse.data[2]],
data: [serviceGraphView, rateResponse.data[1], rateResponse.data[2]],
state: LoadingState.Done,
};
})
@ -715,7 +716,7 @@ function makePromServiceMapRequest(options: DataQueryRequest<TempoQuery>): DataQ
};
}
function getApmTable(
function getServiceGraphView(
request: DataQueryRequest<TempoQuery>,
rateResponse: DataQueryResponse,
secondResponse: DataQueryResponse,
@ -762,14 +763,17 @@ function getApmTable(
df.fields.push({
...rate[0].fields[2],
name: ' ',
name: ' ',
labels: null,
config: {
color: {
mode: 'continuous-BlPu',
},
custom: {
displayMode: 'lcd-gauge',
cellOptions: {
mode: BarGaugeDisplayMode.Lcd,
type: TableCellDisplayMode.Gauge,
},
},
decimals: 3,
},
@ -805,7 +809,7 @@ function getApmTable(
df.fields.push({
...errorRate[0].fields[2],
name: ' ',
name: ' ',
values: values,
labels: null,
config: {
@ -813,7 +817,10 @@ function getApmTable(
mode: 'continuous-RdYlGr',
},
custom: {
displayMode: 'lcd-gauge',
cellOptions: {
mode: BarGaugeDisplayMode.Lcd,
type: TableCellDisplayMode.Gauge,
},
},
decimals: 3,
},
@ -872,7 +879,7 @@ export function buildExpr(
if (serviceMapQueryMatch?.length) {
serviceMapQuery = serviceMapQueryMatch[1];
}
// map serviceGraph metric tags to APM metric tags
// map serviceGraph metric tags to serviceGraphView metric tags
serviceMapQuery = serviceMapQuery.replace('client', 'service').replace('server', 'service');
const metricParams = serviceMapQuery.includes('span_name')
? metric.params.concat(serviceMapQuery)
@ -909,7 +916,7 @@ export function getRateAlignedValues(
return values;
}
export function makeApmRequest(metrics: any[]) {
export function makeServiceGraphViewRequest(metrics: any[]) {
return metrics.map((metric) => {
return {
refId: metric,