123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- import { Registry } from '@grafana/data';
- import { PromVisualQueryOperationCategory } from '../types';
- import { QueryBuilderLabelFilter, QueryBuilderOperation, QueryBuilderOperationDef, VisualQueryModeller } from './types';
- export interface VisualQueryBinary<T> {
- operator: string;
- vectorMatchesType?: 'on' | 'ignoring';
- vectorMatches?: string;
- query: T;
- }
- export interface PromLokiVisualQuery {
- metric?: string;
- labels: QueryBuilderLabelFilter[];
- operations: QueryBuilderOperation[];
- binaryQueries?: Array<VisualQueryBinary<PromLokiVisualQuery>>;
- }
- export abstract class LokiAndPromQueryModellerBase implements VisualQueryModeller {
- protected operationsRegistry: Registry<QueryBuilderOperationDef>;
- private categories: string[] = [];
- constructor(getOperations: () => QueryBuilderOperationDef[]) {
- this.operationsRegistry = new Registry<QueryBuilderOperationDef>(getOperations);
- }
- protected setOperationCategories(categories: string[]) {
- this.categories = categories;
- }
- getOperationsForCategory(category: string) {
- return this.operationsRegistry.list().filter((op) => op.category === category && !op.hideFromList);
- }
- getAlternativeOperations(key: string) {
- return this.operationsRegistry.list().filter((op) => op.alternativesKey && op.alternativesKey === key);
- }
- getCategories() {
- return this.categories;
- }
- getOperationDef(id: string): QueryBuilderOperationDef | undefined {
- return this.operationsRegistry.getIfExists(id);
- }
- renderOperations(queryString: string, operations: QueryBuilderOperation[]) {
- for (const operation of operations) {
- const def = this.operationsRegistry.getIfExists(operation.id);
- if (!def) {
- throw new Error(`Could not find operation ${operation.id} in the registry`);
- }
- queryString = def.renderer(operation, def, queryString);
- }
- return queryString;
- }
- renderBinaryQueries(queryString: string, binaryQueries?: Array<VisualQueryBinary<PromLokiVisualQuery>>) {
- if (binaryQueries) {
- for (const binQuery of binaryQueries) {
- queryString = `${this.renderBinaryQuery(queryString, binQuery)}`;
- }
- }
- return queryString;
- }
- private renderBinaryQuery(leftOperand: string, binaryQuery: VisualQueryBinary<PromLokiVisualQuery>) {
- let result = leftOperand + ` ${binaryQuery.operator} `;
- if (binaryQuery.vectorMatches) {
- result += `${binaryQuery.vectorMatchesType}(${binaryQuery.vectorMatches}) `;
- }
- return result + this.renderQuery(binaryQuery.query, true);
- }
- renderLabels(labels: QueryBuilderLabelFilter[]) {
- if (labels.length === 0) {
- return '';
- }
- let expr = '{';
- for (const filter of labels) {
- if (expr !== '{') {
- expr += ', ';
- }
- expr += `${filter.label}${filter.op}"${filter.value}"`;
- }
- return expr + `}`;
- }
- renderQuery(query: PromLokiVisualQuery, nested?: boolean) {
- let queryString = `${query.metric ?? ''}${this.renderLabels(query.labels)}`;
- queryString = this.renderOperations(queryString, query.operations);
- if (!nested && this.hasBinaryOp(query) && Boolean(query.binaryQueries?.length)) {
- queryString = `(${queryString})`;
- }
- queryString = this.renderBinaryQueries(queryString, query.binaryQueries);
- if (nested && (this.hasBinaryOp(query) || Boolean(query.binaryQueries?.length))) {
- queryString = `(${queryString})`;
- }
- return queryString;
- }
- hasBinaryOp(query: PromLokiVisualQuery): boolean {
- return (
- query.operations.find((op) => {
- const def = this.getOperationDef(op.id);
- return def?.category === PromVisualQueryOperationCategory.BinaryOps;
- }) !== undefined
- );
- }
- }
|