@ -47,10 +47,12 @@ import {
errorRateMetric ,
failedMetric ,
histogramMetric ,
nativeHistogramMetric ,
mapPromMetricsToServiceMap ,
rateMetric ,
serviceMapMetrics ,
totalsMetric ,
nativeHistogramDurationMetric ,
} from './graphTransform' ;
import TempoLanguageProvider from './language_provider' ;
import {
@ -110,6 +112,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
tracesToLogs? : TraceToLogsOptions ;
serviceMap ? : {
datasourceUid? : string ;
histogramType ? : 'classic' | 'native' | 'both' ;
} ;
search ? : {
hide? : boolean ;
@ -512,13 +515,13 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
hasServiceMapQuery : targets.serviceMap [ 0 ] . serviceMapQuery ? true : false ,
} ) ;
const dsId = this . serviceMap . datasourceUid ;
const { datasourceUid , histogramType } = this . serviceMap ;
const tempoDsUid = this . uid ;
subQueries . push (
serviceMapQuery ( options , dsI d , tempoDsUid ) . pipe (
serviceMapQuery ( options , datasourceUi d , tempoDsUid , histogramType ) . pipe (
concatMap ( ( result ) = >
rateQuery ( options , result , dsI d ) . pipe (
concatMap ( ( result ) = > errorAndDurationQuery ( options , result , dsI d , tempoDsUid ) )
rateQuery ( options , result , datasourceUi d ) . pipe (
concatMap ( ( result ) = > errorAndDurationQuery ( options , result , datasourceUi d , tempoDsUid , histogramType ) )
)
)
)
@ -943,9 +946,10 @@ function queryPrometheus(request: DataQueryRequest<PromQuery>, datasourceUid: st
function serviceMapQuery (
request : DataQueryRequest < TempoQuery > ,
datasourceUid : string ,
tempoDatasourceUid : string
tempoDatasourceUid : string ,
histogramType? : string
) : Observable < ServiceMapQueryResponse > {
const serviceMapRequest = makePromServiceMapRequest ( request ) ;
const serviceMapRequest = makePromServiceMapRequest ( request , histogramType ) ;
return queryPrometheus ( serviceMapRequest , datasourceUid ) . pipe (
// Just collect all the responses first before processing into node graph data
@ -982,7 +986,8 @@ function serviceMapQuery(
'__data.fields.title' , // targetField
'__data.fields[0]' , // tempoField
undefined , // sourceField
{ targetNamespace : '__data.fields.subtitle' }
{ targetNamespace : '__data.fields.subtitle' } ,
histogramType
) ;
edges . fields [ 0 ] . config = getFieldConfig (
@ -991,21 +996,27 @@ function serviceMapQuery(
'__data.fields.targetName' , // targetField
'__data.fields.target' , // tempoField
'__data.fields.sourceName' , // sourceField
{ targetNamespace : '__data.fields.targetNamespace' , sourceNamespace : '__data.fields.sourceNamespace' }
{ targetNamespace : '__data.fields.targetNamespace' , sourceNamespace : '__data.fields.sourceNamespace' } ,
histogramType
) ;
} else {
nodes . fields [ 0 ] . config = getFieldConfig (
datasourceUid ,
tempoDatasourceUid ,
'__data.fields.id' ,
'__data.fields[0]'
'__data.fields[0]' ,
undefined ,
undefined ,
histogramType
) ;
edges . fields [ 0 ] . config = getFieldConfig (
datasourceUid ,
tempoDatasourceUid ,
'__data.fields.target' ,
'__data.fields.target' ,
'__data.fields.source'
'__data.fields.source' ,
undefined ,
histogramType
) ;
}
@ -1021,9 +1032,10 @@ function serviceMapQuery(
function rateQuery (
request : DataQueryRequest < TempoQuery > ,
serviceMapResponse : ServiceMapQueryResponse ,
datasourceUid : string
datasourceUid : string ,
histogramType? : string
) : Observable < ServiceMapQueryResponseWithRates > {
const serviceMapRequest = makePromServiceMapRequest ( request ) ;
const serviceMapRequest = makePromServiceMapRequest ( request , histogramType ) ;
serviceMapRequest . targets = makeServiceGraphViewRequest ( [ buildExpr ( rateMetric , defaultTableFilter , request ) ] ) ;
return queryPrometheus ( serviceMapRequest , datasourceUid ) . pipe (
@ -1048,7 +1060,8 @@ function errorAndDurationQuery(
request : DataQueryRequest < TempoQuery > ,
rateResponse : ServiceMapQueryResponseWithRates ,
datasourceUid : string ,
tempoDatasourceUid : string
tempoDatasourceUid : string ,
histogramType? : string
) {
let serviceGraphViewMetrics = [ ] ;
let errorRateBySpanName = '' ;
@ -1074,13 +1087,14 @@ function errorAndDurationQuery(
errorRateBySpanName = buildExpr ( errorRateMetric , 'span_name=~"' + spanNames . join ( '|' ) + '"' , request ) ;
serviceGraphViewMetrics . push ( errorRateBySpanName ) ;
spanNames . map ( ( name : string ) = > {
const metric = buildExpr ( durationMetric , 'span_name=~"' + name + '"' , request ) ;
const checkedDurationMetric = histogramType === 'native' ? nativeHistogramDurationMetric : durationMetric ;
const metric = buildExpr ( checkedDurationMetric , 'span_name=~"' + name + '"' , request ) ;
durationsBySpanName . push ( metric ) ;
serviceGraphViewMetrics . push ( metric ) ;
} ) ;
}
const serviceMapRequest = makePromServiceMapRequest ( request ) ;
const serviceMapRequest = makePromServiceMapRequest ( request , histogramType ) ;
serviceMapRequest . targets = makeServiceGraphViewRequest ( serviceGraphViewMetrics ) ;
return queryPrometheus ( serviceMapRequest , datasourceUid ) . pipe (
@ -1099,7 +1113,8 @@ function errorAndDurationQuery(
errorRateBySpanName ,
durationsBySpanName ,
datasourceUid ,
tempoDatasourceUid
tempoDatasourceUid ,
histogramType
) ;
if ( serviceGraphView . fields . length === 0 ) {
@ -1146,7 +1161,8 @@ export function getFieldConfig(
targetField : string ,
tempoField : string ,
sourceField? : string ,
namespaceFields ? : { targetNamespace : string ; sourceNamespace? : string }
namespaceFields ? : { targetNamespace : string ; sourceNamespace? : string } ,
histogramType? : string
) {
let source = sourceField ? ` client=" \ ${ $ { sourceField } }", ` : '' ;
let target = ` server=" \ ${ $ { targetField } }" ` ;
@ -1172,12 +1188,7 @@ export function getFieldConfig(
datasourceUid ,
false
) ,
makePromLink (
'Request histogram' ,
` histogram_quantile(0.9, sum(rate( ${ histogramMetric } { ${ source } ${ target } }[ $ __rate_interval])) by (le, client, ${ serverSumBy } )) ` ,
datasourceUid ,
false
) ,
. . . makeHistogramLink ( datasourceUid , source , target , serverSumBy , histogramType ) ,
makePromLink (
'Failed request rate' ,
` sum by (client, ${ serverSumBy } )(rate( ${ failedMetric } { ${ source } ${ target } }[ $ __rate_interval])) ` ,
@ -1194,6 +1205,34 @@ export function getFieldConfig(
} ;
}
export function makeHistogramLink (
datasourceUid : string ,
source : string ,
target : string ,
serverSumBy : string ,
histogramType? : string
) {
const createHistogramLink = ( metric : string , title : string ) = >
makePromLink (
title ,
` histogram_quantile(0.9, sum(rate( ${ metric } { ${ source } ${ target } }[ $ __rate_interval])) by (le, client, ${ serverSumBy } )) ` ,
datasourceUid ,
false
) ;
switch ( histogramType ) {
case 'both' :
return [
createHistogramLink ( histogramMetric , 'Request classic histogram' ) ,
createHistogramLink ( nativeHistogramMetric , 'Request native histogram' ) ,
] ;
case 'native' :
return [ createHistogramLink ( nativeHistogramMetric , 'Request native histogram' ) ] ;
default :
return [ createHistogramLink ( histogramMetric , 'Request classic histogram' ) ] ;
}
}
export function makeTempoLink (
title : string ,
serviceNamespace : string | undefined ,
@ -1300,11 +1339,17 @@ function makeTempoLinkServiceMap(
} ;
}
function makePromServiceMapRequest ( options : DataQueryRequest < TempoQuery > ) : DataQueryRequest < PromQuery > {
export function makePromServiceMapRequest (
options : DataQueryRequest < TempoQuery > ,
histogramType? : string
) : DataQueryRequest < PromQuery > {
return {
. . . options ,
targets : serviceMapMetrics
. map < PromQuery [ ] > ( ( metric ) = > {
if ( histogramType === 'native' && metric . includes ( '_bucket' ) ) {
metric = metric . replace ( '_bucket' , '' ) ;
}
const { serviceMapQuery , serviceMapIncludeNamespace : serviceMapIncludeNamespace } = options . targets [ 0 ] ;
const extraSumByFields = serviceMapIncludeNamespace
? ', client_service_namespace, server_service_namespace'
@ -1345,7 +1390,8 @@ function getServiceGraphViewDataFrames(
errorRateBySpanName : string ,
durationsBySpanName : string [ ] ,
datasourceUid : string ,
tempoDatasourceUid : string
tempoDatasourceUid : string ,
histogramType? : string
) {
let df : any = { fields : [ ] } ;
@ -1470,6 +1516,7 @@ function getServiceGraphViewDataFrames(
}
} ) ;
if ( Object . keys ( durationObj ) . length > 0 ) {
const checkedDurationMetric = histogramType === 'native' ? nativeHistogramDurationMetric : durationMetric ;
df . fields . push ( {
. . . duration [ 0 ] . fields [ 1 ] ,
name : 'Duration (p90)' ,
@ -1478,7 +1525,7 @@ function getServiceGraphViewDataFrames(
links : [
makePromLink (
'Duration' ,
buildLinkExpr ( buildExpr ( durationMetric , 'span_name="${__data.fields[0]}"' , request ) ) ,
buildLinkExpr ( buildExpr ( checke dD urationMetric, 'span_name="${__data.fields[0]}"' , request ) ) ,
datasourceUid ,
false
) ,