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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 746 additions and 263 deletions

View File

@ -1,3 +1,3 @@
# (2023-06-11) # (2024-02-16)
First public release First public release. This release provides Prometheus exports in Grafana. Please be aware this is in the alpha state and there is likely to be breaking changes.

View File

@ -8,6 +8,6 @@ See [package source](https://github.com/grafana/grafana/tree/main/packages/grafa
## Installation ## Installation
`yarn add @grafana/ui` `yarn add @grafana/prometheus`
`npm install @grafana/ui` `npm install @grafana/prometheus`

View File

@ -1,9 +1,8 @@
{ {
"author": "Grafana Labs", "author": "Grafana Labs",
"license": "Apache-2.0", "license": "AGPL-3.0-only",
"name": "@grafana/prometheus", "name": "@grafana/prometheus",
"private": true, "version": "10.4.0-pre",
"version": "0.0.1",
"description": "Grafana Prometheus Library", "description": "Grafana Prometheus Library",
"keywords": [ "keywords": [
"typescript" "typescript"
@ -17,13 +16,24 @@
"main": "src/index.ts", "main": "src/index.ts",
"types": "src/index.ts", "types": "src/index.ts",
"files": [ "files": [
"dist", "./dist",
"./README.md", "./README.md",
"./CHANGELOG.md", "./CHANGELOG.md",
"LICENSE" "./LICENSE_AGPL"
], ],
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"access": "public"
},
"scripts": { "scripts": {
"typecheck": "tsc --emitDeclarationOnly false --noEmit" "build": "tsc -p ./tsconfig.build.json && rollup -c rollup.config.ts",
"bundle": "rollup -c rollup.config.ts",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"postpack": "mv package.json.bak package.json"
}, },
"dependencies": { "dependencies": {
"@emotion/css": "11.11.2", "@emotion/css": "11.11.2",
@ -69,7 +79,9 @@
"@grafana/e2e": "workspace:*", "@grafana/e2e": "workspace:*",
"@grafana/e2e-selectors": "workspace:*", "@grafana/e2e-selectors": "workspace:*",
"@grafana/tsconfig": "^1.3.0-rc1", "@grafana/tsconfig": "^1.3.0-rc1",
"@swc/core": "1.4.1", "@rollup/plugin-image": "3.0.3",
"@rollup/plugin-node-resolve": "15.2.3",
"@swc/core": "1.4.0",
"@swc/helpers": "0.5.6", "@swc/helpers": "0.5.6",
"@testing-library/dom": "9.3.4", "@testing-library/dom": "9.3.4",
"@testing-library/jest-dom": "6.4.2", "@testing-library/jest-dom": "6.4.2",
@ -118,6 +130,10 @@
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-select-event": "5.5.1", "react-select-event": "5.5.1",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"rollup": "2.79.1",
"rollup-plugin-dts": "^5.0.0",
"rollup-plugin-esbuild": "5.0.0",
"rollup-plugin-node-externals": "^5.0.0",
"sass": "1.70.0", "sass": "1.70.0",
"sass-loader": "13.3.2", "sass-loader": "13.3.2",
"style-loader": "3.3.4", "style-loader": "3.3.4",

View File

@ -0,0 +1,38 @@
import image from '@rollup/plugin-image';
import resolve from '@rollup/plugin-node-resolve';
import path from 'path';
import dts from 'rollup-plugin-dts';
import esbuild from 'rollup-plugin-esbuild';
import { externals } from 'rollup-plugin-node-externals';
const pkg = require('./package.json');
export default [
{
input: 'src/index.ts',
plugins: [externals({ deps: true, packagePath: './package.json' }), resolve(), esbuild(), image()],
output: [
{
format: 'cjs',
sourcemap: true,
dir: path.dirname(pkg.publishConfig.main),
},
{
format: 'esm',
sourcemap: true,
dir: path.dirname(pkg.publishConfig.module),
preserveModules: true,
// @ts-expect-error (TS cannot assure that `process.env.PROJECT_CWD` is a string)
preserveModulesRoot: path.join(process.env.PROJECT_CWD, `packages/grafana-prometheus/src`),
},
],
},
{
input: './compiled/index.d.ts',
plugins: [dts()],
output: {
file: pkg.publishConfig.types,
format: 'es',
},
},
];

View File

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

View File

@ -7,7 +7,7 @@ import { PromQueryEditorSelector } from '../querybuilder/components/PromQueryEdi
import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting'; import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting';
import { PromQueryEditorProps } from './types'; import { PromQueryEditorProps } from './types';
export function PromQueryEditorByApp(props: PromQueryEditorProps) { function PromQueryEditorByAppBase(props: PromQueryEditorProps) {
const { app } = props; const { app } = props;
switch (app) { 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 React from 'react';
import PromQueryField from './PromQueryField'; import { PromQueryField } from './PromQueryField';
import { PromQueryEditorProps } from './types'; import { PromQueryEditorProps } from './types';
export function PromQueryEditorForAlerting(props: PromQueryEditorProps) { export function PromQueryEditorForAlerting(props: PromQueryEditorProps) {

View File

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

View File

@ -48,7 +48,7 @@ interface PromQueryFieldState {
hint: QueryHint | null; hint: QueryHint | null;
} }
class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryFieldState> { class PromQueryFieldClass extends React.PureComponent<PromQueryFieldProps, PromQueryFieldState> {
declare languageProviderInitializationPromise: CancelablePromise<any>; declare languageProviderInitializationPromise: CancelablePromise<any>;
constructor(props: PromQueryFieldProps) { 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 { getOverrideServices } from './getOverrideServices';
import { getCompletionProvider, getSuggestOptions } from './monaco-completion-provider'; import { getCompletionProvider, getSuggestOptions } from './monaco-completion-provider';
import { placeHolderScopedVars, validateQuery } from './monaco-completion-provider/validation'; import { placeHolderScopedVars, validateQuery } from './monaco-completion-provider/validation';
import { language, languageConfiguration } from './promql';
const options: monacoTypes.editor.IStandaloneEditorConstructionOptions = { const options: monacoTypes.editor.IStandaloneEditorConstructionOptions = {
codeLens: false, codeLens: false,
@ -65,13 +66,13 @@ let PROMQL_SETUP_STARTED = false;
function ensurePromQL(monaco: Monaco) { function ensurePromQL(monaco: Monaco) {
if (PROMQL_SETUP_STARTED === false) { if (PROMQL_SETUP_STARTED === false) {
PROMQL_SETUP_STARTED = true; 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 }); monaco.languages.register({ id: PROMQL_LANG_ID, aliases, extensions, mimetypes });
loader().then((mod) => { // @ts-ignore
monaco.languages.setMonarchTokensProvider(PROMQL_LANG_ID, mod.language); monaco.languages.setMonarchTokensProvider(PROMQL_LANG_ID, language);
monaco.languages.setLanguageConfiguration(PROMQL_LANG_ID, mod.languageConfiguration); // @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 };
// }
// };

View File

@ -9,7 +9,7 @@ import { Alert, FieldValidationMessage, useTheme2 } from '@grafana/ui';
import { PromOptions } from '../types'; import { PromOptions } from '../types';
import { AlertingSettingsOverhaul } from './AlertingSettingsOverhaul'; import { AlertingSettingsOverhaul } from './AlertingSettingsOverhaul';
import { DataSourcehttpSettingsOverhaul } from './DataSourceHttpSettingsOverhaul'; import { DataSourceHttpSettingsOverhaul } from './DataSourceHttpSettingsOverhaul';
import { PromSettings } from './PromSettings'; import { PromSettings } from './PromSettings';
export const PROM_CONFIG_LABEL_WIDTH = 30; export const PROM_CONFIG_LABEL_WIDTH = 30;
@ -33,7 +33,7 @@ export const ConfigEditor = (props: PrometheusConfigProps) => {
docsLink="https://grafana.com/docs/grafana/latest/datasources/prometheus/configure-prometheus-data-source/" docsLink="https://grafana.com/docs/grafana/latest/datasources/prometheus/configure-prometheus-data-source/"
/> />
<hr className={`${styles.hrTopSpace} ${styles.hrBottomSpace}`} /> <hr className={`${styles.hrTopSpace} ${styles.hrBottomSpace}`} />
<DataSourcehttpSettingsOverhaul <DataSourceHttpSettingsOverhaul
options={options} options={options}
onOptionsChange={onOptionsChange} onOptionsChange={onOptionsChange}
secureSocksDSProxyEnabled={config.secureSocksDSProxyEnabled} secureSocksDSProxyEnabled={config.secureSocksDSProxyEnabled}

View File

@ -8,13 +8,13 @@ import { PromOptions } from '../types';
import { docsTip, overhaulStyles } from './ConfigEditor'; import { docsTip, overhaulStyles } from './ConfigEditor';
type Props = { export type DataSourceHttpSettingsProps = {
options: DataSourceSettings<PromOptions, {}>; options: DataSourceSettings<PromOptions, {}>;
onOptionsChange: (options: DataSourceSettings<PromOptions, {}>) => void; onOptionsChange: (options: DataSourceSettings<PromOptions, {}>) => void;
secureSocksDSProxyEnabled: boolean; secureSocksDSProxyEnabled: boolean;
}; };
export const DataSourcehttpSettingsOverhaul = (props: Props) => { export const DataSourceHttpSettingsOverhaul = (props: DataSourceHttpSettingsProps) => {
const { options, onOptionsChange, secureSocksDSProxyEnabled } = props; const { options, onOptionsChange, secureSocksDSProxyEnabled } = props;
const newAuthProps = convertLegacyAuthProps({ const newAuthProps = convertLegacyAuthProps({

View File

@ -16,7 +16,7 @@ type Props = {
disabled?: boolean; disabled?: boolean;
}; };
export default function ExemplarSetting({ value, onChange, onDelete, disabled }: Props) { export function ExemplarSetting({ value, onChange, onDelete, disabled }: Props) {
const [isInternalLink, setIsInternalLink] = useState(Boolean(value.datasourceUid)); const [isInternalLink, setIsInternalLink] = useState(Boolean(value.datasourceUid));
const theme = useTheme2(); const theme = useTheme2();

View File

@ -8,7 +8,7 @@ import { Button, useTheme2 } from '@grafana/ui';
import { ExemplarTraceIdDestination } from '../types'; import { ExemplarTraceIdDestination } from '../types';
import { overhaulStyles } from './ConfigEditor'; import { overhaulStyles } from './ConfigEditor';
import ExemplarSetting from './ExemplarSetting'; import { ExemplarSetting } from './ExemplarSetting';
type Props = { type Props = {
options?: ExemplarTraceIdDestination[]; options?: ExemplarTraceIdDestination[];

View File

@ -1,7 +0,0 @@
export * from './AlertingSettingsOverhaul';
export * from './ConfigEditor';
export * from './DataSourceHttpSettingsOverhaul';
export * from './ExemplarSetting';
export * from './ExemplarsSettings';
export * from './PromFlavorVersions';
export * from './PromSettings';

View File

@ -24,7 +24,7 @@ import {
prometheusSpecialRegexEscape, prometheusSpecialRegexEscape,
} from './datasource'; } from './datasource';
import PromQlLanguageProvider from './language_provider'; import PromQlLanguageProvider from './language_provider';
import { PrometheusCacheLevel, PromOptions, PromQuery, PromQueryRequest } from './types'; import { PromApplication, PrometheusCacheLevel, PromOptions, PromQuery, PromQueryRequest } from './types';
const fetchMock = jest.fn().mockReturnValue(of(createDefaultPromResponse())); const fetchMock = jest.fn().mockReturnValue(of(createDefaultPromResponse()));
@ -106,6 +106,8 @@ describe('PrometheusDatasource', () => {
access: 'direct', access: 'direct',
jsonData: { jsonData: {
customQueryParameters: '', customQueryParameters: '',
prometheusVersion: '2.20.0',
prometheusType: PromApplication.Prometheus,
}, },
} as unknown as DataSourceInstanceSettings<PromOptions>; } as unknown as DataSourceInstanceSettings<PromOptions>;
const range = { from: time({ seconds: 63 }), to: time({ seconds: 183 }) }; const range = { from: time({ seconds: 63 }), to: time({ seconds: 183 }) };

View File

@ -48,7 +48,7 @@ import {
getPrometheusTime, getPrometheusTime,
getRangeSnapInterval, getRangeSnapInterval,
} from './language_utils'; } from './language_utils';
import PrometheusMetricFindQuery from './metric_find_query'; import { PrometheusMetricFindQuery } from './metric_find_query';
import { getInitHints, getQueryHints } from './query_hints'; import { getInitHints, getQueryHints } from './query_hints';
import { promQueryModeller } from './querybuilder/PromQueryModeller'; import { promQueryModeller } from './querybuilder/PromQueryModeller';
import { QueryBuilderLabelFilter, QueryEditorMode } from './querybuilder/shared/types'; import { QueryBuilderLabelFilter, QueryEditorMode } from './querybuilder/shared/types';
@ -188,9 +188,9 @@ export class PrometheusDatasource
} }
_isDatasourceVersionGreaterOrEqualTo(targetVersion: string, targetFlavor: PromApplication): boolean { _isDatasourceVersionGreaterOrEqualTo(targetVersion: string, targetFlavor: PromApplication): boolean {
// User hasn't configured flavor/version yet, default behavior is to not support features that require version configuration when not provided // User hasn't configured flavor/version yet, default behavior is to support labels match api support
if (!this.datasourceConfigurationPrometheusVersion || !this.datasourceConfigurationPrometheusFlavor) { if (!this.datasourceConfigurationPrometheusVersion || !this.datasourceConfigurationPrometheusFlavor) {
return false; return true;
} }
if (targetFlavor !== this.datasourceConfigurationPrometheusFlavor) { if (targetFlavor !== this.datasourceConfigurationPrometheusFlavor) {

View File

@ -1,16 +1,87 @@
export * from './components'; // The Grafana Prometheus library exports a number of components.
export * from './configuration'; // There are main components that can be imported directly into your plugin module.ts file.
export * from './querybuilder'; // There are also more granular components that can be used to build components, for example, the config section can be built with granular parts to allow for custom auths.
export * from './add_label_to_query'; // COMPONENTS/
export * from './dataquery.gen'; // Main export
export * from './datasource'; export { PromQueryEditorByApp } from './components/PromQueryEditorByApp';
export * from './language_provider'; // The parts
export * from './language_utils'; export { MonacoQueryFieldLazy } from './components/monaco-query-field/MonacoQueryFieldLazy';
export * from './metric_find_query'; export { AnnotationQueryEditor } from './components/AnnotationQueryEditor';
export * from './promql'; export { PromCheatSheet } from './components/PromCheatSheet';
export * from './query_hints'; export { PrometheusMetricsBrowser } from './components/PrometheusMetricsBrowser';
export * from './result_transformer'; export { PromExemplarField } from './components/PromExemplarField';
export * from './tracking'; export { PromExploreExtraField } from './components/PromExploreExtraField';
export * from './types'; export { PromQueryEditorForAlerting } from './components/PromQueryEditorForAlerting';
export * from './variables'; export { PromQueryField } from './components/PromQueryField';
export { PromVariableQueryEditor } from './components/VariableQueryEditor';
// CONFIGURATION/
// Main export
export {
ConfigEditor,
docsTip,
overhaulStyles,
validateInput,
PROM_CONFIG_LABEL_WIDTH,
} from './configuration/ConfigEditor';
// The parts
export { AlertingSettingsOverhaul } from './configuration/AlertingSettingsOverhaul';
export { DataSourceHttpSettingsOverhaul } from './configuration/DataSourceHttpSettingsOverhaul';
export { ExemplarSetting } from './configuration/ExemplarSetting';
export { ExemplarsSettings } from './configuration/ExemplarsSettings';
export { PromFlavorVersions } from './configuration/PromFlavorVersions';
export { PromSettings } from './configuration/PromSettings';
// QUERYBUILDER/
// The parts (The query builder is imported into PromQueryEditorByApp)
export { QueryPattern } from './querybuilder/QueryPattern';
export { QueryPatternsModal } from './querybuilder/QueryPatternsModal';
// QUERYBUILDER/COMPONENTS/
export { LabelFilterItem } from './querybuilder/components/LabelFilterItem';
export { LabelFilters } from './querybuilder/components/LabelFilters';
export { LabelParamEditor } from './querybuilder/components/LabelParamEditor';
export { MetricSelect } from './querybuilder/components/MetricSelect';
export { MetricsLabelsSection } from './querybuilder/components/MetricsLabelsSection';
export { NestedQuery } from './querybuilder/components/NestedQuery';
export { NestedQueryList } from './querybuilder/components/NestedQueryList';
export { PromQueryBuilder } from './querybuilder/components/PromQueryBuilder';
export { PromQueryBuilderContainer } from './querybuilder/components/PromQueryBuilderContainer';
export { PromQueryBuilderExplained } from './querybuilder/components/PromQueryBuilderExplained';
export { PromQueryBuilderOptions } from './querybuilder/components/PromQueryBuilderOptions';
export { PromQueryCodeEditor } from './querybuilder/components/PromQueryCodeEditor';
export { PromQueryEditorSelector } from './querybuilder/components/PromQueryEditorSelector';
export { PromQueryLegendEditor } from './querybuilder/components/PromQueryLegendEditor';
export { QueryPreview } from './querybuilder/components/QueryPreview';
export { MetricsModal } from './querybuilder/components/metrics-modal/MetricsModal';
export { PromQail } from './querybuilder/components/promQail/PromQail';
// SRC/
// Main export
export { PrometheusDatasource } from './datasource';
// The parts
export { addLabelToQuery } from './add_label_to_query';
export { type QueryEditorMode, type PromQueryFormat, type Prometheus } from './dataquery.gen';
export { PrometheusMetricFindQuery } from './metric_find_query';
export { promqlGrammar } from './promql';
export { getQueryHints, getInitHints } from './query_hints';
export { transformV2, transformDFToTable } from './result_transformer';
export {
type PromQuery,
type PrometheusCacheLevel,
type PromApplication,
type PromOptions,
type ExemplarTraceIdDestination,
type PromQueryRequest,
type PromMetricsMetadataItem,
type PromMetricsMetadata,
type PromValue,
type PromMetric,
type PromBuildInfoResponse,
type LegendFormatMode,
type PromVariableQueryType,
type PromVariableQuery,
type StandardPromVariableQuery,
} from './types';
export { PrometheusVariableSupport } from './variables';

View File

@ -6,7 +6,7 @@ import { BackendDataSourceResponse, BackendSrvRequest, FetchResponse, TemplateSr
import { PrometheusDatasource } from './datasource'; import { PrometheusDatasource } from './datasource';
import { getPrometheusTime } from './language_utils'; import { getPrometheusTime } from './language_utils';
import PrometheusMetricFindQuery from './metric_find_query'; import { PrometheusMetricFindQuery } from './metric_find_query';
import { PromApplication, PromOptions } from './types'; import { PromApplication, PromOptions } from './types';
const fetchMock = jest.fn((options: BackendSrvRequest): Observable<FetchResponse<BackendDataSourceResponse>> => { const fetchMock = jest.fn((options: BackendSrvRequest): Observable<FetchResponse<BackendDataSourceResponse>> => {
@ -28,7 +28,11 @@ const instanceSettings = {
uid: 'ABCDEF', uid: 'ABCDEF',
user: 'test', user: 'test',
password: 'mupp', password: 'mupp',
jsonData: { httpMethod: 'GET' }, jsonData: {
httpMethod: 'GET',
prometheusVersion: '2.20.0',
prometheusType: PromApplication.Prometheus,
},
} as Partial<DataSourceInstanceSettings<PromOptions>> as DataSourceInstanceSettings<PromOptions>; } as Partial<DataSourceInstanceSettings<PromOptions>> as DataSourceInstanceSettings<PromOptions>;
const raw: TimeRange = { const raw: TimeRange = {
from: toUtc('2018-04-25 10:00'), from: toUtc('2018-04-25 10:00'),

View File

@ -11,7 +11,7 @@ import {
PrometheusQueryResultRegex, PrometheusQueryResultRegex,
} from './migrations/variableMigration'; } from './migrations/variableMigration';
export default class PrometheusMetricFindQuery { export class PrometheusMetricFindQuery {
range: TimeRange; range: TimeRange;
constructor( constructor(

View File

@ -2,8 +2,8 @@
import { DataSourcePlugin } from '@grafana/data'; import { DataSourcePlugin } from '@grafana/data';
import PromCheatSheet from './components/PromCheatSheet'; import { PromCheatSheet } from './components/PromCheatSheet';
import PromQueryEditorByApp from './components/PromQueryEditorByApp'; import { PromQueryEditorByApp } from './components/PromQueryEditorByApp';
import { ConfigEditor } from './configuration/ConfigEditor'; import { ConfigEditor } from './configuration/ConfigEditor';
import { PrometheusDatasource } from './datasource'; import { PrometheusDatasource } from './datasource';

View File

@ -5,7 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
import PromQueryField from '../../components/PromQueryField'; import { PromQueryField } from '../../components/PromQueryField';
import { PromQueryEditorProps } from '../../components/types'; import { PromQueryEditorProps } from '../../components/types';
import { PromQueryBuilderExplained } from './PromQueryBuilderExplained'; import { PromQueryBuilderExplained } from './PromQueryBuilderExplained';

View File

@ -1,17 +0,0 @@
export * from './LabelFilterItem';
export * from './LabelFilters';
export * from './LabelParamEditor';
export * from './MetricSelect';
export * from './MetricsLabelsSection';
export * from './NestedQuery';
export * from './NestedQueryList';
export * from './PromQueryBuilder';
export * from './PromQueryBuilderContainer';
export * from './PromQueryBuilderExplained';
export * from './PromQueryBuilderOptions';
export * from './PromQueryCodeEditor';
export * from './PromQueryEditorSelector';
export * from './PromQueryLegendEditor';
export * from './QueryPreview';
export * from './metrics-modal';
export * from './promQail';

View File

@ -1,4 +1,5 @@
import { cx } from '@emotion/css'; import { cx } from '@emotion/css';
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import debounce from 'debounce-promise'; import debounce from 'debounce-promise';
import React, { useCallback, useEffect, useMemo, useReducer } from 'react'; import React, { useCallback, useEffect, useMemo, useReducer } from 'react';
@ -38,10 +39,10 @@ import {
initialState, initialState,
MAXIMUM_RESULTS_PER_PAGE, MAXIMUM_RESULTS_PER_PAGE,
MetricsModalMetadata, MetricsModalMetadata,
stateSlice, // stateSlice,
} from './state/state'; } from './state/state';
import { getStyles } from './styles'; import { getStyles } from './styles';
import { PromFilterOption } from './types'; import { MetricsData, PromFilterOption } from './types';
import { debouncedFuzzySearch } from './uFuzzy'; import { debouncedFuzzySearch } from './uFuzzy';
export type MetricsModalProps = { export type MetricsModalProps = {
@ -53,24 +54,6 @@ export type MetricsModalProps = {
initialMetrics: string[]; initialMetrics: string[];
}; };
// actions to update the state
const {
setIsLoading,
buildMetrics,
filterMetricsBackend,
setResultsPerPage,
setPageNum,
setFuzzySearchQuery,
setNameHaystack,
setMetaHaystack,
setFullMetaSearch,
setIncludeNullMetadata,
setSelectedTypes,
setUseBackend,
setDisableTextWrap,
showAdditionalSettings,
} = stateSlice.actions;
export const MetricsModal = (props: MetricsModalProps) => { export const MetricsModal = (props: MetricsModalProps) => {
const { datasource, isOpen, onClose, onChange, query, initialMetrics } = props; const { datasource, isOpen, onClose, onChange, query, initialMetrics } = props;
@ -335,3 +318,97 @@ export const metricsModaltestIds = {
setUseBackend: 'set-use-backend', setUseBackend: 'set-use-backend',
showAdditionalSettings: 'show-additional-settings', showAdditionalSettings: 'show-additional-settings',
}; };
const stateSlice = createSlice({
name: 'metrics-modal-state',
initialState: initialState(),
reducers: {
filterMetricsBackend: (
state,
action: PayloadAction<{
metrics: MetricsData;
filteredMetricCount: number;
isLoading: boolean;
}>
) => {
state.metrics = action.payload.metrics;
state.filteredMetricCount = action.payload.filteredMetricCount;
state.isLoading = action.payload.isLoading;
},
buildMetrics: (state, action: PayloadAction<MetricsModalMetadata>) => {
state.isLoading = action.payload.isLoading;
state.metrics = action.payload.metrics;
state.hasMetadata = action.payload.hasMetadata;
state.metaHaystackDictionary = action.payload.metaHaystackDictionary;
state.nameHaystackDictionary = action.payload.nameHaystackDictionary;
state.totalMetricCount = action.payload.totalMetricCount;
state.filteredMetricCount = action.payload.filteredMetricCount;
},
setIsLoading: (state, action: PayloadAction<boolean>) => {
state.isLoading = action.payload;
},
setFilteredMetricCount: (state, action: PayloadAction<number>) => {
state.filteredMetricCount = action.payload;
},
setResultsPerPage: (state, action: PayloadAction<number>) => {
state.resultsPerPage = action.payload;
},
setPageNum: (state, action: PayloadAction<number>) => {
state.pageNum = action.payload;
},
setFuzzySearchQuery: (state, action: PayloadAction<string>) => {
state.fuzzySearchQuery = action.payload;
state.pageNum = 1;
},
setNameHaystack: (state, action: PayloadAction<string[][]>) => {
state.nameHaystackOrder = action.payload[0];
state.nameHaystackMatches = action.payload[1];
},
setMetaHaystack: (state, action: PayloadAction<string[][]>) => {
state.metaHaystackOrder = action.payload[0];
state.metaHaystackMatches = action.payload[1];
},
setFullMetaSearch: (state, action: PayloadAction<boolean>) => {
state.fullMetaSearch = action.payload;
state.pageNum = 1;
},
setIncludeNullMetadata: (state, action: PayloadAction<boolean>) => {
state.includeNullMetadata = action.payload;
state.pageNum = 1;
},
setSelectedTypes: (state, action: PayloadAction<Array<SelectableValue<string>>>) => {
state.selectedTypes = action.payload;
state.pageNum = 1;
},
setUseBackend: (state, action: PayloadAction<boolean>) => {
state.useBackend = action.payload;
state.fullMetaSearch = false;
state.pageNum = 1;
},
setDisableTextWrap: (state) => {
state.disableTextWrap = !state.disableTextWrap;
},
showAdditionalSettings: (state) => {
state.showAdditionalSettings = !state.showAdditionalSettings;
},
},
});
// actions to update the state
export const {
setIsLoading,
buildMetrics,
filterMetricsBackend,
setResultsPerPage,
setPageNum,
setFuzzySearchQuery,
setNameHaystack,
setMetaHaystack,
setFullMetaSearch,
setIncludeNullMetadata,
setSelectedTypes,
setUseBackend,
setDisableTextWrap,
showAdditionalSettings,
setFilteredMetricCount,
} = stateSlice.actions;

View File

@ -7,11 +7,12 @@ import { getMetadataHelp, getMetadataType } from '../../../../language_provider'
import { regexifyLabelValuesQueryString } from '../../../parsingUtils'; import { regexifyLabelValuesQueryString } from '../../../parsingUtils';
import { QueryBuilderLabelFilter } from '../../../shared/types'; import { QueryBuilderLabelFilter } from '../../../shared/types';
import { PromVisualQuery } from '../../../types'; import { PromVisualQuery } from '../../../types';
import { setFilteredMetricCount } from '../MetricsModal';
import { HaystackDictionary, MetricData, MetricsData, PromFilterOption } from '../types'; import { HaystackDictionary, MetricData, MetricsData, PromFilterOption } from '../types';
import { MetricsModalMetadata, MetricsModalState, stateSlice } from './state'; import { MetricsModalMetadata, MetricsModalState } from './state';
const { setFilteredMetricCount } = stateSlice.actions; // const { setFilteredMetricCount } = stateSlice.actions;
export async function setMetrics( export async function setMetrics(
datasource: PrometheusDatasource, datasource: PrometheusDatasource,

View File

@ -1,5 +1,3 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { PromVisualQuery } from '../../../types'; import { PromVisualQuery } from '../../../types';
@ -8,81 +6,6 @@ import { HaystackDictionary, MetricsData } from '../types';
export const DEFAULT_RESULTS_PER_PAGE = 100; export const DEFAULT_RESULTS_PER_PAGE = 100;
export const MAXIMUM_RESULTS_PER_PAGE = 1000; export const MAXIMUM_RESULTS_PER_PAGE = 1000;
export const stateSlice = createSlice({
name: 'metrics-modal-state',
initialState: initialState(),
reducers: {
filterMetricsBackend: (
state,
action: PayloadAction<{
metrics: MetricsData;
filteredMetricCount: number;
isLoading: boolean;
}>
) => {
state.metrics = action.payload.metrics;
state.filteredMetricCount = action.payload.filteredMetricCount;
state.isLoading = action.payload.isLoading;
},
buildMetrics: (state, action: PayloadAction<MetricsModalMetadata>) => {
state.isLoading = action.payload.isLoading;
state.metrics = action.payload.metrics;
state.hasMetadata = action.payload.hasMetadata;
state.metaHaystackDictionary = action.payload.metaHaystackDictionary;
state.nameHaystackDictionary = action.payload.nameHaystackDictionary;
state.totalMetricCount = action.payload.totalMetricCount;
state.filteredMetricCount = action.payload.filteredMetricCount;
},
setIsLoading: (state, action: PayloadAction<boolean>) => {
state.isLoading = action.payload;
},
setFilteredMetricCount: (state, action: PayloadAction<number>) => {
state.filteredMetricCount = action.payload;
},
setResultsPerPage: (state, action: PayloadAction<number>) => {
state.resultsPerPage = action.payload;
},
setPageNum: (state, action: PayloadAction<number>) => {
state.pageNum = action.payload;
},
setFuzzySearchQuery: (state, action: PayloadAction<string>) => {
state.fuzzySearchQuery = action.payload;
state.pageNum = 1;
},
setNameHaystack: (state, action: PayloadAction<string[][]>) => {
state.nameHaystackOrder = action.payload[0];
state.nameHaystackMatches = action.payload[1];
},
setMetaHaystack: (state, action: PayloadAction<string[][]>) => {
state.metaHaystackOrder = action.payload[0];
state.metaHaystackMatches = action.payload[1];
},
setFullMetaSearch: (state, action: PayloadAction<boolean>) => {
state.fullMetaSearch = action.payload;
state.pageNum = 1;
},
setIncludeNullMetadata: (state, action: PayloadAction<boolean>) => {
state.includeNullMetadata = action.payload;
state.pageNum = 1;
},
setSelectedTypes: (state, action: PayloadAction<Array<SelectableValue<string>>>) => {
state.selectedTypes = action.payload;
state.pageNum = 1;
},
setUseBackend: (state, action: PayloadAction<boolean>) => {
state.useBackend = action.payload;
state.fullMetaSearch = false;
state.pageNum = 1;
},
setDisableTextWrap: (state) => {
state.disableTextWrap = !state.disableTextWrap;
},
showAdditionalSettings: (state) => {
state.showAdditionalSettings = !state.showAdditionalSettings;
},
},
});
/** /**
* Initial state for the metrics explorer * Initial state for the metrics explorer
* @returns * @returns

View File

@ -1,4 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import React, { useEffect, useReducer, useRef, useState } from 'react'; import React, { useEffect, useReducer, useRef, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -13,12 +14,9 @@ import { QuerySuggestionContainer } from './QuerySuggestionContainer';
// @ts-ignore until we can get these added for icons // @ts-ignore until we can get these added for icons
import AI_Logo_color from './resources/AI_Logo_color.svg'; import AI_Logo_color from './resources/AI_Logo_color.svg';
import { promQailExplain, promQailSuggest } from './state/helpers'; import { promQailExplain, promQailSuggest } from './state/helpers';
import { initialState, stateSlice } from './state/state'; import { createInteraction, initialState } from './state/state';
import { Interaction, SuggestionType } from './types'; import { Interaction, SuggestionType } from './types';
// actions to update the state
const { showStartingMessage, indicateCheckbox, addInteraction, updateInteraction } = stateSlice.actions;
export type PromQailProps = { export type PromQailProps = {
query: PromVisualQuery; query: PromVisualQuery;
closeDrawer: () => void; closeDrawer: () => void;
@ -565,3 +563,54 @@ export const queryAssistanttestIds = {
submitPrompt: 'submit-prompt', submitPrompt: 'submit-prompt',
refinePrompt: 'refine-prompt', refinePrompt: 'refine-prompt',
}; };
const stateSlice = createSlice({
name: 'metrics-modal-state',
initialState: initialState(),
reducers: {
showExplainer: (state, action: PayloadAction<boolean>) => {
state.showExplainer = action.payload;
},
showStartingMessage: (state, action: PayloadAction<boolean>) => {
state.showStartingMessage = action.payload;
},
indicateCheckbox: (state, action: PayloadAction<boolean>) => {
state.indicateCheckbox = action.payload;
},
askForQueryHelp: (state, action: PayloadAction<boolean>) => {
state.askForQueryHelp = action.payload;
},
/*
* start working on a collection of interactions
* {
* askForhelp y n
* prompt question
* queries querySuggestions
* }
*
*/
addInteraction: (state, action: PayloadAction<{ suggestionType: SuggestionType; isLoading: boolean }>) => {
// AI or Historical?
const interaction = createInteraction(action.payload.suggestionType, action.payload.isLoading);
const interactions = state.interactions;
state.interactions = interactions.concat([interaction]);
},
updateInteraction: (state, action: PayloadAction<{ idx: number; interaction: Interaction }>) => {
// update the interaction by index
// will most likely be the last interaction but we might update previous by giving them cues of helpful or not
const index = action.payload.idx;
const updInteraction = action.payload.interaction;
state.interactions = state.interactions.map((interaction: Interaction, idx: number) => {
if (idx === index) {
return updInteraction;
}
return interaction;
});
},
},
});
// actions to update the state
export const { showStartingMessage, indicateCheckbox, addInteraction, updateInteraction } = stateSlice.actions;

View File

@ -8,6 +8,7 @@ import { getMetadataHelp, getMetadataType } from '../../../../language_provider'
import { promQueryModeller } from '../../../PromQueryModeller'; import { promQueryModeller } from '../../../PromQueryModeller';
import { buildVisualQueryFromString } from '../../../parsing'; import { buildVisualQueryFromString } from '../../../parsing';
import { PromVisualQuery } from '../../../types'; import { PromVisualQuery } from '../../../types';
import { updateInteraction } from '../PromQail';
import { import {
ExplainSystemPrompt, ExplainSystemPrompt,
GetExplainUserPrompt, GetExplainUserPrompt,
@ -17,13 +18,11 @@ import {
} from '../prompts'; } from '../prompts';
import { Interaction, QuerySuggestion, SuggestionType } from '../types'; import { Interaction, QuerySuggestion, SuggestionType } from '../types';
import { createInteraction, stateSlice } from './state'; import { createInteraction } from './state';
import { getTemplateSuggestions } from './templates'; import { getTemplateSuggestions } from './templates';
const OPENAI_MODEL_NAME = 'gpt-3.5-turbo-1106'; const OPENAI_MODEL_NAME = 'gpt-3.5-turbo-1106';
const promQLTemplatesCollection = 'grafana.promql.templates'; const promQLTemplatesCollection = 'grafana.promql.templates';
// actions to update the state
const { updateInteraction } = stateSlice.actions;
interface TemplateSearchResult { interface TemplateSearchResult {
description: string | null; description: string | null;

View File

@ -1,56 +1,6 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { PromVisualQuery } from '../../../types'; import { PromVisualQuery } from '../../../types';
import { Interaction, SuggestionType } from '../types'; import { Interaction, SuggestionType } from '../types';
export const stateSlice = createSlice({
name: 'metrics-modal-state',
initialState: initialState(),
reducers: {
showExplainer: (state, action: PayloadAction<boolean>) => {
state.showExplainer = action.payload;
},
showStartingMessage: (state, action: PayloadAction<boolean>) => {
state.showStartingMessage = action.payload;
},
indicateCheckbox: (state, action: PayloadAction<boolean>) => {
state.indicateCheckbox = action.payload;
},
askForQueryHelp: (state, action: PayloadAction<boolean>) => {
state.askForQueryHelp = action.payload;
},
/*
* start working on a collection of interactions
* {
* askForhelp y n
* prompt question
* queries querySuggestions
* }
*
*/
addInteraction: (state, action: PayloadAction<{ suggestionType: SuggestionType; isLoading: boolean }>) => {
// AI or Historical?
const interaction = createInteraction(action.payload.suggestionType, action.payload.isLoading);
const interactions = state.interactions;
state.interactions = interactions.concat([interaction]);
},
updateInteraction: (state, action: PayloadAction<{ idx: number; interaction: Interaction }>) => {
// update the interaction by index
// will most likely be the last interaction but we might update previous by giving them cues of helpful or not
const index = action.payload.idx;
const updInteraction = action.payload.interaction;
state.interactions = state.interactions.map((interaction: Interaction, idx: number) => {
if (idx === index) {
return updInteraction;
}
return interaction;
});
},
},
});
/** /**
* Initial state for PromQAIL * Initial state for PromQAIL
* @param query the prometheus query with metric and possible labels * @param query the prometheus query with metric and possible labels

View File

@ -1,13 +0,0 @@
export * from './aggregations';
export * from './binaryScalarOperations';
export * from './operations';
export * from './operationUtils';
export * from './parsing';
export * from './parsingUtils';
export * from './PromQueryModeller';
export * from './QueryPattern';
export * from './QueryPatternsModal';
export * from './state';
export * from './testUtils';
export * from './types';
export * from './components';

View File

@ -6,7 +6,7 @@ import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import { PromVariableQueryEditor } from './components/VariableQueryEditor'; import { PromVariableQueryEditor } from './components/VariableQueryEditor';
import { PrometheusDatasource } from './datasource'; import { PrometheusDatasource } from './datasource';
import PrometheusMetricFindQuery from './metric_find_query'; import { PrometheusMetricFindQuery } from './metric_find_query';
import { PromVariableQuery } from './types'; import { PromVariableQuery } from './types';
export class PrometheusVariableSupport extends CustomVariableSupport<PrometheusDatasource> { export class PrometheusVariableSupport extends CustomVariableSupport<PrometheusDatasource> {

View File

@ -22,7 +22,7 @@ for file in "$ARTIFACTS_DIR"/*.tgz; do
pushd "./npm-artifacts/$dir_name" || exit pushd "./npm-artifacts/$dir_name" || exit
# Check for required files # Check for required files
check_files=("package.json" "README.md" "CHANGELOG.md" "LICENSE_APACHE2") check_files=("package.json" "README.md" "CHANGELOG.md")
for check_file in "${check_files[@]}"; do for check_file in "${check_files[@]}"; do
if [ ! -f "$check_file" ]; then if [ ! -f "$check_file" ]; then
echo -e "❌ Failed: Missing required file $check_file in package $dir_name.\n" echo -e "❌ Failed: Missing required file $check_file in package $dir_name.\n"
@ -30,6 +30,14 @@ for file in "$ARTIFACTS_DIR"/*.tgz; do
fi fi
done done
# Check license files
if [ -f "LICENSE_APACHE2" ] || [ -f "LICENSE_AGPL" ]; then
echo -e "Found required license file in package $dir_name.\n"
else
echo -e "❌ Failed: Missing required license file in package $dir_name.\n"
exit 1
fi
# Assert commonjs builds # Assert commonjs builds
if [ ! -d dist ] || [ ! -f dist/index.js ] || [ ! -f dist/index.d.ts ]; then if [ ! -d dist ] || [ ! -f dist/index.js ] || [ ! -f dist/index.d.ts ]; then
echo -e "❌ Failed: Missing 'dist' directory or required commonjs files in package $dir_name.\n" echo -e "❌ Failed: Missing 'dist' directory or required commonjs files in package $dir_name.\n"

150
yarn.lock
View File

@ -3898,7 +3898,9 @@ __metadata:
"@lezer/lr": "npm:1.3.3" "@lezer/lr": "npm:1.3.3"
"@prometheus-io/lezer-promql": "npm:^0.37.0-rc.1" "@prometheus-io/lezer-promql": "npm:^0.37.0-rc.1"
"@reduxjs/toolkit": "npm:1.9.5" "@reduxjs/toolkit": "npm:1.9.5"
"@swc/core": "npm:1.4.1" "@rollup/plugin-image": "npm:3.0.3"
"@rollup/plugin-node-resolve": "npm:15.2.3"
"@swc/core": "npm:1.4.0"
"@swc/helpers": "npm:0.5.6" "@swc/helpers": "npm:0.5.6"
"@testing-library/dom": "npm:9.3.4" "@testing-library/dom": "npm:9.3.4"
"@testing-library/jest-dom": "npm:6.4.2" "@testing-library/jest-dom": "npm:6.4.2"
@ -3965,6 +3967,10 @@ __metadata:
react-test-renderer: "npm:18.2.0" react-test-renderer: "npm:18.2.0"
react-use: "npm:17.5.0" react-use: "npm:17.5.0"
react-window: "npm:1.8.10" react-window: "npm:1.8.10"
rollup: "npm:2.79.1"
rollup-plugin-dts: "npm:^5.0.0"
rollup-plugin-esbuild: "npm:5.0.0"
rollup-plugin-node-externals: "npm:^5.0.0"
rxjs: "npm:7.8.1" rxjs: "npm:7.8.1"
sass: "npm:1.70.0" sass: "npm:1.70.0"
sass-loader: "npm:13.3.2" sass-loader: "npm:13.3.2"
@ -6963,6 +6969,21 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@rollup/plugin-image@npm:3.0.3":
version: 3.0.3
resolution: "@rollup/plugin-image@npm:3.0.3"
dependencies:
"@rollup/pluginutils": "npm:^5.0.1"
mini-svg-data-uri: "npm:^1.4.4"
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
checksum: 10/30363d50c3d43fc35add135ce1b9591a69f378d696829724ce229e7c78ed00bc646280c150bd4b872d9359aeee656fae7107876c802dd7374aa71e21cb0af371
languageName: node
linkType: hard
"@rollup/plugin-json@npm:6.1.0": "@rollup/plugin-json@npm:6.1.0":
version: 6.1.0 version: 6.1.0
resolution: "@rollup/plugin-json@npm:6.1.0" resolution: "@rollup/plugin-json@npm:6.1.0"
@ -8236,6 +8257,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-darwin-arm64@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-darwin-arm64@npm:1.4.0"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@swc/core-darwin-arm64@npm:1.4.1": "@swc/core-darwin-arm64@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-darwin-arm64@npm:1.4.1" resolution: "@swc/core-darwin-arm64@npm:1.4.1"
@ -8243,6 +8271,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-darwin-x64@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-darwin-x64@npm:1.4.0"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@swc/core-darwin-x64@npm:1.4.1": "@swc/core-darwin-x64@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-darwin-x64@npm:1.4.1" resolution: "@swc/core-darwin-x64@npm:1.4.1"
@ -8250,6 +8285,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-linux-arm-gnueabihf@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.0"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@swc/core-linux-arm-gnueabihf@npm:1.4.1": "@swc/core-linux-arm-gnueabihf@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.1" resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.1"
@ -8257,6 +8299,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-linux-arm64-gnu@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-linux-arm64-gnu@npm:1.4.0"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@swc/core-linux-arm64-gnu@npm:1.4.1": "@swc/core-linux-arm64-gnu@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-linux-arm64-gnu@npm:1.4.1" resolution: "@swc/core-linux-arm64-gnu@npm:1.4.1"
@ -8264,6 +8313,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-linux-arm64-musl@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-linux-arm64-musl@npm:1.4.0"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@swc/core-linux-arm64-musl@npm:1.4.1": "@swc/core-linux-arm64-musl@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-linux-arm64-musl@npm:1.4.1" resolution: "@swc/core-linux-arm64-musl@npm:1.4.1"
@ -8271,6 +8327,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-linux-x64-gnu@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-linux-x64-gnu@npm:1.4.0"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@swc/core-linux-x64-gnu@npm:1.4.1": "@swc/core-linux-x64-gnu@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-linux-x64-gnu@npm:1.4.1" resolution: "@swc/core-linux-x64-gnu@npm:1.4.1"
@ -8278,6 +8341,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-linux-x64-musl@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-linux-x64-musl@npm:1.4.0"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@swc/core-linux-x64-musl@npm:1.4.1": "@swc/core-linux-x64-musl@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-linux-x64-musl@npm:1.4.1" resolution: "@swc/core-linux-x64-musl@npm:1.4.1"
@ -8285,6 +8355,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-win32-arm64-msvc@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-win32-arm64-msvc@npm:1.4.0"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@swc/core-win32-arm64-msvc@npm:1.4.1": "@swc/core-win32-arm64-msvc@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-win32-arm64-msvc@npm:1.4.1" resolution: "@swc/core-win32-arm64-msvc@npm:1.4.1"
@ -8292,6 +8369,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-win32-ia32-msvc@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-win32-ia32-msvc@npm:1.4.0"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
"@swc/core-win32-ia32-msvc@npm:1.4.1": "@swc/core-win32-ia32-msvc@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-win32-ia32-msvc@npm:1.4.1" resolution: "@swc/core-win32-ia32-msvc@npm:1.4.1"
@ -8299,6 +8383,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core-win32-x64-msvc@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core-win32-x64-msvc@npm:1.4.0"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@swc/core-win32-x64-msvc@npm:1.4.1": "@swc/core-win32-x64-msvc@npm:1.4.1":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core-win32-x64-msvc@npm:1.4.1" resolution: "@swc/core-win32-x64-msvc@npm:1.4.1"
@ -8306,6 +8397,52 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/core@npm:1.4.0":
version: 1.4.0
resolution: "@swc/core@npm:1.4.0"
dependencies:
"@swc/core-darwin-arm64": "npm:1.4.0"
"@swc/core-darwin-x64": "npm:1.4.0"
"@swc/core-linux-arm-gnueabihf": "npm:1.4.0"
"@swc/core-linux-arm64-gnu": "npm:1.4.0"
"@swc/core-linux-arm64-musl": "npm:1.4.0"
"@swc/core-linux-x64-gnu": "npm:1.4.0"
"@swc/core-linux-x64-musl": "npm:1.4.0"
"@swc/core-win32-arm64-msvc": "npm:1.4.0"
"@swc/core-win32-ia32-msvc": "npm:1.4.0"
"@swc/core-win32-x64-msvc": "npm:1.4.0"
"@swc/counter": "npm:^0.1.1"
"@swc/types": "npm:^0.1.5"
peerDependencies:
"@swc/helpers": ^0.5.0
dependenciesMeta:
"@swc/core-darwin-arm64":
optional: true
"@swc/core-darwin-x64":
optional: true
"@swc/core-linux-arm-gnueabihf":
optional: true
"@swc/core-linux-arm64-gnu":
optional: true
"@swc/core-linux-arm64-musl":
optional: true
"@swc/core-linux-x64-gnu":
optional: true
"@swc/core-linux-x64-musl":
optional: true
"@swc/core-win32-arm64-msvc":
optional: true
"@swc/core-win32-ia32-msvc":
optional: true
"@swc/core-win32-x64-msvc":
optional: true
peerDependenciesMeta:
"@swc/helpers":
optional: true
checksum: 10/2f310f81c24b5688a6d4171b4fdb59987070ecda03aad51d755592607b461ddcd6a9d0488510f47785ce634707fd6f30f986ab1f1138e794972d53ce0e94db80
languageName: node
linkType: hard
"@swc/core@npm:1.4.1, @swc/core@npm:^1.3.49": "@swc/core@npm:1.4.1, @swc/core@npm:^1.3.49":
version: 1.4.1 version: 1.4.1
resolution: "@swc/core@npm:1.4.1" resolution: "@swc/core@npm:1.4.1"
@ -8352,7 +8489,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3": "@swc/counter@npm:^0.1.1, @swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3":
version: 0.1.3 version: 0.1.3
resolution: "@swc/counter@npm:0.1.3" resolution: "@swc/counter@npm:0.1.3"
checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598
@ -22338,6 +22475,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mini-svg-data-uri@npm:^1.4.4":
version: 1.4.4
resolution: "mini-svg-data-uri@npm:1.4.4"
bin:
mini-svg-data-uri: cli.js
checksum: 10/1336c2b00b6a72b0ce3cf942f7ab074faf463b941042fbe51d7a70be119c5d4223880aaa29584d5a804496ca1dda9b6fff7dd5aa284721907519b646192d8aaa
languageName: node
linkType: hard
"minimalistic-assert@npm:^1.0.0": "minimalistic-assert@npm:^1.0.0":
version: 1.0.1 version: 1.0.1
resolution: "minimalistic-assert@npm:1.0.1" resolution: "minimalistic-assert@npm:1.0.1"