Tempo: Fix type errors that appeared when removing the "any" type from DataQueryResponseData (#75600)

* Tempo: Improving typing of data types

* last fix

* Fix
This commit is contained in:
Torkel Ödegaard 2023-10-11 18:04:54 +02:00 committed by GitHub
parent 7329e2dc62
commit bf7fae4bd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 580 additions and 528 deletions

View File

@ -193,9 +193,7 @@
"footer": {
"countRows": false,
"fields": "",
"reducer": [
"sum"
],
"reducer": ["sum"],
"show": false
},
"showHeader": true

View File

@ -1,425 +1,425 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 2312,
"links": [],
"liveNow": false,
"panels": [
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
"type": "grafana",
"uid": "-- Grafana --"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 1
}
],
"title": "Panel 1",
"type": "timeseries"
},
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 8
},
"id": 2,
"panels": [],
"title": "Expanded row",
"type": "row"
},
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"id": 1,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"refId": "B",
"scenarioId": "random_walk",
"seriesCount": 1
}
],
"title": "Panel 2",
"type": "timeseries"
},
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"id": 6,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"refId": "C",
"scenarioId": "random_walk",
"seriesCount": 1
}
],
"title": "Panel 3",
"type": "timeseries"
},
{
"collapsed": true,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 4,
"panels": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 10
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"title": "Panel inside colapsed row",
"type": "timeseries"
}
],
"title": "Collapsed row",
"type": "row"
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
],
"refresh": "",
"schemaVersion": 38,
"tags": [],
"templating": {
"list": []
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 2312,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 1
}
],
"title": "Panel 1",
"type": "timeseries"
},
"time": {
"from": "now-6h",
"to": "now"
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 8
},
"id": 2,
"panels": [],
"title": "Expanded row",
"type": "row"
},
"timepicker": {},
"timezone": "",
"title": "Snapshots - basic rows",
"uid": "a3b23921-287d-4f90-9a14-c04228057dfa",
"version": 4,
"weekStart": ""
}
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"id": 1,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"refId": "B",
"scenarioId": "random_walk",
"seriesCount": 1
}
],
"title": "Panel 2",
"type": "timeseries"
},
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"id": 6,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"refId": "C",
"scenarioId": "random_walk",
"seriesCount": 1
}
],
"title": "Panel 3",
"type": "timeseries"
},
{
"collapsed": true,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 4,
"panels": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "gdev-testdata"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 10
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"title": "Panel inside colapsed row",
"type": "timeseries"
}
],
"title": "Collapsed row",
"type": "row"
}
],
"refresh": "",
"schemaVersion": 38,
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Snapshots - basic rows",
"uid": "a3b23921-287d-4f90-9a14-c04228057dfa",
"version": 4,
"weekStart": ""
}

View File

@ -232,11 +232,11 @@ describe('Tempo data source', () => {
expect(response.data).toHaveLength(2);
const nodesFrame = response.data[0];
expect(nodesFrame.name).toBe('Nodes');
expect(nodesFrame.meta.preferredVisualisationType).toBe('nodeGraph');
expect(nodesFrame.meta?.preferredVisualisationType).toBe('nodeGraph');
const edgesFrame = response.data[1];
expect(edgesFrame.name).toBe('Edges');
expect(edgesFrame.meta.preferredVisualisationType).toBe('nodeGraph');
expect(edgesFrame.meta?.preferredVisualisationType).toBe('nodeGraph');
});
it('should build search query correctly', () => {
@ -486,67 +486,67 @@ describe('Tempo service graph view', () => {
expect(response.data[0].fields[1].values.length).toBe(2);
expect(response.data[0].fields[1].values[0]).toBe(12.75164671814457);
expect(response.data[0].fields[1].values[1]).toBe(12.121331111401608);
expect(response.data[0].fields[1].config.decimals).toBe(2);
expect(response.data[0].fields[1].config.links[0].title).toBe('Rate');
expect(response.data[0].fields[1].config.links[0].internal.query.expr).toBe(
expect(response.data[0].fields[1]?.config?.decimals).toBe(2);
expect(response.data[0].fields[1]?.config?.links?.[0]?.title).toBe('Rate');
expect(response.data[0].fields[1]?.config?.links?.[0]?.internal?.query.expr).toBe(
'sum(rate(traces_spanmetrics_calls_total{span_name="${__data.fields[0]}"}[$__rate_interval]))'
);
expect(response.data[0].fields[1].config.links[0].internal.query.range).toBe(true);
expect(response.data[0].fields[1].config.links[0].internal.query.exemplar).toBe(true);
expect(response.data[0].fields[1].config.links[0].internal.query.instant).toBe(false);
expect(response.data[0].fields[1]?.config?.links?.[0]?.internal?.query.range).toBe(true);
expect(response.data[0].fields[1]?.config?.links?.[0]?.internal?.query.exemplar).toBe(true);
expect(response.data[0].fields[1]?.config?.links?.[0]?.internal?.query.instant).toBe(false);
expect(response.data[0].fields[2].values.length).toBe(2);
expect(response.data[0].fields[2].values[0]).toBe(12.75164671814457);
expect(response.data[0].fields[2].values[1]).toBe(12.121331111401608);
expect(response.data[0].fields[2].config.color.mode).toBe('continuous-BlPu');
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[2]?.config?.color?.mode).toBe('continuous-BlPu');
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');
expect(response.data[0].fields[3].values.length).toBe(2);
expect(response.data[0].fields[3].values[0]).toBe(3.75164671814457);
expect(response.data[0].fields[3].values[1]).toBe(3.121331111401608);
expect(response.data[0].fields[3].config.decimals).toBe(2);
expect(response.data[0].fields[3].config.links[0].title).toBe('Error Rate');
expect(response.data[0].fields[3].config.links[0].internal.query.expr).toBe(
expect(response.data[0].fields[3]?.config?.decimals).toBe(2);
expect(response.data[0].fields[3]?.config?.links?.[0]?.title).toBe('Error Rate');
expect(response.data[0].fields[3]?.config?.links?.[0]?.internal?.query.expr).toBe(
'sum(rate(traces_spanmetrics_calls_total{status_code="STATUS_CODE_ERROR",span_name="${__data.fields[0]}"}[$__rate_interval]))'
);
expect(response.data[0].fields[3].config.links[0].internal.query.range).toBe(true);
expect(response.data[0].fields[3].config.links[0].internal.query.exemplar).toBe(true);
expect(response.data[0].fields[3].config.links[0].internal.query.instant).toBe(false);
expect(response.data[0].fields[3]?.config?.links?.[0]?.internal?.query.range).toBe(true);
expect(response.data[0].fields[3]?.config?.links?.[0]?.internal?.query.exemplar).toBe(true);
expect(response.data[0].fields[3]?.config?.links?.[0]?.internal?.query.instant).toBe(false);
expect(response.data[0].fields[4].values.length).toBe(2);
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.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[4]?.config?.color?.mode).toBe('continuous-RdYlGr');
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)');
expect(response.data[0].fields[5].values.length).toBe(2);
expect(response.data[0].fields[5].values[0]).toBe('0');
expect(response.data[0].fields[5].values[1]).toBe(0.12003505696757232);
expect(response.data[0].fields[5].config.unit).toBe('s');
expect(response.data[0].fields[5].config.links[0].title).toBe('Duration');
expect(response.data[0].fields[5].config.links[0].internal.query.expr).toBe(
expect(response.data[0].fields[5]?.config?.unit).toBe('s');
expect(response.data[0].fields[5]?.config?.links?.[0]?.title).toBe('Duration');
expect(response.data[0].fields[5]?.config?.links?.[0]?.internal?.query.expr).toBe(
'histogram_quantile(.9, sum(rate(traces_spanmetrics_latency_bucket{span_name="${__data.fields[0]}"}[$__rate_interval])) by (le))'
);
expect(response.data[0].fields[5].config.links[0].internal.query.range).toBe(true);
expect(response.data[0].fields[5].config.links[0].internal.query.exemplar).toBe(true);
expect(response.data[0].fields[5].config.links[0].internal.query.instant).toBe(false);
expect(response.data[0].fields[5]?.config?.links?.[0]?.internal?.query.range).toBe(true);
expect(response.data[0].fields[5]?.config?.links?.[0]?.internal?.query.exemplar).toBe(true);
expect(response.data[0].fields[5]?.config?.links?.[0]?.internal?.query.instant).toBe(false);
expect(response.data[0].fields[6].config.links[0].url).toBe('');
expect(response.data[0].fields[6].config.links[0].title).toBe('Tempo');
expect(response.data[0].fields[6].config.links[0].internal.query.queryType).toBe('traceqlSearch');
expect(response.data[0].fields[6].config.links[0].internal.query.filters[0].value).toBe('${__data.fields[0]}');
expect(response.data[0].fields[6]?.config?.links?.[0].url).toBe('');
expect(response.data[0].fields[6]?.config?.links?.[0].title).toBe('Tempo');
expect(response.data[0].fields[6]?.config?.links?.[0].internal.query.queryType).toBe('traceqlSearch');
expect(response.data[0].fields[6]?.config?.links?.[0].internal.query.filters[0].value).toBe('${__data.fields[0]}');
// Service graph
expect(response.data[1].name).toBe('Nodes');
expect(response.data[1].fields[0].values.length).toBe(3);
expect(response.data[1].fields[0].config.links.length).toBeGreaterThan(0);
expect(response.data[1].fields[0].config.links).toEqual(serviceGraphLinks);
expect(response.data[1].fields[0]?.config?.links?.length).toBeGreaterThan(0);
expect(response.data[1].fields[0]?.config?.links).toEqual(serviceGraphLinks);
expect(response.data[2].name).toBe('Edges');
expect(response.data[2].fields[0].values.length).toBe(2);
@ -804,7 +804,7 @@ describe('Tempo service graph view', () => {
fields: [
{
name: 'Time',
type: 'time',
type: FieldType.time,
config: {},
values: [1653828275000, 1653828275000, 1653828275000, 1653828275000, 1653828275000],
},
@ -813,12 +813,14 @@ describe('Tempo service graph view', () => {
config: {
filterable: true,
},
type: 'string',
type: FieldType.string,
values: ['HTTP Client', 'HTTP GET', 'HTTP GET - root', 'HTTP POST', 'HTTP POST - post'],
},
],
values: [],
},
];
const objToAlign = {
'HTTP GET - root': {
value: '0.1234',

View File

@ -6,13 +6,13 @@ import semver from 'semver';
import {
CoreApp,
DataFrame,
DataFrameDTO,
DataQueryRequest,
DataQueryResponse,
DataQueryResponseData,
DataSourceApi,
DataSourceInstanceSettings,
dateTime,
Field,
FieldType,
isValidGoDuration,
LoadingState,
@ -86,6 +86,17 @@ const featuresToTempoVersion = {
// This is the last minor version of Tempo that does not expose the endpoint for build information.
const defaultTempoVersion = '2.1.0';
interface ServiceMapQueryResponse {
nodes: DataFrame;
edges: DataFrame;
}
interface ServiceMapQueryResponseWithRates {
rates: Array<DataFrame | DataFrameDTO>;
nodes: DataFrame;
edges: DataFrame;
}
export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJsonData> {
tracesToLogs?: TraceToLogsOptions;
serviceMap?: {
@ -783,7 +794,11 @@ function queryPrometheus(request: DataQueryRequest<PromQuery>, datasourceUid: st
);
}
function serviceMapQuery(request: DataQueryRequest<TempoQuery>, datasourceUid: string, tempoDatasourceUid: string) {
function serviceMapQuery(
request: DataQueryRequest<TempoQuery>,
datasourceUid: string,
tempoDatasourceUid: string
): Observable<ServiceMapQueryResponse> {
const serviceMapRequest = makePromServiceMapRequest(request);
return queryPrometheus(serviceMapRequest, datasourceUid).pipe(
@ -849,7 +864,8 @@ function serviceMapQuery(request: DataQueryRequest<TempoQuery>, datasourceUid: s
}
return {
data: [nodes, edges],
nodes,
edges,
state: LoadingState.Done,
};
})
@ -858,9 +874,9 @@ function serviceMapQuery(request: DataQueryRequest<TempoQuery>, datasourceUid: s
function rateQuery(
request: DataQueryRequest<TempoQuery>,
serviceMapResponse: DataQueryResponse,
serviceMapResponse: ServiceMapQueryResponse,
datasourceUid: string
) {
): Observable<ServiceMapQueryResponseWithRates> {
const serviceMapRequest = makePromServiceMapRequest(request);
serviceMapRequest.targets = makeServiceGraphViewRequest([buildExpr(rateMetric, defaultTableFilter, request)]);
@ -872,8 +888,9 @@ function rateQuery(
throw new Error(getErrorMessage(errorRes.error?.message));
}
return {
data: [responses[0]?.data ?? [], serviceMapResponse.data[0], serviceMapResponse.data[1]],
state: LoadingState.Done,
rates: responses[0]?.data ?? [],
nodes: serviceMapResponse.nodes,
edges: serviceMapResponse.edges,
};
})
);
@ -883,7 +900,7 @@ function rateQuery(
// -> which determine the errorRate/duration span_name(s) we need to query
function errorAndDurationQuery(
request: DataQueryRequest<TempoQuery>,
rateResponse: DataQueryResponse,
rateResponse: ServiceMapQueryResponseWithRates,
datasourceUid: string,
tempoDatasourceUid: string
) {
@ -892,14 +909,14 @@ function errorAndDurationQuery(
let durationsBySpanName: string[] = [];
let labels = [];
if (rateResponse.data[0][0] && request.app === CoreApp.Explore) {
const spanNameField = rateResponse.data[0][0].fields.find((field: Field) => field.name === 'span_name');
if (rateResponse.rates[0] && request.app === CoreApp.Explore) {
const spanNameField = rateResponse.rates[0].fields.find((field) => field.name === 'span_name');
if (spanNameField && spanNameField.values) {
labels = spanNameField.values;
}
} else if (rateResponse.data[0]) {
rateResponse.data[0].map((df: DataFrame) => {
const spanNameLabels = df.fields.find((field: Field) => field.labels?.['span_name']);
} else if (rateResponse.rates) {
rateResponse.rates.map((df: DataFrame | DataFrameDTO) => {
const spanNameLabels = df.fields.find((field) => field.labels?.['span_name']);
if (spanNameLabels) {
labels.push(spanNameLabels.labels?.['span_name']);
}
@ -941,13 +958,13 @@ function errorAndDurationQuery(
if (serviceGraphView.fields.length === 0) {
return {
data: [rateResponse.data[1], rateResponse.data[2]],
data: [rateResponse.nodes, rateResponse.edges],
state: LoadingState.Done,
};
}
return {
data: [serviceGraphView, rateResponse.data[1], rateResponse.data[2]],
data: [serviceGraphView, rateResponse.nodes, rateResponse.edges],
state: LoadingState.Done,
};
})
@ -1078,7 +1095,7 @@ function makePromServiceMapRequest(options: DataQueryRequest<TempoQuery>): DataQ
function getServiceGraphView(
request: DataQueryRequest<TempoQuery>,
rateResponse: DataQueryResponse,
rateResponse: ServiceMapQueryResponseWithRates,
secondResponse: DataQueryResponse,
errorRateBySpanName: string,
durationsBySpanName: string[],
@ -1086,14 +1103,15 @@ function getServiceGraphView(
tempoDatasourceUid: string
) {
let df: any = { fields: [] };
const rate = rateResponse.data[0]?.filter((x: { refId: string }) => {
const rate = rateResponse.rates.filter((x) => {
return x.refId === buildExpr(rateMetric, defaultTableFilter, request);
});
const errorRate = secondResponse.data.filter((x) => {
return x.refId === errorRateBySpanName;
});
const duration = secondResponse.data.filter((x) => {
return durationsBySpanName.includes(x.refId);
return durationsBySpanName.includes(x.refId ?? '');
});
if (rate.length > 0 && rate[0].fields?.length > 2) {
@ -1193,7 +1211,7 @@ function getServiceGraphView(
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] };
durationObj[name!] = { value: d.fields[1].values[0] };
}
});
if (Object.keys(durationObj).length > 0) {

View File

@ -8,6 +8,7 @@ import {
NodeGraphDataFrameFieldNames as Fields,
TimeRange,
FieldType,
toDataFrame,
} from '@grafana/data';
import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '../../../core/utils/tracing';
@ -189,39 +190,53 @@ function createServiceMapDataFrames() {
}
const nodes = createDF('Nodes', [
{ name: Fields.id, type: FieldType.string },
{ name: Fields.title, type: FieldType.string, config: { displayName: 'Service name' } },
{ name: Fields.subTitle, type: FieldType.string, config: { displayName: 'Service namespace' } },
{ name: Fields.mainStat, type: FieldType.number, config: { unit: 'ms/r', displayName: 'Average response time' } },
{ name: Fields.id, type: FieldType.string, values: [] },
{ name: Fields.title, type: FieldType.string, config: { displayName: 'Service name' }, values: [] },
{ name: Fields.subTitle, type: FieldType.string, config: { displayName: 'Service namespace' }, values: [] },
{
name: Fields.mainStat,
type: FieldType.number,
config: { unit: 'ms/r', displayName: 'Average response time' },
values: [],
},
{
name: Fields.secondaryStat,
type: FieldType.number,
config: { unit: 'r/sec', displayName: 'Requests per second' },
values: [],
},
{
name: Fields.arc + 'success',
type: FieldType.number,
config: { displayName: 'Success', color: { fixedColor: 'green', mode: FieldColorModeId.Fixed } },
values: [],
},
{
name: Fields.arc + 'failed',
type: FieldType.number,
config: { displayName: 'Failed', color: { fixedColor: 'red', mode: FieldColorModeId.Fixed } },
values: [],
},
]);
const edges = createDF('Edges', [
{ name: Fields.id, type: FieldType.string },
{ name: Fields.source, type: FieldType.string },
{ name: AdditionalEdgeFields.sourceName, type: FieldType.string },
{ name: AdditionalEdgeFields.sourceNamespace, type: FieldType.string },
{ name: Fields.target, type: FieldType.string },
{ name: AdditionalEdgeFields.targetName, type: FieldType.string },
{ name: AdditionalEdgeFields.targetNamespace, type: FieldType.string },
{ name: Fields.mainStat, type: FieldType.number, config: { unit: 'ms/r', displayName: 'Average response time' } },
{ name: Fields.id, type: FieldType.string, values: [] },
{ name: Fields.source, type: FieldType.string, values: [] },
{ name: AdditionalEdgeFields.sourceName, type: FieldType.string, values: [] },
{ name: AdditionalEdgeFields.sourceNamespace, type: FieldType.string, values: [] },
{ name: Fields.target, type: FieldType.string, values: [] },
{ name: AdditionalEdgeFields.targetName, type: FieldType.string, values: [] },
{ name: AdditionalEdgeFields.targetNamespace, type: FieldType.string, values: [] },
{
name: Fields.mainStat,
type: FieldType.number,
config: { unit: 'ms/r', displayName: 'Average response time' },
values: [],
},
{
name: Fields.secondaryStat,
type: FieldType.number,
config: { unit: 'r/sec', displayName: 'Requests per second' },
values: [],
},
]);
@ -234,8 +249,9 @@ function createServiceMapDataFrames() {
* @param responses
*/
function getMetricFrames(responses: DataQueryResponse[]): Record<string, DataFrameView> {
return responses[0].data.reduce<Record<string, DataFrameView>>((acc, frame) => {
acc[frame.refId] = new DataFrameView(frame);
return responses[0].data.reduce<Record<string, DataFrameView>>((acc, frameDTO) => {
const frame = toDataFrame(frameDTO);
acc[frame.refId ?? 'A'] = new DataFrameView(frame);
return acc;
}, {});
}

View File

@ -60,6 +60,7 @@ export function createTableFrameFromMetricsSummaryQuery(
name: `${series.key}`,
type: FieldType.string,
config: getConfig(series, configQuery, instanceSettings),
values: [],
};
});
});

View File

@ -16,6 +16,8 @@ import {
createDataFrame,
getDisplayProcessor,
createTheme,
DataFrameDTO,
toDataFrame,
} from '@grafana/data';
import { SearchTableType } from './dataquery.gen';
@ -23,7 +25,7 @@ import { createGraphFrames } from './graphTransform';
import { Span, SpanAttributes, Spanset, TraceSearchMetadata } from './types';
export function createTableFrame(
logsFrame: DataFrame,
logsFrame: DataFrame | DataFrameDTO,
datasourceUid: string,
datasourceName: string,
traceRegexs: string[]
@ -38,6 +40,7 @@ export function createTableFrame(
width: 200,
},
},
values: [],
},
{
name: 'traceID',
@ -59,10 +62,12 @@ export function createTableFrame(
},
],
},
values: [],
},
{
name: 'Message',
type: FieldType.string,
values: [],
},
],
meta: {
@ -80,7 +85,7 @@ export function createTableFrame(
for (let field of logsFrame.fields) {
let hasMatch = false;
if (field.type === FieldType.string) {
const values = field.values;
const values = field.values!;
for (let i = 0; i < values.length; i++) {
const line = values[i];
if (line) {
@ -88,7 +93,7 @@ export function createTableFrame(
const match = line.match(traceRegex);
if (match) {
const traceId = match[1];
const time = timeField ? timeField.values[i] : null;
const time = timeField ? timeField.values![i] : null;
tableFrame.fields[0].values.push(time);
tableFrame.fields[1].values.push(traceId);
tableFrame.fields[2].values.push(line);
@ -226,23 +231,23 @@ export function transformFromOTLP(
): DataQueryResponse {
const frame = new MutableDataFrame({
fields: [
{ name: 'traceID', type: FieldType.string },
{ name: 'spanID', type: FieldType.string },
{ name: 'parentSpanID', type: FieldType.string },
{ name: 'operationName', type: FieldType.string },
{ name: 'serviceName', type: FieldType.string },
{ name: 'kind', type: FieldType.string },
{ name: 'statusCode', type: FieldType.number },
{ name: 'statusMessage', type: FieldType.string },
{ name: 'instrumentationLibraryName', type: FieldType.string },
{ name: 'instrumentationLibraryVersion', type: FieldType.string },
{ name: 'traceState', type: FieldType.string },
{ name: 'serviceTags', type: FieldType.other },
{ name: 'startTime', type: FieldType.number },
{ name: 'duration', type: FieldType.number },
{ name: 'logs', type: FieldType.other },
{ name: 'references', type: FieldType.other },
{ name: 'tags', type: FieldType.other },
{ name: 'traceID', type: FieldType.string, values: [] },
{ name: 'spanID', type: FieldType.string, values: [] },
{ name: 'parentSpanID', type: FieldType.string, values: [] },
{ name: 'operationName', type: FieldType.string, values: [] },
{ name: 'serviceName', type: FieldType.string, values: [] },
{ name: 'kind', type: FieldType.string, values: [] },
{ name: 'statusCode', type: FieldType.number, values: [] },
{ name: 'statusMessage', type: FieldType.string, values: [] },
{ name: 'instrumentationLibraryName', type: FieldType.string, values: [] },
{ name: 'instrumentationLibraryVersion', type: FieldType.string, values: [] },
{ name: 'traceState', type: FieldType.string, values: [] },
{ name: 'serviceTags', type: FieldType.other, values: [] },
{ name: 'startTime', type: FieldType.number, values: [] },
{ name: 'duration', type: FieldType.number, values: [] },
{ name: 'logs', type: FieldType.other, values: [] },
{ name: 'references', type: FieldType.other, values: [] },
{ name: 'tags', type: FieldType.other, values: [] },
],
meta: {
preferredVisualisationType: 'trace',
@ -487,7 +492,7 @@ function getOTLPReferences(
}
export function transformTrace(response: DataQueryResponse, nodeGraph = false): DataQueryResponse {
const frame: DataFrame = response.data[0];
const frame = response.data[0];
if (!frame) {
return emptyDataQueryResponse;
@ -495,7 +500,7 @@ export function transformTrace(response: DataQueryResponse, nodeGraph = false):
let data = [...response.data];
if (nodeGraph) {
data.push(...createGraphFrames(frame));
data.push(...createGraphFrames(toDataFrame(frame)));
}
return {
@ -512,6 +517,7 @@ export function createTableFrameFromSearch(data: TraceSearchMetadata[], instance
{
name: 'traceID',
type: FieldType.string,
values: [],
config: {
unit: 'string',
displayNameFromDS: 'Trace ID',
@ -531,10 +537,15 @@ export function createTableFrameFromSearch(data: TraceSearchMetadata[], instance
],
},
},
{ name: 'traceService', type: FieldType.string, config: { displayNameFromDS: 'Trace service' } },
{ name: 'traceName', type: FieldType.string, config: { displayNameFromDS: 'Trace name' } },
{ name: 'startTime', type: FieldType.time, config: { displayNameFromDS: 'Start time' } },
{ name: 'traceDuration', type: FieldType.number, config: { displayNameFromDS: 'Duration', unit: 'ms' } },
{ name: 'traceService', type: FieldType.string, config: { displayNameFromDS: 'Trace service' }, values: [] },
{ name: 'traceName', type: FieldType.string, config: { displayNameFromDS: 'Trace name' }, values: [] },
{ name: 'startTime', type: FieldType.time, config: { displayNameFromDS: 'Start time' }, values: [] },
{
name: 'traceDuration',
type: FieldType.number,
config: { displayNameFromDS: 'Duration', unit: 'ms' },
values: [],
},
],
meta: {
preferredVisualisationType: 'table',
@ -826,6 +837,7 @@ const traceSubFrame = (
name: attr.key,
type: FieldType.string,
config: { displayNameFromDS: attr.key },
values: [],
};
});
spanSet.spans.forEach((span) => {
@ -837,6 +849,7 @@ const traceSubFrame = (
name: attr.key,
type: FieldType.string,
config: { displayNameFromDS: attr.key },
values: [],
};
});
});
@ -849,10 +862,12 @@ const traceSubFrame = (
config: {
custom: { hidden: true },
},
values: [],
},
{
name: 'spanID',
type: FieldType.string,
values: [],
config: {
unit: 'string',
displayNameFromDS: 'Span ID',
@ -893,12 +908,14 @@ const traceSubFrame = (
{
name: 'name',
type: FieldType.string,
values: [],
config: { displayNameFromDS: 'Name', custom: { hidden: !hasNameAttribute } },
},
...Object.values(spanDynamicAttrs).sort((a, b) => a.name.localeCompare(b.name)),
{
name: 'duration',
type: FieldType.number,
values: [],
config: {
displayNameFromDS: 'Duration',
unit: 'ns',

View File

@ -1,7 +1,7 @@
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { DataQueryRequest, DataQueryResponse, CustomVariableSupport } from '@grafana/data';
import { DataQueryRequest, CustomVariableSupport, MetricFindValue } from '@grafana/data';
import { TempoVariableQuery, TempoVariableQueryEditor } from './VariableQueryEditor';
import { TempoDatasource } from './datasource';
@ -13,7 +13,7 @@ export class TempoVariableSupport extends CustomVariableSupport<TempoDatasource,
super();
}
query(request: DataQueryRequest<TempoVariableQuery>): Observable<DataQueryResponse> {
query(request: DataQueryRequest<TempoVariableQuery>): Observable<{ data: MetricFindValue[] }> {
if (!this.datasource) {
throw new Error('Datasource not initialized');
}

View File

@ -9,16 +9,16 @@ export function transformResponse(zSpans: ZipkinSpan[]): DataFrame {
const spanRows = zSpans.map(transformSpan);
const frame = new MutableDataFrame({
fields: [
{ name: 'traceID', type: FieldType.string },
{ name: 'spanID', type: FieldType.string },
{ name: 'parentSpanID', type: FieldType.string },
{ name: 'operationName', type: FieldType.string },
{ name: 'serviceName', type: FieldType.string },
{ name: 'serviceTags', type: FieldType.other },
{ name: 'startTime', type: FieldType.number },
{ name: 'duration', type: FieldType.number },
{ name: 'logs', type: FieldType.other },
{ name: 'tags', type: FieldType.other },
{ name: 'traceID', type: FieldType.string, values: [] },
{ name: 'spanID', type: FieldType.string, values: [] },
{ name: 'parentSpanID', type: FieldType.string, values: [] },
{ name: 'operationName', type: FieldType.string, values: [] },
{ name: 'serviceName', type: FieldType.string, values: [] },
{ name: 'serviceTags', type: FieldType.other, values: [] },
{ name: 'startTime', type: FieldType.number, values: [] },
{ name: 'duration', type: FieldType.number, values: [] },
{ name: 'logs', type: FieldType.other, values: [] },
{ name: 'tags', type: FieldType.other, values: [] },
],
meta: {
preferredVisualisationType: 'trace',