mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tempo: TraceQL editor bug fixes (#60414)
* Set width of common columns between trace and span rows * Better syntax highlighting for non string constants * Apply variables to traceql query * Fix test
This commit is contained in:
@@ -13,7 +13,13 @@ import {
|
|||||||
MutableDataFrame,
|
MutableDataFrame,
|
||||||
PluginType,
|
PluginType,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { BackendDataSourceResponse, FetchResponse, setBackendSrv, setDataSourceSrv } from '@grafana/runtime';
|
import {
|
||||||
|
BackendDataSourceResponse,
|
||||||
|
FetchResponse,
|
||||||
|
setBackendSrv,
|
||||||
|
setDataSourceSrv,
|
||||||
|
TemplateSrv,
|
||||||
|
} from '@grafana/runtime';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -49,7 +55,8 @@ describe('Tempo data source', () => {
|
|||||||
beforeEach(() => (console.error = consoleErrorMock));
|
beforeEach(() => (console.error = consoleErrorMock));
|
||||||
|
|
||||||
it('returns empty response when traceId is empty', async () => {
|
it('returns empty response when traceId is empty', async () => {
|
||||||
const ds = new TempoDatasource(defaultSettings);
|
const templateSrv: TemplateSrv = { replace: jest.fn() } as unknown as TemplateSrv;
|
||||||
|
const ds = new TempoDatasource(defaultSettings, templateSrv);
|
||||||
const response = await lastValueFrom(
|
const response = await lastValueFrom(
|
||||||
ds.query({ targets: [{ refId: 'refid1', queryType: 'traceql', query: '' } as Partial<TempoQuery>] } as any),
|
ds.query({ targets: [{ refId: 'refid1', queryType: 'traceql', query: '' } as Partial<TempoQuery>] } as any),
|
||||||
{ defaultValue: 'empty' }
|
{ defaultValue: 'empty' }
|
||||||
|
|||||||
@@ -175,7 +175,8 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
|||||||
}
|
}
|
||||||
if (targets.traceql?.length) {
|
if (targets.traceql?.length) {
|
||||||
try {
|
try {
|
||||||
const queryValue = targets.traceql[0].query;
|
const appliedQuery = this.applyVariables(targets.traceql[0], options.scopedVars);
|
||||||
|
const queryValue = appliedQuery?.query || '';
|
||||||
const hexOnlyRegex = /^[0-9A-Fa-f]*$/;
|
const hexOnlyRegex = /^[0-9A-Fa-f]*$/;
|
||||||
// Check whether this is a trace ID or traceQL query by checking if it only contains hex characters
|
// Check whether this is a trace ID or traceQL query by checking if it only contains hex characters
|
||||||
if (queryValue.trim().match(hexOnlyRegex)) {
|
if (queryValue.trim().match(hexOnlyRegex)) {
|
||||||
|
|||||||
@@ -131,15 +131,15 @@ describe('createTableFrameFromTraceQlQuery()', () => {
|
|||||||
expect(frame.fields[0].values.get(0)).toBe('b1586c3c8c34d');
|
expect(frame.fields[0].values.get(0)).toBe('b1586c3c8c34d');
|
||||||
expect(frame.fields[0].config.unit).toBe('string');
|
expect(frame.fields[0].config.unit).toBe('string');
|
||||||
expect(frame.fields[0].values).toBeInstanceOf(ArrayVector);
|
expect(frame.fields[0].values).toBeInstanceOf(ArrayVector);
|
||||||
// Trace name field
|
|
||||||
expect(frame.fields[1].name).toBe('traceName');
|
|
||||||
expect(frame.fields[1].type).toBe('string');
|
|
||||||
expect(frame.fields[1].values.get(0)).toBe('lb HTTP Client');
|
|
||||||
expect(frame.fields[1].values).toBeInstanceOf(ArrayVector);
|
|
||||||
// Start time field
|
// Start time field
|
||||||
expect(frame.fields[2].name).toBe('startTime');
|
expect(frame.fields[1].name).toBe('startTime');
|
||||||
|
expect(frame.fields[1].type).toBe('string');
|
||||||
|
expect(frame.fields[1].values.get(1)).toBe('2022-01-27 22:56:06');
|
||||||
|
expect(frame.fields[1].values).toBeInstanceOf(ArrayVector);
|
||||||
|
// Trace name field
|
||||||
|
expect(frame.fields[2].name).toBe('traceName');
|
||||||
expect(frame.fields[2].type).toBe('string');
|
expect(frame.fields[2].type).toBe('string');
|
||||||
expect(frame.fields[2].values.get(1)).toBe('2022-01-27 22:56:06');
|
expect(frame.fields[2].values.get(0)).toBe('lb HTTP Client');
|
||||||
expect(frame.fields[2].values).toBeInstanceOf(ArrayVector);
|
expect(frame.fields[2].values).toBeInstanceOf(ArrayVector);
|
||||||
// Duration field
|
// Duration field
|
||||||
expect(frame.fields[3].name).toBe('traceDuration');
|
expect(frame.fields[3].name).toBe('traceDuration');
|
||||||
|
|||||||
@@ -630,6 +630,9 @@ export function createTableFrameFromTraceQlQuery(
|
|||||||
config: {
|
config: {
|
||||||
unit: 'string',
|
unit: 'string',
|
||||||
displayNameFromDS: 'Trace ID',
|
displayNameFromDS: 'Trace ID',
|
||||||
|
custom: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
title: 'Trace: ${__value.raw}',
|
title: 'Trace: ${__value.raw}',
|
||||||
@@ -646,9 +649,28 @@ export function createTableFrameFromTraceQlQuery(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'startTime',
|
||||||
|
type: FieldType.string,
|
||||||
|
config: {
|
||||||
|
displayNameFromDS: 'Start time',
|
||||||
|
custom: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{ name: 'traceName', type: FieldType.string, config: { displayNameFromDS: 'Name' } },
|
{ name: 'traceName', type: FieldType.string, config: { displayNameFromDS: 'Name' } },
|
||||||
{ name: 'startTime', type: FieldType.string, config: { displayNameFromDS: 'Start time' } },
|
{
|
||||||
{ name: 'traceDuration', type: FieldType.number, config: { displayNameFromDS: 'Duration', unit: 'ms' } },
|
name: 'traceDuration',
|
||||||
|
type: FieldType.number,
|
||||||
|
config: {
|
||||||
|
displayNameFromDS: 'Duration',
|
||||||
|
unit: 'ms',
|
||||||
|
custom: {
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
preferredVisualisationType: 'table',
|
preferredVisualisationType: 'table',
|
||||||
@@ -710,6 +732,9 @@ const traceSubFrame = (
|
|||||||
config: {
|
config: {
|
||||||
unit: 'string',
|
unit: 'string',
|
||||||
displayNameFromDS: 'Span ID',
|
displayNameFromDS: 'Span ID',
|
||||||
|
custom: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
title: 'Span: ${__value.raw}',
|
title: 'Span: ${__value.raw}',
|
||||||
@@ -731,21 +756,32 @@ const traceSubFrame = (
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'spanStartTime',
|
||||||
|
type: FieldType.string,
|
||||||
|
config: {
|
||||||
|
displayNameFromDS: 'Start time',
|
||||||
|
custom: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
type: FieldType.string,
|
type: FieldType.string,
|
||||||
config: { displayNameFromDS: 'Name', custom: { hidden: !hasNameAttribute } },
|
config: { displayNameFromDS: 'Name', custom: { hidden: !hasNameAttribute } },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'spanStartTime',
|
|
||||||
type: FieldType.string,
|
|
||||||
config: { displayNameFromDS: 'Start time' },
|
|
||||||
},
|
|
||||||
...Object.values(spanDynamicAttrs),
|
...Object.values(spanDynamicAttrs),
|
||||||
{
|
{
|
||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
config: { displayNameFromDS: 'Duration', unit: 'ns' },
|
config: {
|
||||||
|
displayNameFromDS: 'Duration',
|
||||||
|
unit: 'ns',
|
||||||
|
custom: {
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ const intrinsics = ['duration', 'name', 'status', 'parent'];
|
|||||||
|
|
||||||
const scopes: string[] = ['resource', 'span'];
|
const scopes: string[] = ['resource', 'span'];
|
||||||
|
|
||||||
const booleans = ['false', 'true'];
|
const keywords = intrinsics.concat(scopes);
|
||||||
|
|
||||||
const keywords = intrinsics.concat(scopes).concat(booleans);
|
const statusValues = ['ok', 'unset', 'error', 'false', 'true'];
|
||||||
|
|
||||||
export const language = {
|
export const language = {
|
||||||
ignoreCase: false,
|
ignoreCase: false,
|
||||||
@@ -37,6 +37,7 @@ export const language = {
|
|||||||
|
|
||||||
keywords,
|
keywords,
|
||||||
operators,
|
operators,
|
||||||
|
statusValues,
|
||||||
|
|
||||||
// we include these common regular expressions
|
// we include these common regular expressions
|
||||||
symbols: /[=><!~?:&|+\-*\/^%]+/,
|
symbols: /[=><!~?:&|+\-*\/^%]+/,
|
||||||
@@ -62,6 +63,7 @@ export const language = {
|
|||||||
{
|
{
|
||||||
cases: {
|
cases: {
|
||||||
'@keywords': 'type',
|
'@keywords': 'type',
|
||||||
|
'@statusValues': 'type.identifier',
|
||||||
'@default': 'identifier',
|
'@default': 'identifier',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user