Phlare: Transition from LogQL/PromQL to Phlare should keep the query (#60217)

* Transition from LogQL/PromQL to Phlare keeps the query

* Tests
This commit is contained in:
Joey Tawadrous 2023-01-03 10:25:16 +00:00 committed by GitHub
parent 5bceff971d
commit b8618723d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 124 additions and 1 deletions

View File

@ -0,0 +1,66 @@
import { AbstractLabelOperator, DataSourceInstanceSettings, PluginMetaInfo, PluginType } from '@grafana/data';
import { PhlareDataSource } from './datasource';
describe('Phlare data source', () => {
let ds: PhlareDataSource;
beforeEach(() => {
ds = new PhlareDataSource(defaultSettings);
});
describe('importing queries', () => {
it('keeps all labels and values', async () => {
const queries = await ds.importFromAbstractQueries([
{
refId: 'A',
labelMatchers: [
{ name: 'foo', operator: AbstractLabelOperator.Equal, value: 'bar' },
{ name: 'foo2', operator: AbstractLabelOperator.Equal, value: 'bar2' },
],
},
]);
expect(queries[0].labelSelector).toBe('{foo="bar", foo2="bar2"}');
});
});
describe('exporting queries', () => {
it('keeps all labels and values', async () => {
const queries = await ds.exportToAbstractQueries([
{
refId: 'A',
labelSelector: '{foo="bar", foo2="bar2"}',
queryType: 'both',
profileTypeId: '',
groupBy: [''],
},
]);
expect(queries).toMatchObject([
{
refId: 'A',
labelMatchers: [
{ name: 'foo', operator: AbstractLabelOperator.Equal, value: 'bar' },
{ name: 'foo2', operator: AbstractLabelOperator.Equal, value: 'bar2' },
],
},
]);
});
});
});
const defaultSettings: DataSourceInstanceSettings = {
id: 0,
uid: 'phlare',
type: 'profiling',
name: 'phlare',
access: 'proxy',
meta: {
id: 'phlare',
name: 'phlare',
type: PluginType.datasource,
info: {} as PluginMetaInfo,
module: '',
baseUrl: '',
},
jsonData: {},
readOnly: false,
};

View File

@ -1,8 +1,11 @@
import Prism, { Grammar } from 'prismjs';
import { Observable, of } from 'rxjs';
import { DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/data';
import { AbstractQuery, DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/data';
import { DataSourceWithBackend } from '@grafana/runtime';
import { extractLabelMatchers, toPromLikeExpr } from '../prometheus/language_utils';
import { normalizeQuery } from './QueryEditor/QueryEditor';
import { PhlareDataSourceOptions, Query, ProfileTypeMessage, SeriesMessage } from './types';
@ -45,4 +48,58 @@ export class PhlareDataSource extends DataSourceWithBackend<Query, PhlareDataSou
async getLabelNames(): Promise<string[]> {
return await super.getResource('labelNames');
}
async importFromAbstractQueries(abstractQueries: AbstractQuery[]): Promise<Query[]> {
return abstractQueries.map((abstractQuery) => this.importFromAbstractQuery(abstractQuery));
}
importFromAbstractQuery(labelBasedQuery: AbstractQuery): Query {
return {
refId: labelBasedQuery.refId,
labelSelector: toPromLikeExpr(labelBasedQuery),
queryType: 'both',
profileTypeId: '',
groupBy: [''],
};
}
async exportToAbstractQueries(queries: Query[]): Promise<AbstractQuery[]> {
return queries.map((query) => this.exportToAbstractQuery(query));
}
exportToAbstractQuery(query: Query): AbstractQuery {
const phlareQuery = query.labelSelector;
if (!phlareQuery || phlareQuery.length === 0) {
return { refId: query.refId, labelMatchers: [] };
}
const tokens = Prism.tokenize(phlareQuery, grammar);
return {
refId: query.refId,
labelMatchers: extractLabelMatchers(tokens),
};
}
}
const grammar: Grammar = {
'context-labels': {
pattern: /\{[^}]*(?=}?)/,
greedy: true,
inside: {
comment: {
pattern: /#.*/,
},
'label-key': {
pattern: /[a-zA-Z_]\w*(?=\s*(=|!=|=~|!~))/,
alias: 'attr-name',
greedy: true,
},
'label-value': {
pattern: /"(?:\\.|[^\\"])*"/,
greedy: true,
alias: 'attr-value',
},
punctuation: /[{]/,
},
},
punctuation: /[{}(),.]/,
};