Prometheus package: Replace deprecated @grafana/experimental with @grafana/plugin-ui and @grafana/llm (#99385)

* Prometheus package: Replace deprecated @grafana/experimental with @grafana/plugin-ui and @grafana/llm

* Fix @grafana/llm mock in test

* Keep version exact

* Keep version exact

* Update lock
This commit is contained in:
Ivana Huckova
2025-01-24 12:46:31 +01:00
committed by GitHub
parent b07a39bb46
commit 2dfb796f21
23 changed files with 820 additions and 113 deletions

View File

@ -39,8 +39,9 @@
"@emotion/css": "11.13.5",
"@floating-ui/react": "0.27.3",
"@grafana/data": "11.5.0-pre",
"@grafana/experimental": "2.1.6",
"@grafana/faro-web-sdk": "1.12.3",
"@grafana/llm": "0.12.0",
"@grafana/plugin-ui": "0.9.6",
"@grafana/runtime": "11.5.0-pre",
"@grafana/schema": "11.5.0-pre",
"@grafana/ui": "11.5.0-pre",

View File

@ -1,7 +1,7 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/components/AnnotationQueryEditor.tsx
import { AnnotationQuery } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { EditorField, EditorRow, EditorRows, EditorSwitch } from '@grafana/experimental';
import { EditorField, EditorRow, EditorRows, EditorSwitch } from '@grafana/plugin-ui';
import { AutoSizeInput, Input, Space } from '@grafana/ui';
import { PromQueryCodeEditor } from '../querybuilder/components/PromQueryCodeEditor';

View File

@ -3,7 +3,7 @@ import { cx } from '@emotion/css';
import { DataSourceJsonData, DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { ConfigSubSection } from '@grafana/experimental';
import { ConfigSubSection } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { InlineField, Switch, useTheme2 } from '@grafana/ui';

View File

@ -2,7 +2,7 @@
import { css } from '@emotion/css';
import { DataSourcePluginOptionsEditorProps, GrafanaTheme2 } from '@grafana/data';
import { ConfigSection, DataSourceDescription, AdvancedHttpSettings } from '@grafana/experimental';
import { ConfigSection, DataSourceDescription, AdvancedHttpSettings } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { Alert, FieldValidationMessage, useTheme2 } from '@grafana/ui';

View File

@ -1,6 +1,6 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/configuration/DataSourceHttpSettingsOverhaul.tsx
import { DataSourceSettings } from '@grafana/data';
import { Auth, AuthMethod, ConnectionSettings, convertLegacyAuthProps } from '@grafana/experimental';
import { Auth, AuthMethod, ConnectionSettings, convertLegacyAuthProps } from '@grafana/plugin-ui';
import { SecureSocksProxySettings, useTheme2 } from '@grafana/ui';
import { PromOptions } from '../types';

View File

@ -2,7 +2,7 @@
import { css } from '@emotion/css';
import { selectors } from '@grafana/e2e-selectors';
import { ConfigSubSection } from '@grafana/experimental';
import { ConfigSubSection } from '@grafana/plugin-ui';
import { Button, useTheme2 } from '@grafana/ui';
import { ExemplarTraceIdDestination } from '../types';

View File

@ -8,7 +8,7 @@ import {
updateDatasourcePluginJsonDataOption,
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { ConfigSubSection } from '@grafana/experimental';
import { ConfigSubSection } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { InlineField, Input, Select, Switch, useTheme2 } from '@grafana/ui';

View File

@ -1,6 +1,6 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/query_hints.test.ts
import { QueryHint } from '@grafana/data';
import { QueryBuilderLabelFilter } from '@grafana/experimental';
import { QueryBuilderLabelFilter } from '@grafana/plugin-ui';
import { PrometheusDatasource } from './datasource';
import {

View File

@ -4,7 +4,7 @@ import { useState } from 'react';
import { SelectableValue, toOption } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { AccessoryButton, InputGroup } from '@grafana/experimental';
import { AccessoryButton, InputGroup } from '@grafana/plugin-ui';
import { AsyncSelect, Select } from '@grafana/ui';
import { truncateResult } from '../../language_utils';

View File

@ -4,7 +4,7 @@ import { isEqual } from 'lodash';
import { useEffect, useState } from 'react';
import { SelectableValue } from '@grafana/data';
import { EditorField, EditorFieldGroup, EditorList } from '@grafana/experimental';
import { EditorField, EditorFieldGroup, EditorList } from '@grafana/plugin-ui';
import { InlineFieldRow, InlineLabel } from '@grafana/ui';
import { QueryBuilderLabelFilter } from '../shared/types';

View File

@ -1,7 +1,7 @@
import { useCallback, useState } from 'react';
import { SelectableValue } from '@grafana/data';
import { EditorField, EditorFieldGroup, InputGroup } from '@grafana/experimental';
import { EditorField, EditorFieldGroup, InputGroup } from '@grafana/plugin-ui';
import { Button, InlineField, InlineFieldRow, Combobox, ComboboxOption } from '@grafana/ui';
import { PrometheusDatasource } from '../../datasource';

View File

@ -7,7 +7,7 @@ import Highlighter from 'react-highlight-words';
import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { EditorField, EditorFieldGroup } from '@grafana/experimental';
import { EditorField, EditorFieldGroup } from '@grafana/plugin-ui';
import {
AsyncSelect,
Button,

View File

@ -3,7 +3,7 @@ import { css } from '@emotion/css';
import { memo } from 'react';
import { GrafanaTheme2, toOption } from '@grafana/data';
import { EditorRows, FlexItem } from '@grafana/experimental';
import { EditorRows, FlexItem } from '@grafana/plugin-ui';
import { AutoSizeInput, IconButton, Select, useStyles2 } from '@grafana/ui';
import { PrometheusDatasource } from '../../datasource';

View File

@ -4,7 +4,7 @@ import { memo, useEffect, useState } from 'react';
import { DataSourceApi, PanelData } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { EditorRow } from '@grafana/experimental';
import { EditorRow } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { Drawer } from '@grafana/ui';

View File

@ -4,7 +4,7 @@ import * as React from 'react';
import { CoreApp, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { EditorField, EditorRow, EditorSwitch } from '@grafana/experimental';
import { EditorField, EditorRow, EditorSwitch } from '@grafana/plugin-ui';
import { AutoSizeInput, RadioButtonGroup, Select } from '@grafana/ui';
import { getQueryTypeChangeHandler, getQueryTypeOptions } from '../../components/PromExploreExtraField';

View File

@ -4,7 +4,7 @@ import { memo, SyntheticEvent, useCallback, useEffect, useState } from 'react';
import { CoreApp, LoadingState, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { EditorHeader, EditorRows, FlexItem } from '@grafana/experimental';
import { EditorHeader, EditorRows, FlexItem } from '@grafana/plugin-ui';
import { reportInteraction } from '@grafana/runtime';
import { Button, ConfirmModal, Space } from '@grafana/ui';

View File

@ -4,7 +4,7 @@ import * as React from 'react';
import { SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { EditorField } from '@grafana/experimental';
import { EditorField } from '@grafana/plugin-ui';
import { AutoSizeInput, Select } from '@grafana/ui';
import { LegendFormatMode } from '../../types';

View File

@ -1,5 +1,5 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/QueryPreview.tsx
import { EditorFieldGroup, EditorRow } from '@grafana/experimental';
import { EditorFieldGroup, EditorRow } from '@grafana/plugin-ui';
import promqlGrammar from '../../promql';
import { RawQuery } from '../shared/RawQuery';

View File

@ -1,24 +1,22 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/promQail/state/helpers.test.ts
import { llms } from '@grafana/experimental';
import { openai, vector } from '@grafana/llm';
import { guessMetricType, isLLMPluginEnabled } from './helpers';
// Mock the grafana-experimental llms module
jest.mock('@grafana/experimental', () => ({
llms: {
// Mock the grafana llms module
jest.mock('@grafana/llm', () => ({
openai: {
health: jest.fn(),
},
vector: {
health: jest.fn(),
},
},
}));
describe('isLLMPluginEnabled', () => {
it('should return true if LLM plugin is enabled', async () => {
jest.mocked(llms.openai.health).mockResolvedValue({ ok: true, configured: true });
jest.mocked(llms.vector.health).mockResolvedValue({ ok: true, enabled: true });
jest.mocked(openai.health).mockResolvedValue({ ok: true, configured: true });
jest.mocked(vector.health).mockResolvedValue({ ok: true, enabled: true });
const enabled = await isLLMPluginEnabled();
@ -26,8 +24,8 @@ describe('isLLMPluginEnabled', () => {
});
it('should return false if LLM plugin is not enabled', async () => {
jest.mocked(llms.openai.health).mockResolvedValue({ ok: false, configured: false });
jest.mocked(llms.vector.health).mockResolvedValue({ ok: false, enabled: false });
jest.mocked(openai.health).mockResolvedValue({ ok: false, configured: false });
jest.mocked(vector.health).mockResolvedValue({ ok: false, enabled: false });
const enabled = await isLLMPluginEnabled();
@ -35,8 +33,8 @@ describe('isLLMPluginEnabled', () => {
});
it('should return false if LLM plugin is enabled but health check fails', async () => {
jest.mocked(llms.openai.health).mockResolvedValue({ ok: false, configured: true });
jest.mocked(llms.vector.health).mockResolvedValue({ ok: false, enabled: true });
jest.mocked(openai.health).mockResolvedValue({ ok: false, configured: true });
jest.mocked(vector.health).mockResolvedValue({ ok: false, enabled: true });
const enabled = await isLLMPluginEnabled();

View File

@ -1,7 +1,7 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/promQail/state/helpers.ts
import { AnyAction } from 'redux';
import { llms } from '@grafana/experimental';
import { openai, vector } from '@grafana/llm';
import { reportInteraction } from '@grafana/runtime';
import { PrometheusDatasource } from '../../../../datasource';
@ -31,11 +31,7 @@ interface TemplateSearchResult {
promql: string | null;
}
export function getExplainMessage(
query: string,
metric: string,
datasource: PrometheusDatasource
): llms.openai.Message[] {
export function getExplainMessage(query: string, metric: string, datasource: PrometheusDatasource): openai.Message[] {
let metricMetadata = '';
let metricType = '';
@ -84,7 +80,7 @@ function getSuggestMessages({
metricType,
labels,
templates,
}: SuggestUserPromptParams): llms.openai.Message[] {
}: SuggestUserPromptParams): openai.Message[] {
return [
{ role: 'system', content: SuggestSystemPrompt },
{ role: 'user', content: GetSuggestUserPrompt({ promql, question, metricType, labels, templates }) },
@ -112,13 +108,13 @@ export async function promQailExplain(
const promptMessages = getExplainMessage(suggestedQuery, query.metric, datasource);
const interactionToUpdate = interaction;
return llms.openai
return openai
.streamChatCompletions({
model: OPENAI_MODEL_NAME,
messages: promptMessages,
temperature: 0,
})
.pipe(llms.openai.accumulateContent())
.pipe(openai.accumulateContent())
.subscribe((response) => {
const updatedSuggestions = interactionToUpdate.suggestions.map((sg: QuerySuggestion, sidx: number) => {
if (suggIdx === sidx) {
@ -274,8 +270,8 @@ function guessMetricFamily(metric: string): string {
export async function isLLMPluginEnabled(): Promise<boolean> {
// Check if the LLM plugin is enabled.
// If not, we won't be able to make requests, so return early.
const openaiEnabled = llms.openai.health().then((response) => response.ok);
const vectorEnabled = llms.vector.health().then((response) => response.ok);
const openaiEnabled = openai.health().then((response) => response.ok);
const vectorEnabled = vector.health().then((response) => response.ok);
// combine 2 promises
return Promise.all([openaiEnabled, vectorEnabled]).then((results) => {
return results.every((result) => result);
@ -392,13 +388,13 @@ export async function promQailSuggest(
templates: resultsString,
});
return llms.openai
return openai
.streamChatCompletions({
model: OPENAI_MODEL_NAME,
messages: promptMessages,
temperature: 0.5,
})
.pipe(llms.openai.accumulateContent())
.pipe(openai.accumulateContent())
.subscribe((response) => {
const payload = {
idx,

View File

@ -4,7 +4,7 @@ import { DraggableProvided } from '@hello-pangea/dnd';
import { memo, useState } from 'react';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { FlexItem } from '@grafana/experimental';
import { FlexItem } from '@grafana/plugin-ui';
import { Button, Select, useStyles2 } from '@grafana/ui';
import { OperationInfoButton } from './OperationInfoButton';

View File

@ -13,7 +13,7 @@ import {
import { memo, useState } from 'react';
import { GrafanaTheme2, renderMarkdown } from '@grafana/data';
import { FlexItem } from '@grafana/experimental';
import { FlexItem } from '@grafana/plugin-ui';
import { Button, Portal, useStyles2 } from '@grafana/ui';
import { QueryBuilderOperation, QueryBuilderOperationDef } from './types';

840
yarn.lock

File diff suppressed because it is too large Load Diff