From b75b747881f35271e387ae99372dad43af27c316 Mon Sep 17 00:00:00 2001 From: Domas Date: Tue, 10 Oct 2023 17:57:05 +0300 Subject: [PATCH] Tempo data source: Fix service map query error when a duration data frame has no data (#76269) * fix tempo service graph req when data frame is empty * also report error to Faro --- public/app/features/query/state/runRequest.ts | 6 +-- .../datasource/tempo/datasource.test.ts | 16 ++++++- .../plugins/datasource/tempo/datasource.ts | 47 ++++++++++--------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/public/app/features/query/state/runRequest.ts b/public/app/features/query/state/runRequest.ts index cf389aff076..c9195b45475 100644 --- a/public/app/features/query/state/runRequest.ts +++ b/public/app/features/query/state/runRequest.ts @@ -18,7 +18,7 @@ import { PanelData, TimeRange, } from '@grafana/data'; -import { config, toDataQueryError } from '@grafana/runtime'; +import { config, toDataQueryError, logError } from '@grafana/runtime'; import { isExpressionReference } from '@grafana/runtime/src/utils/DataSourceWithBackend'; import { backendSrv } from 'app/core/services/backend_srv'; import { queryIsEmpty } from 'app/core/utils/query'; @@ -156,8 +156,8 @@ export function runRequest( }), // handle errors catchError((err) => { - const errLog = typeof err === 'string' ? err : JSON.stringify(err); - console.error('runRequest.catchError', errLog); + console.error('runRequest.catchError', err); + logError(err); return of({ ...state.panelData, state: LoadingState.Error, diff --git a/public/app/plugins/datasource/tempo/datasource.test.ts b/public/app/plugins/datasource/tempo/datasource.test.ts index 7a41119d45e..9091e9f61d3 100644 --- a/public/app/plugins/datasource/tempo/datasource.test.ts +++ b/public/app/plugins/datasource/tempo/datasource.test.ts @@ -987,7 +987,15 @@ const backendSrvWithPrometheus = { return { query() { return of({ - data: [rateMetric, errorRateMetric, durationMetric, totalsPromMetric, secondsPromMetric, failedPromMetric], + data: [ + rateMetric, + errorRateMetric, + durationMetric, + emptyDurationMetric, + totalsPromMetric, + secondsPromMetric, + failedPromMetric, + ], }); }, }; @@ -1079,6 +1087,12 @@ const durationMetric = createDataFrame({ ], }); +const emptyDurationMetric = createDataFrame({ + refId: + 'histogram_quantile(.9, sum(rate(traces_spanmetrics_latency_bucket{span_name=~"HTTP GET - root"}[$__range])) by (le))', + fields: [], +}); + const totalsPromMetric = createDataFrame({ refId: 'traces_service_graph_request_total', fields: [ diff --git a/public/app/plugins/datasource/tempo/datasource.ts b/public/app/plugins/datasource/tempo/datasource.ts index 47b6190227e..b9d40dbb218 100644 --- a/public/app/plugins/datasource/tempo/datasource.ts +++ b/public/app/plugins/datasource/tempo/datasource.ts @@ -1187,30 +1187,33 @@ function getServiceGraphView( }); } - if (duration.length > 0 && duration[0].fields?.length > 1) { + if (duration.length > 0) { let durationObj: any = {}; - duration.map((d) => { - const delimiter = d.refId?.includes('span_name=~"') ? 'span_name=~"' : 'span_name="'; - const name = d.refId?.split(delimiter)[1].split('"}')[0]; - durationObj[name] = { value: d.fields[1].values[0] }; - }); - - df.fields.push({ - ...duration[0].fields[1], - name: 'Duration (p90)', - values: getRateAlignedValues({ ...rate }, durationObj), - config: { - links: [ - makePromLink( - 'Duration', - buildLinkExpr(buildExpr(durationMetric, 'span_name="${__data.fields[0]}"', request)), - datasourceUid, - false - ), - ], - unit: 's', - }, + duration.forEach((d) => { + if (d.fields.length > 1) { + const delimiter = d.refId?.includes('span_name=~"') ? 'span_name=~"' : 'span_name="'; + const name = d.refId?.split(delimiter)[1].split('"}')[0]; + durationObj[name] = { value: d.fields[1].values[0] }; + } }); + if (Object.keys(durationObj).length > 0) { + df.fields.push({ + ...duration[0].fields[1], + name: 'Duration (p90)', + values: getRateAlignedValues({ ...rate }, durationObj), + config: { + links: [ + makePromLink( + 'Duration', + buildLinkExpr(buildExpr(durationMetric, 'span_name="${__data.fields[0]}"', request)), + datasourceUid, + false + ), + ], + unit: 's', + }, + }); + } } if (df.fields.length > 0 && df.fields[0].values) {