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>
pull/82918/head^2
Brendan O'Handley 1 year ago committed by GitHub
parent 0a9389c8f7
commit c6f8462a06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      packages/grafana-prometheus/CHANGELOG.md
  2. 0
      packages/grafana-prometheus/LICENSE_AGPL
  3. 4
      packages/grafana-prometheus/README.md
  4. 30
      packages/grafana-prometheus/package.json
  5. 38
      packages/grafana-prometheus/rollup.config.ts
  6. 4
      packages/grafana-prometheus/src/components/PromCheatSheet.tsx
  7. 4
      packages/grafana-prometheus/src/components/PromQueryEditorByApp.tsx
  8. 2
      packages/grafana-prometheus/src/components/PromQueryEditorForAlerting.tsx
  9. 2
      packages/grafana-prometheus/src/components/PromQueryField.test.tsx
  10. 4
      packages/grafana-prometheus/src/components/PromQueryField.tsx
  11. 10
      packages/grafana-prometheus/src/components/index.ts
  12. 11
      packages/grafana-prometheus/src/components/monaco-query-field/MonacoQueryField.tsx
  13. 247
      packages/grafana-prometheus/src/components/monaco-query-field/promql.ts
  14. 4
      packages/grafana-prometheus/src/configuration/ConfigEditor.tsx
  15. 4
      packages/grafana-prometheus/src/configuration/DataSourceHttpSettingsOverhaul.tsx
  16. 2
      packages/grafana-prometheus/src/configuration/ExemplarSetting.tsx
  17. 2
      packages/grafana-prometheus/src/configuration/ExemplarsSettings.tsx
  18. 7
      packages/grafana-prometheus/src/configuration/index.ts
  19. 4
      packages/grafana-prometheus/src/datasource.test.ts
  20. 6
      packages/grafana-prometheus/src/datasource.ts
  21. 101
      packages/grafana-prometheus/src/index.ts
  22. 8
      packages/grafana-prometheus/src/metric_find_query.test.ts
  23. 2
      packages/grafana-prometheus/src/metric_find_query.ts
  24. 4
      packages/grafana-prometheus/src/module.ts
  25. 2
      packages/grafana-prometheus/src/querybuilder/components/PromQueryCodeEditor.tsx
  26. 17
      packages/grafana-prometheus/src/querybuilder/components/index.ts
  27. 117
      packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.tsx
  28. 5
      packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/helpers.ts
  29. 77
      packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/state.ts
  30. 57
      packages/grafana-prometheus/src/querybuilder/components/promQail/PromQail.tsx
  31. 5
      packages/grafana-prometheus/src/querybuilder/components/promQail/state/helpers.ts
  32. 50
      packages/grafana-prometheus/src/querybuilder/components/promQail/state/state.ts
  33. 13
      packages/grafana-prometheus/src/querybuilder/index.ts
  34. 2
      packages/grafana-prometheus/src/variables.ts
  35. 10
      scripts/validate-npm-packages.sh
  36. 150
      yarn.lock

@ -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.

@ -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`

@ -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",

@ -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',
},
},
];

@ -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;

@ -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);

@ -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) {

@ -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

@ -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);

@ -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';

@ -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);
} }
} }

@ -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 };
// }
// };

@ -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}

@ -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({

@ -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();

@ -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[];

@ -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';

@ -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 }) };

@ -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) {

@ -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';

@ -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'),

@ -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(

@ -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';

@ -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';

@ -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';

@ -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;

@ -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,

@ -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

@ -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;

@ -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;

@ -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

@ -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';

@ -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> {

@ -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"

@ -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"

Loading…
Cancel
Save