mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
Prometheus: Use frontend package in Prometheus DS with a feature toggle (#84397)
* add feature toggle usePrometheusFrontendPackage * add feature toggle logic to Prometheus module * use config editor with package and remove configOverhaul feature toggle * update betterer because we will be removing other files as we replace with files from @grafana/prometheus * fix exemplar ds picker selector * add more description to ts-ignore * remove go.work.sum change * copy go.work.sum from main * update go.work.sum after talking with ismail * put back the promlib entry --------- Co-authored-by: ismail simsek <ismailsimsek09@gmail.com>
This commit is contained in:
parent
cdb64cb7eb
commit
d084595211
@ -5291,6 +5291,12 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Styles should be written using objects.", "18"],
|
||||
[0, 0, 0, "Styles should be written using objects.", "19"]
|
||||
],
|
||||
"public/app/plugins/datasource/prometheus/configuration/ConfigEditorPackage.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
|
||||
],
|
||||
"public/app/plugins/datasource/prometheus/configuration/ExemplarsSettings.tsx:5381": [
|
||||
[0, 0, 0, "Styles should be written using objects.", "0"]
|
||||
],
|
||||
|
@ -173,6 +173,7 @@ Experimental features might be changed or removed without prior notice.
|
||||
| `nodeGraphDotLayout` | Changed the layout algorithm for the node graph |
|
||||
| `kubernetesAggregator` | Enable grafana aggregator |
|
||||
| `expressionParser` | Enable new expression parser |
|
||||
| `usePrometheusFrontendPackage` | Use the @grafana/prometheus frontend package in core Prometheus. |
|
||||
|
||||
## Development feature toggles
|
||||
|
||||
|
@ -11,7 +11,7 @@ const addDataSource = () => {
|
||||
e2e.components.DataSource.Prometheus.configPage.exemplarsAddButton().click();
|
||||
e2e.components.DataSource.Prometheus.configPage.internalLinkSwitch().check({ force: true });
|
||||
e2e.components.DataSource.Prometheus.configPage.connectionSettings().type('http://prom-url:9090');
|
||||
e2e.components.DataSourcePicker.inputV2().click().should('have.focus');
|
||||
cy.get('[data-testid="data-testid Data source picker select container"]').click();
|
||||
|
||||
cy.contains('gdev-tempo').scrollIntoView().should('be.visible').click();
|
||||
},
|
||||
|
@ -409,6 +409,7 @@ github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 h1:/of8Z8taCPft
|
||||
github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.212.0/go.mod h1:qsI4ktDf0lig74u8SLPJf9zRdVxWV/W4Wi+Ox6gifgs=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.215.0/go.mod h1:nBsh3jRItKQUXDF2BQkiQCPxqrsSQeb+7hiFyJTO1RE=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.216.0/go.mod h1:FdvSvOliqpVLnytM7e89zCFyYPDE6VOn9SIjVQRvVxM=
|
||||
github.com/grafana/grafana/pkg/promlib v0.0.3/go.mod h1:3El4NlsfALz8QQCbEGHGFvJUG+538QLMuALRhZ3pcoo=
|
||||
github.com/grafana/grafana/pkg/promlib v0.0.4/go.mod h1:621zjsCaFtP7mqqaiMJRN9h3SXrywAMaIPkeHvq3jsk=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
|
||||
|
@ -175,4 +175,5 @@ export interface FeatureToggles {
|
||||
betterPageScrolling?: boolean;
|
||||
scopeFilters?: boolean;
|
||||
ssoSettingsSAML?: boolean;
|
||||
usePrometheusFrontendPackage?: boolean;
|
||||
}
|
||||
|
@ -1174,6 +1174,13 @@ var (
|
||||
HideFromDocs: true,
|
||||
HideFromAdminPage: true,
|
||||
},
|
||||
{
|
||||
Name: "usePrometheusFrontendPackage",
|
||||
Description: "Use the @grafana/prometheus frontend package in core Prometheus.",
|
||||
Stage: FeatureStageExperimental,
|
||||
FrontendOnly: true,
|
||||
Owner: grafanaObservabilityMetricsSquad,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -156,3 +156,4 @@ groupByVariable,experimental,@grafana/dashboards-squad,false,false,false
|
||||
betterPageScrolling,GA,@grafana/grafana-frontend-platform,false,false,true
|
||||
scopeFilters,experimental,@grafana/dashboards-squad,false,false,false
|
||||
ssoSettingsSAML,experimental,@grafana/identity-access-team,false,false,false
|
||||
usePrometheusFrontendPackage,experimental,@grafana/observability-metrics,false,false,true
|
||||
|
|
@ -634,4 +634,8 @@ const (
|
||||
// FlagSsoSettingsSAML
|
||||
// Use the new SSO Settings API to configure the SAML connector
|
||||
FlagSsoSettingsSAML = "ssoSettingsSAML"
|
||||
|
||||
// FlagUsePrometheusFrontendPackage
|
||||
// Use the @grafana/prometheus frontend package in core Prometheus.
|
||||
FlagUsePrometheusFrontendPackage = "usePrometheusFrontendPackage"
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,152 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
|
||||
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, GrafanaTheme2 } from '@grafana/data';
|
||||
import { AdvancedHttpSettings, ConfigSection, DataSourceDescription } from '@grafana/experimental';
|
||||
import { AlertingSettingsOverhaul, PromOptions, PromSettings } from '@grafana/prometheus';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Alert, FieldValidationMessage, useTheme2 } from '@grafana/ui';
|
||||
|
||||
import { AzureAuthSettings } from './AzureAuthSettings';
|
||||
import { hasCredentials, setDefaultCredentials, resetCredentials } from './AzureCredentialsConfig';
|
||||
import { DataSourcehttpSettingsOverhaul } from './DataSourceHttpSettingsOverhaulPackage';
|
||||
|
||||
export const PROM_CONFIG_LABEL_WIDTH = 30;
|
||||
|
||||
export type Props = DataSourcePluginOptionsEditorProps<PromOptions>;
|
||||
|
||||
export const ConfigEditor = (props: Props) => {
|
||||
const { options, onOptionsChange } = props;
|
||||
|
||||
const azureAuthSettings = {
|
||||
azureAuthSupported: config.azureAuthEnabled,
|
||||
getAzureAuthEnabled: (config: DataSourceSettings<any, any>): boolean => hasCredentials(config),
|
||||
setAzureAuthEnabled: (config: DataSourceSettings<any, any>, enabled: boolean) =>
|
||||
enabled ? setDefaultCredentials(config) : resetCredentials(config),
|
||||
azureSettingsUI: AzureAuthSettings,
|
||||
};
|
||||
|
||||
const theme = useTheme2();
|
||||
const styles = overhaulStyles(theme);
|
||||
|
||||
return (
|
||||
<>
|
||||
{options.access === 'direct' && (
|
||||
<Alert title="Error" severity="error">
|
||||
Browser access mode in the Prometheus data source is no longer available. Switch to server access mode.
|
||||
</Alert>
|
||||
)}
|
||||
<DataSourceDescription
|
||||
dataSourceName="Prometheus"
|
||||
docsLink="https://grafana.com/docs/grafana/latest/datasources/prometheus/configure-prometheus-data-source/"
|
||||
/>
|
||||
<hr className={`${styles.hrTopSpace} ${styles.hrBottomSpace}`} />
|
||||
<DataSourcehttpSettingsOverhaul
|
||||
options={options}
|
||||
onOptionsChange={onOptionsChange}
|
||||
azureAuthSettings={azureAuthSettings}
|
||||
sigV4AuthToggleEnabled={config.sigV4AuthEnabled}
|
||||
renderSigV4Editor={
|
||||
<SIGV4ConnectionConfig inExperimentalAuthComponent={true} {...props}></SIGV4ConnectionConfig>
|
||||
}
|
||||
secureSocksDSProxyEnabled={config.secureSocksDSProxyEnabled}
|
||||
/>
|
||||
<hr />
|
||||
<ConfigSection
|
||||
className={styles.advancedSettings}
|
||||
title="Advanced settings"
|
||||
description="Additional settings are optional settings that can be configured for more control over your data source."
|
||||
>
|
||||
<AdvancedHttpSettings
|
||||
className={styles.advancedHTTPSettingsMargin}
|
||||
config={options}
|
||||
onChange={onOptionsChange}
|
||||
/>
|
||||
<AlertingSettingsOverhaul<PromOptions> options={options} onOptionsChange={onOptionsChange} />
|
||||
<PromSettings options={options} onOptionsChange={onOptionsChange} />
|
||||
</ConfigSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Use this to return a url in a tooltip in a field. Don't forget to make the field interactive to be able to click on the tooltip
|
||||
* @param url
|
||||
* @returns
|
||||
*/
|
||||
export function docsTip(url?: string) {
|
||||
const docsUrl = 'https://grafana.com/docs/grafana/latest/datasources/prometheus/#configure-the-data-source';
|
||||
|
||||
return (
|
||||
<a href={url ? url : docsUrl} target="_blank" rel="noopener noreferrer">
|
||||
Visit docs for more details here.
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export const validateInput = (
|
||||
input: string,
|
||||
pattern: string | RegExp,
|
||||
errorMessage?: string
|
||||
): boolean | JSX.Element => {
|
||||
const defaultErrorMessage = 'Value is not valid';
|
||||
if (input && !input.match(pattern)) {
|
||||
return <FieldValidationMessage>{errorMessage ? errorMessage : defaultErrorMessage}</FieldValidationMessage>;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
export function overhaulStyles(theme: GrafanaTheme2) {
|
||||
return {
|
||||
additionalSettings: css({
|
||||
marginBottom: '25px',
|
||||
}),
|
||||
secondaryGrey: css({
|
||||
color: `${theme.colors.secondary.text}`,
|
||||
opacity: '65%',
|
||||
}),
|
||||
inlineError: css({
|
||||
margin: '0px 0px 4px 245px',
|
||||
}),
|
||||
switchField: css({
|
||||
alignItems: 'center',
|
||||
}),
|
||||
sectionHeaderPadding: css({
|
||||
paddingTop: '32px',
|
||||
}),
|
||||
sectionBottomPadding: css({
|
||||
paddingBottom: '28px',
|
||||
}),
|
||||
subsectionText: css({
|
||||
fontSize: '12px',
|
||||
}),
|
||||
hrBottomSpace: css({
|
||||
marginBottom: '56px',
|
||||
}),
|
||||
hrTopSpace: css({
|
||||
marginTop: '50px',
|
||||
}),
|
||||
textUnderline: css({
|
||||
textDecoration: 'underline',
|
||||
}),
|
||||
versionMargin: css({
|
||||
marginBottom: '12px',
|
||||
}),
|
||||
advancedHTTPSettingsMargin: css({
|
||||
margin: '24px 0 8px 0',
|
||||
}),
|
||||
advancedSettings: css({
|
||||
paddingTop: '32px',
|
||||
}),
|
||||
alertingTop: css({
|
||||
marginTop: '40px !important',
|
||||
}),
|
||||
overhaulPageHeading: css({
|
||||
fontWeight: '400',
|
||||
}),
|
||||
container: css({
|
||||
maxwidth: '578',
|
||||
}),
|
||||
};
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
import React, { ReactElement, useState } from 'react';
|
||||
|
||||
import { DataSourceSettings } from '@grafana/data';
|
||||
import { Auth, ConnectionSettings, convertLegacyAuthProps, AuthMethod } from '@grafana/experimental';
|
||||
import { PromOptions, docsTip, overhaulStyles } from '@grafana/prometheus';
|
||||
import { SecureSocksProxySettings, useTheme2 } from '@grafana/ui';
|
||||
// NEED TO EXPORT THIS FROM GRAFANA/UI FOR EXTERNAL DS
|
||||
import { AzureAuthSettings } from '@grafana/ui/src/components/DataSourceSettings/types';
|
||||
|
||||
type Props = {
|
||||
options: DataSourceSettings<PromOptions, {}>;
|
||||
onOptionsChange: (options: DataSourceSettings<PromOptions, {}>) => void;
|
||||
azureAuthSettings: AzureAuthSettings;
|
||||
sigV4AuthToggleEnabled: boolean | undefined;
|
||||
renderSigV4Editor: React.ReactNode;
|
||||
secureSocksDSProxyEnabled: boolean;
|
||||
};
|
||||
|
||||
// these are not available yet in grafana
|
||||
export type CustomMethodId = `custom-${string}`;
|
||||
|
||||
export type CustomMethod = {
|
||||
id: CustomMethodId;
|
||||
label: string;
|
||||
description: string;
|
||||
component: ReactElement;
|
||||
};
|
||||
|
||||
export const DataSourcehttpSettingsOverhaul = (props: Props) => {
|
||||
const {
|
||||
options,
|
||||
onOptionsChange,
|
||||
azureAuthSettings,
|
||||
sigV4AuthToggleEnabled,
|
||||
renderSigV4Editor,
|
||||
secureSocksDSProxyEnabled,
|
||||
} = props;
|
||||
|
||||
const newAuthProps = convertLegacyAuthProps({
|
||||
config: options,
|
||||
onChange: onOptionsChange,
|
||||
});
|
||||
|
||||
const theme = useTheme2();
|
||||
const styles = overhaulStyles(theme);
|
||||
|
||||
// for custom auth methods sigV4 and azure auth
|
||||
let customMethods: CustomMethod[] = [];
|
||||
|
||||
const [sigV4Selected, setSigV4Selected] = useState<boolean>(options.jsonData.sigV4Auth || false);
|
||||
|
||||
const sigV4Id = 'custom-sigV4Id';
|
||||
|
||||
const sigV4Option: CustomMethod = {
|
||||
id: sigV4Id,
|
||||
label: 'SigV4 auth',
|
||||
description: 'This is SigV4 auth description',
|
||||
component: <>{renderSigV4Editor}</>,
|
||||
};
|
||||
|
||||
if (sigV4AuthToggleEnabled) {
|
||||
customMethods.push(sigV4Option);
|
||||
}
|
||||
|
||||
const azureAuthEnabled: boolean =
|
||||
(azureAuthSettings?.azureAuthSupported && azureAuthSettings.getAzureAuthEnabled(options)) || false;
|
||||
|
||||
const [azureAuthSelected, setAzureAuthSelected] = useState<boolean>(azureAuthEnabled);
|
||||
|
||||
const azureAuthId = 'custom-azureAuthId';
|
||||
|
||||
const azureAuthOption: CustomMethod = {
|
||||
id: azureAuthId,
|
||||
label: 'Azure auth',
|
||||
description: 'This is Azure auth description',
|
||||
component: (
|
||||
<>
|
||||
{azureAuthSettings.azureSettingsUI && (
|
||||
<azureAuthSettings.azureSettingsUI dataSourceConfig={options} onChange={onOptionsChange} />
|
||||
)}
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
||||
// allow the option to show in the dropdown
|
||||
if (azureAuthSettings?.azureAuthSupported) {
|
||||
customMethods.push(azureAuthOption);
|
||||
}
|
||||
|
||||
function returnSelectedMethod() {
|
||||
if (sigV4Selected) {
|
||||
return sigV4Id;
|
||||
}
|
||||
|
||||
if (azureAuthSelected) {
|
||||
return azureAuthId;
|
||||
}
|
||||
|
||||
return newAuthProps.selectedMethod;
|
||||
}
|
||||
|
||||
// Do we need this switch anymore? Update the language.
|
||||
let urlTooltip;
|
||||
switch (options.access) {
|
||||
case 'direct':
|
||||
urlTooltip = (
|
||||
<>
|
||||
Your access method is <em>Browser</em>, this means the URL needs to be accessible from the browser.
|
||||
{docsTip()}
|
||||
</>
|
||||
);
|
||||
break;
|
||||
case 'proxy':
|
||||
urlTooltip = (
|
||||
<>
|
||||
Your access method is <em>Server</em>, this means the URL needs to be accessible from the grafana
|
||||
backend/server.
|
||||
{docsTip()}
|
||||
</>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
urlTooltip = <>Specify a complete HTTP URL (for example http://your_server:8080) {docsTip()}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConnectionSettings
|
||||
urlPlaceholder="http://localhost:9090"
|
||||
config={options}
|
||||
onChange={onOptionsChange}
|
||||
urlLabel="Prometheus server URL"
|
||||
urlTooltip={urlTooltip}
|
||||
/>
|
||||
<hr className={`${styles.hrTopSpace} ${styles.hrBottomSpace}`} />
|
||||
<Auth
|
||||
{...newAuthProps}
|
||||
customMethods={customMethods}
|
||||
onAuthMethodSelect={(method) => {
|
||||
// sigV4Id
|
||||
if (sigV4AuthToggleEnabled) {
|
||||
setSigV4Selected(method === sigV4Id);
|
||||
}
|
||||
|
||||
// Azure
|
||||
if (azureAuthSettings?.azureAuthSupported) {
|
||||
setAzureAuthSelected(method === azureAuthId);
|
||||
azureAuthSettings.setAzureAuthEnabled(options, method === azureAuthId);
|
||||
}
|
||||
|
||||
onOptionsChange({
|
||||
...options,
|
||||
basicAuth: method === AuthMethod.BasicAuth,
|
||||
withCredentials: method === AuthMethod.CrossSiteCredentials,
|
||||
jsonData: {
|
||||
...options.jsonData,
|
||||
sigV4Auth: method === sigV4Id,
|
||||
oauthPassThru: method === AuthMethod.OAuthForward,
|
||||
},
|
||||
});
|
||||
}}
|
||||
// If your method is selected pass its id to `selectedMethod`,
|
||||
// otherwise pass the id from converted legacy data
|
||||
selectedMethod={returnSelectedMethod()}
|
||||
/>
|
||||
<div className={styles.sectionBottomPadding} />
|
||||
{secureSocksDSProxyEnabled && (
|
||||
<>
|
||||
<SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} />
|
||||
<div className={styles.sectionBottomPadding} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,11 +1,27 @@
|
||||
import { DataSourcePlugin } from '@grafana/data';
|
||||
import {
|
||||
PrometheusDatasource as PrometheusDatasourcePackage,
|
||||
PromQueryEditorByApp as PromQueryEditorByAppPackage,
|
||||
PromCheatSheet as PromCheatSheetPackage,
|
||||
} from '@grafana/prometheus';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import PromCheatSheet from './components/PromCheatSheet';
|
||||
import PromQueryEditorByApp from './components/PromQueryEditorByApp';
|
||||
import { ConfigEditor } from './configuration/ConfigEditor';
|
||||
import { ConfigEditor as ConfigEditorPackage } from './configuration/ConfigEditorPackage';
|
||||
import { PrometheusDatasource } from './datasource';
|
||||
|
||||
export const plugin = new DataSourcePlugin(PrometheusDatasource)
|
||||
.setQueryEditor(PromQueryEditorByApp)
|
||||
.setConfigEditor(ConfigEditor)
|
||||
.setQueryEditorHelp(PromCheatSheet);
|
||||
const usePackage = config.featureToggles.usePrometheusFrontendPackage;
|
||||
|
||||
const PrometheusDataSourceUsed = usePackage ? PrometheusDatasource : PrometheusDatasourcePackage;
|
||||
const PromQueryEditorByAppUsed = usePackage ? PromQueryEditorByApp : PromQueryEditorByAppPackage;
|
||||
const ConfigEditorUsed = usePackage ? ConfigEditor : ConfigEditorPackage;
|
||||
const PromCheatSheetUsed = usePackage ? PromCheatSheet : PromCheatSheetPackage;
|
||||
|
||||
// @ts-ignore These type errors will be removed when we fully migrate to the @grafana/prometheus package
|
||||
export const plugin = new DataSourcePlugin(PrometheusDataSourceUsed)
|
||||
// @ts-ignore These type errors will be removed when we fully migrate to the @grafana/prometheus package
|
||||
.setQueryEditor(PromQueryEditorByAppUsed)
|
||||
.setConfigEditor(ConfigEditorUsed)
|
||||
.setQueryEditorHelp(PromCheatSheetUsed);
|
||||
|
Loading…
Reference in New Issue
Block a user