Prometheus: Library fixes for using in external vendor DS (#82115)

* fix stateSlice type errors for build, do not export stateSlice in the future

* fix exports for consistency

* fix package.json for rollup, update licence, keep private

* rollup as devdependencies

* try a different version of @testing-library/dom to try to fix the aria-query issue in drone

* remove testUtils export

* change @testing-library/dom version back

* remove icon bundling, grafana-ui handles this

* remove unused dependencies

* components folder: avoid nested barrel files and use named exports

* configuration folder: avoid nested barrel files and use named exports

* querybuilder folder: avoid nested barrel files and use named exports

* general files: use named exports

* fix loader issue with promql for external ds

* default to support labels match api

* export things necessary for custom config auth

* remove changes to core datasource.test.ts

* Update packages/grafana-prometheus/package.json

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>

* remove icons script, not needed

* update readme, remove references to grafana/ui

* remove private property

* check tests

* remove private property in package.json

* update changelog

* update npm drone script for file checks

* debug why updating test in script broke another library that had never been tested before

* fix npm test for checking licenses

* fix npm test for checking licenses

* fix npm test for checking licenses

* fix npm test for checking licenses

* update license file for npm drone test

* fix bash script

---------

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
Brendan O'Handley
2024-02-16 12:55:39 -06:00
committed by GitHub
parent 0a9389c8f7
commit c6f8462a06
36 changed files with 746 additions and 263 deletions

View File

@ -28,7 +28,7 @@ const CHEAT_SHEET_ITEMS = [
},
];
const PromCheatSheet = (props: QueryEditorHelpProps<PromQuery>) => (
export const PromCheatSheet = (props: QueryEditorHelpProps<PromQuery>) => (
<div>
<h2>PromQL Cheat Sheet</h2>
{CHEAT_SHEET_ITEMS.map((item, index) => (
@ -48,5 +48,3 @@ const PromCheatSheet = (props: QueryEditorHelpProps<PromQuery>) => (
))}
</div>
);
export default PromCheatSheet;

View File

@ -7,7 +7,7 @@ import { PromQueryEditorSelector } from '../querybuilder/components/PromQueryEdi
import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting';
import { PromQueryEditorProps } from './types';
export function PromQueryEditorByApp(props: PromQueryEditorProps) {
function PromQueryEditorByAppBase(props: PromQueryEditorProps) {
const { app } = props;
switch (app) {
@ -18,4 +18,4 @@ export function PromQueryEditorByApp(props: PromQueryEditorProps) {
}
}
export default memo(PromQueryEditorByApp);
export const PromQueryEditorByApp = memo(PromQueryEditorByAppBase);

View File

@ -1,6 +1,6 @@
import React from 'react';
import PromQueryField from './PromQueryField';
import { PromQueryField } from './PromQueryField';
import { PromQueryEditorProps } from './types';
export function PromQueryEditorForAlerting(props: PromQueryEditorProps) {

View File

@ -8,7 +8,7 @@ import { CoreApp, DataFrame, LoadingState, PanelData } from '@grafana/data';
import { PrometheusDatasource } from '../datasource';
import PromQlLanguageProvider from '../language_provider';
import PromQueryField from './PromQueryField';
import { PromQueryField } from './PromQueryField';
import { Props } from './monaco-query-field/MonacoQueryFieldProps';
// the monaco-based editor uses lazy-loading and that does not work

View File

@ -48,7 +48,7 @@ interface PromQueryFieldState {
hint: QueryHint | null;
}
class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryFieldState> {
class PromQueryFieldClass extends React.PureComponent<PromQueryFieldProps, PromQueryFieldState> {
declare languageProviderInitializationPromise: CancelablePromise<any>;
constructor(props: PromQueryFieldProps) {
@ -287,4 +287,4 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
}
}
export default withTheme2(PromQueryField);
export const PromQueryField = withTheme2(PromQueryFieldClass);

View File

@ -1,10 +0,0 @@
export * from './AnnotationQueryEditor';
export * from './PromCheatSheet';
export * from './PrometheusMetricsBrowser';
export * from './PromExemplarField';
export * from './PromExploreExtraField';
export * from './PromQueryEditorByApp';
export * from './PromQueryEditorForAlerting';
export * from './PromQueryField';
export * from './types';
export * from './VariableQueryEditor';

View File

@ -14,6 +14,7 @@ import { Props } from './MonacoQueryFieldProps';
import { getOverrideServices } from './getOverrideServices';
import { getCompletionProvider, getSuggestOptions } from './monaco-completion-provider';
import { placeHolderScopedVars, validateQuery } from './monaco-completion-provider/validation';
import { language, languageConfiguration } from './promql';
const options: monacoTypes.editor.IStandaloneEditorConstructionOptions = {
codeLens: false,
@ -65,13 +66,13 @@ let PROMQL_SETUP_STARTED = false;
function ensurePromQL(monaco: Monaco) {
if (PROMQL_SETUP_STARTED === false) {
PROMQL_SETUP_STARTED = true;
const { aliases, extensions, mimetypes, loader } = promLanguageDefinition;
const { aliases, extensions, mimetypes } = promLanguageDefinition;
monaco.languages.register({ id: PROMQL_LANG_ID, aliases, extensions, mimetypes });
loader().then((mod) => {
monaco.languages.setMonarchTokensProvider(PROMQL_LANG_ID, mod.language);
monaco.languages.setLanguageConfiguration(PROMQL_LANG_ID, mod.languageConfiguration);
});
// @ts-ignore
monaco.languages.setMonarchTokensProvider(PROMQL_LANG_ID, language);
// @ts-ignore
monaco.languages.setLanguageConfiguration(PROMQL_LANG_ID, languageConfiguration);
}
}

View File

@ -0,0 +1,247 @@
// The MIT License (MIT)
//
// Copyright (c) Celian Garcia and Augustin Husson @ Amadeus IT Group
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
'use strict';
// import { languages } from "monaco-editor";
// noinspection JSUnusedGlobalSymbols
export const languageConfiguration = {
// the default separators except `@$`
wordPattern: /(-?\d*\.\d\w*)|([^`~!#%^&*()\-=+\[{\]}\\|;:'",.<>\/?\s]+)/g,
// Not possible to make comments in PromQL syntax
comments: {
lineComment: '#',
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
{ open: '<', close: '>' },
],
folding: {},
};
// PromQL Aggregation Operators
// (https://prometheus.io/docs/prometheus/latest/querying/operators/#aggregation-operators)
const aggregations = [
'sum',
'min',
'max',
'avg',
'group',
'stddev',
'stdvar',
'count',
'count_values',
'bottomk',
'topk',
'quantile',
];
// PromQL functions
// (https://prometheus.io/docs/prometheus/latest/querying/functions/)
const functions = [
'abs',
'absent',
'ceil',
'changes',
'clamp_max',
'clamp_min',
'day_of_month',
'day_of_week',
'days_in_month',
'delta',
'deriv',
'exp',
'floor',
'histogram_quantile',
'holt_winters',
'hour',
'idelta',
'increase',
'irate',
'label_join',
'label_replace',
'ln',
'log2',
'log10',
'minute',
'month',
'predict_linear',
'rate',
'resets',
'round',
'scalar',
'sort',
'sort_desc',
'sqrt',
'time',
'timestamp',
'vector',
'year',
];
// PromQL specific functions: Aggregations over time
// (https://prometheus.io/docs/prometheus/latest/querying/functions/#aggregation_over_time)
const aggregationsOverTime = [];
for (let _i = 0, aggregations_1 = aggregations; _i < aggregations_1.length; _i++) {
let agg = aggregations_1[_i];
aggregationsOverTime.push(agg + '_over_time');
}
// PromQL vector matching + the by and without clauses
// (https://prometheus.io/docs/prometheus/latest/querying/operators/#vector-matching)
const vectorMatching = ['on', 'ignoring', 'group_right', 'group_left', 'by', 'without'];
// Produce a regex matching elements : (elt1|elt2|...)
const vectorMatchingRegex =
'(' +
vectorMatching.reduce(function (prev, curr) {
return prev + '|' + curr;
}) +
')';
// PromQL Operators
// (https://prometheus.io/docs/prometheus/latest/querying/operators/)
const operators = ['+', '-', '*', '/', '%', '^', '==', '!=', '>', '<', '>=', '<=', 'and', 'or', 'unless'];
// PromQL offset modifier
// (https://prometheus.io/docs/prometheus/latest/querying/basics/#offset-modifier)
const offsetModifier = ['offset'];
// Merging all the keywords in one list
const keywords = aggregations
.concat(functions)
.concat(aggregationsOverTime)
.concat(vectorMatching)
.concat(offsetModifier);
// noinspection JSUnusedGlobalSymbols
export const language = {
ignoreCase: false,
defaultToken: '',
tokenPostfix: '.promql',
keywords: keywords,
operators: operators,
vectorMatching: vectorMatchingRegex,
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/^%]+/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
digits: /\d+(_+\d+)*/,
octaldigits: /[0-7]+(_+[0-7]+)*/,
binarydigits: /[0-1]+(_+[0-1]+)*/,
hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,
integersuffix: /(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,
floatsuffix: /[fFlL]?/,
// The main tokenizer for our languages
tokenizer: {
root: [
// 'by', 'without' and vector matching
[/@vectorMatching\s*(?=\()/, 'type', '@clauses'],
// labels
[/[a-z_]\w*(?=\s*(=|!=|=~|!~))/, 'tag'],
// comments
[/(^#.*$)/, 'comment'],
// all keywords have the same color
[
/[a-zA-Z_]\w*/,
{
cases: {
'@keywords': 'type',
'@default': 'identifier',
},
},
],
// strings
[/"([^"\\]|\\.)*$/, 'string.invalid'],
[/'([^'\\]|\\.)*$/, 'string.invalid'],
[/"/, 'string', '@string_double'],
[/'/, 'string', '@string_single'],
[/`/, 'string', '@string_backtick'],
// whitespace
{ include: '@whitespace' },
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[
/@symbols/,
{
cases: {
'@operators': 'delimiter',
'@default': '',
},
},
],
// numbers
[/\d+[smhdwy]/, 'number'],
[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'],
[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'],
[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'],
[/0[0-7']*[0-7](@integersuffix)/, 'number.octal'],
[/0[bB][0-1']*[0-1](@integersuffix)/, 'number.binary'],
[/\d[\d']*\d(@integersuffix)/, 'number'],
[/\d(@integersuffix)/, 'number'],
],
string_double: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/"/, 'string', '@pop'],
],
string_single: [
[/[^\\']+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/'/, 'string', '@pop'],
],
string_backtick: [
[/[^\\`$]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/`/, 'string', '@pop'],
],
clauses: [
[/[^(,)]/, 'tag'],
[/\)/, 'identifier', '@pop'],
],
whitespace: [[/[ \t\r\n]+/, 'white']],
},
};
// noinspection JSUnusedGlobalSymbols
// export const completionItemProvider = {
// provideCompletionItems: function () {
// // To simplify, we made the choice to never create automatically the parenthesis behind keywords
// // It is because in PromQL, some keywords need parenthesis behind, some don't, some can have but it's optional.
// const suggestions = keywords.map(function (value) {
// return {
// label: value,
// kind: languages.CompletionItemKind.Keyword,
// insertText: value,
// insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet
// };
// });
// return { suggestions: suggestions };
// }
// };