Brojd/implement insights (#3583)
# What this PR does - Use Grafana Scenes to add Insights as a separate page in OnCall - Add an option to run Prometheus instance via helm so that Prometheus Exporter feature can be used easily without the need of setting up Prometheus separately ## Which issue(s) this PR fixes https://github.com/grafana/oncall-private/issues/2382 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
This commit is contained in:
parent
74b68a8d27
commit
960dcae608
39 changed files with 1993 additions and 12 deletions
10
.github/helm-values.yml
vendored
10
.github/helm-values.yml
vendored
|
|
@ -4,6 +4,8 @@ base_url_protocol: http
|
||||||
env:
|
env:
|
||||||
- name: GRAFANA_CLOUD_NOTIFICATIONS_ENABLED
|
- name: GRAFANA_CLOUD_NOTIFICATIONS_ENABLED
|
||||||
value: "False"
|
value: "False"
|
||||||
|
- name: FEATURE_PROMETHEUS_EXPORTER_ENABLED
|
||||||
|
value: "True"
|
||||||
image:
|
image:
|
||||||
tag: latest
|
tag: latest
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|
@ -104,3 +106,11 @@ service:
|
||||||
type: NodePort
|
type: NodePort
|
||||||
port: 8080
|
port: 8080
|
||||||
nodePort: 30001
|
nodePort: 30001
|
||||||
|
prometheus:
|
||||||
|
enabled: true
|
||||||
|
extraScrapeConfigs: |
|
||||||
|
- job_name: 'oncall-exporter'
|
||||||
|
metrics_path: /metrics/
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- oncall-dev-engine.default.svc.cluster.local:8080
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Move Insights to OnCall as a separate page ([#2382](https://github.com/grafana/oncall-private/issues/2382))
|
||||||
|
|
||||||
## v1.3.82 (2024-01-04)
|
## v1.3.82 (2024-01-04)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -133,3 +133,11 @@ service:
|
||||||
type: NodePort
|
type: NodePort
|
||||||
port: 8080
|
port: 8080
|
||||||
nodePort: 30001
|
nodePort: 30001
|
||||||
|
prometheus:
|
||||||
|
enabled: false
|
||||||
|
extraScrapeConfigs: |
|
||||||
|
- job_name: 'oncall-exporter'
|
||||||
|
metrics_path: /metrics/
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- oncall-dev-engine.default.svc.cluster.local:8080
|
||||||
|
|
|
||||||
65
grafana-plugin/e2e-tests/insights/insights.test.ts
Normal file
65
grafana-plugin/e2e-tests/insights/insights.test.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { test, expect } from '../fixtures';
|
||||||
|
import { resolveFiringAlert } from '../utils/alertGroup';
|
||||||
|
import { createEscalationChain, EscalationStep } from '../utils/escalationChain';
|
||||||
|
import { clickButton, generateRandomValue } from '../utils/forms';
|
||||||
|
import { createIntegrationAndSendDemoAlert } from '../utils/integrations';
|
||||||
|
import { goToGrafanaPage, goToOnCallPage } from '../utils/navigation';
|
||||||
|
import { createOnCallSchedule } from '../utils/schedule';
|
||||||
|
|
||||||
|
test.describe('Insights', () => {
|
||||||
|
test.beforeAll(async ({ adminRolePage: { page, userName } }) => {
|
||||||
|
const DATASOURCE_NAME = 'OnCall Prometheus';
|
||||||
|
const DATASOURCE_URL = 'http://oncall-dev-prometheus-server.default.svc.cluster.local';
|
||||||
|
|
||||||
|
await goToGrafanaPage(page, '/connections/datasources');
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
// setup data source if it's not already connected
|
||||||
|
const isDataSourceAlreadyConnected = await page.getByText(DATASOURCE_NAME).isVisible();
|
||||||
|
if (!isDataSourceAlreadyConnected) {
|
||||||
|
await page.getByRole('link', { name: 'Add data source' }).click();
|
||||||
|
await clickButton({ page, buttonText: 'Prometheus' });
|
||||||
|
await page.getByRole('textbox', { name: 'Data source settings page name input field' }).fill(DATASOURCE_NAME);
|
||||||
|
await page.getByPlaceholder('http://localhost:9090').fill(DATASOURCE_URL);
|
||||||
|
await clickButton({ page, buttonText: 'Save & test' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// send alert and resolve to get some values in insights
|
||||||
|
const escalationChainName = generateRandomValue();
|
||||||
|
const integrationName = generateRandomValue();
|
||||||
|
const onCallScheduleName = generateRandomValue();
|
||||||
|
await createOnCallSchedule(page, onCallScheduleName, userName);
|
||||||
|
await createEscalationChain(
|
||||||
|
page,
|
||||||
|
escalationChainName,
|
||||||
|
EscalationStep.NotifyUsersFromOnCallSchedule,
|
||||||
|
onCallScheduleName
|
||||||
|
);
|
||||||
|
await createIntegrationAndSendDemoAlert(page, integrationName, escalationChainName);
|
||||||
|
await resolveFiringAlert(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Viewer can see all the panels in OnCall insights', async ({ viewerRolePage: { page } }) => {
|
||||||
|
await goToOnCallPage(page, 'insights');
|
||||||
|
[
|
||||||
|
'Total alert groups',
|
||||||
|
'Total alert groups by state',
|
||||||
|
'New alert groups for selected period',
|
||||||
|
'Mean time to respond \\(MTTR\\)',
|
||||||
|
'MTTR changed for period',
|
||||||
|
'New alert groups during time period',
|
||||||
|
'Alert groups by Integration',
|
||||||
|
'Mean time to respond \\(MTTR\\) by Integration',
|
||||||
|
].forEach(async (panelTitle) => {
|
||||||
|
await expect(page.getByRole('heading', { name: new RegExp(`^${panelTitle}$`) }).first()).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('There is no panel that misses data', async ({ adminRolePage: { page } }) => {
|
||||||
|
await goToOnCallPage(page, 'insights');
|
||||||
|
await page.getByText('Last 7 days').click();
|
||||||
|
await page.getByText('Last 1 hour').click();
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await expect(page.getByText('No data')).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -98,3 +98,9 @@ export const verifyThatAlertGroupIsTriggered = async (
|
||||||
|
|
||||||
expect(await incidentTimelineContainsStep(page, triggeredStepText)).toBe(true);
|
expect(await incidentTimelineContainsStep(page, triggeredStepText)).toBe(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const resolveFiringAlert = async (page: Page) => {
|
||||||
|
await goToOnCallPage(page, 'alert-groups');
|
||||||
|
await page.getByText('Firing').nth(1).click();
|
||||||
|
await page.getByLabel('Context menu').getByText('Resolve').click();
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ import type { Page } from '@playwright/test';
|
||||||
|
|
||||||
import { BASE_URL } from './constants';
|
import { BASE_URL } from './constants';
|
||||||
|
|
||||||
type GrafanaPage = '/plugins/grafana-oncall-app';
|
type OnCallPage = 'alert-groups' | 'integrations' | 'escalations' | 'schedules' | 'users' | 'insights';
|
||||||
type OnCallPage = 'alert-groups' | 'integrations' | 'escalations' | 'schedules' | 'users';
|
|
||||||
|
|
||||||
const _goToPage = async (page: Page, url = '') => page.goto(`${BASE_URL}${url}`);
|
const _goToPage = async (page: Page, url = '') => page.goto(`${BASE_URL}${url}`);
|
||||||
|
|
||||||
export const goToGrafanaPage = async (page: Page, url: GrafanaPage) => _goToPage(page, url);
|
export const goToGrafanaPage = async (page: Page, url = '') => _goToPage(page, url);
|
||||||
|
|
||||||
export const goToOnCallPage = async (page: Page, onCallPage: OnCallPage) => {
|
export const goToOnCallPage = async (page: Page, onCallPage: OnCallPage) => {
|
||||||
await _goToPage(page, `/a/grafana-oncall-app/${onCallPage}`);
|
await _goToPage(page, `/a/grafana-oncall-app/${onCallPage}`);
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,8 @@
|
||||||
"@grafana/faro-web-tracing": "^1.0.0-beta4",
|
"@grafana/faro-web-tracing": "^1.0.0-beta4",
|
||||||
"@grafana/labels": "~1.4.4",
|
"@grafana/labels": "~1.4.4",
|
||||||
"@grafana/runtime": "9.3.0-beta1",
|
"@grafana/runtime": "9.3.0-beta1",
|
||||||
|
"@grafana/scenes": "^1.28.0",
|
||||||
|
"@grafana/schema": "^10.2.2",
|
||||||
"@grafana/ui": "^10.2.0",
|
"@grafana/ui": "^10.2.0",
|
||||||
"@lifeomic/attempt": "^3.0.3",
|
"@lifeomic/attempt": "^3.0.3",
|
||||||
"@opentelemetry/api": "^1.3.0",
|
"@opentelemetry/api": "^1.3.0",
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ export default function Alerts() {
|
||||||
|
|
||||||
function showMismatchWarning(): boolean {
|
function showMismatchWarning(): boolean {
|
||||||
return (
|
return (
|
||||||
store.isOpenSource() &&
|
store.isOpenSource &&
|
||||||
store.backendVersion &&
|
store.backendVersion &&
|
||||||
plugin?.version &&
|
plugin?.version &&
|
||||||
store.backendVersion !== plugin?.version &&
|
store.backendVersion !== plugin?.version &&
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ const mockUseStore = (rest?: any, connected = false, cloud_connected = true) =>
|
||||||
cloudConnectionStatus: { cloud_connection_status: cloud_connected },
|
cloudConnectionStatus: { cloud_connection_status: cloud_connected },
|
||||||
} as unknown as CloudStore,
|
} as unknown as CloudStore,
|
||||||
hasFeature: jest.fn().mockReturnValue(true),
|
hasFeature: jest.fn().mockReturnValue(true),
|
||||||
isOpenSource: jest.fn().mockReturnValue(true),
|
isOpenSource: true,
|
||||||
} as unknown as RootStore;
|
} as unknown as RootStore;
|
||||||
|
|
||||||
useStore.mockReturnValue(store);
|
useStore.mockReturnValue(store);
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ const MobileAppConnection = observer(({ userPk }: Props) => {
|
||||||
<QRCode className={cx({ 'qr-code': true, blurry: isQRBlurry })} value={QRCodeValue} />
|
<QRCode className={cx({ 'qr-code': true, blurry: isQRBlurry })} value={QRCodeValue} />
|
||||||
{isQRBlurry && <QRLoading />}
|
{isQRBlurry && <QRLoading />}
|
||||||
</div>
|
</div>
|
||||||
{store.isOpenSource() && QRCodeDataParsed && (
|
{store.isOpenSource && QRCodeDataParsed && (
|
||||||
<Text type="secondary">
|
<Text type="secondary">
|
||||||
Server URL embedded in this QR:
|
Server URL embedded in this QR:
|
||||||
<br />
|
<br />
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ const Header = observer(() => {
|
||||||
);
|
);
|
||||||
|
|
||||||
function renderHeading() {
|
function renderHeading() {
|
||||||
if (store.isOpenSource()) {
|
if (store.isOpenSource) {
|
||||||
return (
|
return (
|
||||||
<div className={cx('heading')}>
|
<div className={cx('heading')}>
|
||||||
<h1 className={cx('page-header__title')}>Grafana OnCall</h1>
|
<h1 className={cx('page-header__title')}>Grafana OnCall</h1>
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,12 @@ export const pages: { [id: string]: PageDefinition } = [
|
||||||
path: getPath('cloud'),
|
path: getPath('cloud'),
|
||||||
action: UserActions.OtherSettingsWrite,
|
action: UserActions.OtherSettingsWrite,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: 'cloud',
|
||||||
|
id: 'insights',
|
||||||
|
text: 'Insights',
|
||||||
|
path: getPath('insights'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
id: 'test',
|
id: 'test',
|
||||||
|
|
@ -180,6 +186,7 @@ export const ROUTES = {
|
||||||
'chat-ops': ['chat-ops'],
|
'chat-ops': ['chat-ops'],
|
||||||
'live-settings': ['live-settings'],
|
'live-settings': ['live-settings'],
|
||||||
cloud: ['cloud'],
|
cloud: ['cloud'],
|
||||||
|
insights: ['insights'],
|
||||||
test: ['test'],
|
test: ['test'],
|
||||||
|
|
||||||
// backwards compatible to redirect to new alert-groups
|
// backwards compatible to redirect to new alert-groups
|
||||||
|
|
|
||||||
4
grafana-plugin/src/pages/insights/Insights.helpers.ts
Normal file
4
grafana-plugin/src/pages/insights/Insights.helpers.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { DataSourceRef } from '@grafana/schema';
|
||||||
|
|
||||||
|
export const getDataSource = (isOpenSource: boolean): DataSourceRef =>
|
||||||
|
isOpenSource ? { uid: '$datasource' } : { uid: 'grafanacloud-usage' };
|
||||||
170
grafana-plugin/src/pages/insights/Insights.tsx
Normal file
170
grafana-plugin/src/pages/insights/Insights.tsx
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
EmbeddedScene,
|
||||||
|
SceneTimeRange,
|
||||||
|
SceneFlexLayout,
|
||||||
|
SceneControlsSpacer,
|
||||||
|
SceneRefreshPicker,
|
||||||
|
SceneTimePicker,
|
||||||
|
SceneVariableSet,
|
||||||
|
VariableValueSelectors,
|
||||||
|
NestedScene,
|
||||||
|
} from '@grafana/scenes';
|
||||||
|
import { Alert } from '@grafana/ui';
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
|
|
||||||
|
import Text from 'components/Text/Text';
|
||||||
|
import { useStore } from 'state/useStore';
|
||||||
|
import { DOCS_ROOT } from 'utils/consts';
|
||||||
|
|
||||||
|
import { getDataSource } from './Insights.helpers';
|
||||||
|
import { InsightsConfig } from './Insights.types';
|
||||||
|
import getAlertGroupsByIntegrationScene from './scenes/AlertGroupsByIntegration';
|
||||||
|
import getAlertGroupsByTeamScene from './scenes/AlertGroupsByTeam';
|
||||||
|
import getMTTRScene from './scenes/MTTR';
|
||||||
|
import getMTTRByIntegrationScene from './scenes/MTTRByIntegration';
|
||||||
|
import getMTTRByTeamScene from './scenes/MTTRByTeam';
|
||||||
|
import getMTTRChangedForPeriodStatScene from './scenes/MTTRChangedForPeriodStat';
|
||||||
|
import getMTTRChangedForPeriodTimeseriesScene from './scenes/MTTRChangedForPeriodTimeseries';
|
||||||
|
import getNewAlertGroupsDuringTimePeriodScene from './scenes/NewAlertGroupsDuringTimePeriod';
|
||||||
|
import getNewAlertGroupsForSelectedPeriodScene from './scenes/NewAlertGroupsForSelectedPeriod';
|
||||||
|
import getNewAlertGroupsNotificationsDuringTimePeriodScene from './scenes/NewAlertGroupsNotificationsDuringTimePeriod';
|
||||||
|
import getNewAlertGroupsNotificationsForPeriodTableScene from './scenes/NewAlertGroupsNotificationsForPeriodTable';
|
||||||
|
import getNewAlertGroupsNotificationsInTotalScene from './scenes/NewAlertGroupsNotificationsInTotal';
|
||||||
|
import getTotalAlertGroupsScene from './scenes/TotalAlertGroups';
|
||||||
|
import getTotalAlertGroupsByStateScene from './scenes/TotalAlertGroupsByState';
|
||||||
|
import getVariables from './variables';
|
||||||
|
|
||||||
|
const Insights = observer(() => {
|
||||||
|
const { isOpenSource } = useStore();
|
||||||
|
const [alertVisible, setAlertVisible] = useState(true);
|
||||||
|
|
||||||
|
const rootScene = useMemo(
|
||||||
|
() => getRootScene({ isOpenSource, datasource: getDataSource(isOpenSource) }),
|
||||||
|
[isOpenSource]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isOpenSource && alertVisible && (
|
||||||
|
<Alert onRemove={() => setAlertVisible(false)} severity="info" title="">
|
||||||
|
{
|
||||||
|
<>
|
||||||
|
In order to see insights you need to set up Prometheus, add it to your Grafana instance as a data source,
|
||||||
|
set FEATURE_PROMETHEUS_EXPORTER_ENABLED environment variable to true and then select your Data source in
|
||||||
|
the dropdown below.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<>
|
||||||
|
You can find out more in
|
||||||
|
<a
|
||||||
|
href={`${DOCS_ROOT}/insights-and-metrics/#for-open-source-customers`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<Text type="link"> documentation</Text>
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
<rootScene.Component model={rootScene} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const getRootScene = (config: InsightsConfig) =>
|
||||||
|
new EmbeddedScene({
|
||||||
|
$timeRange: new SceneTimeRange({ from: 'now-7d', to: 'now' }),
|
||||||
|
$variables: new SceneVariableSet({
|
||||||
|
variables: getVariables(config),
|
||||||
|
}),
|
||||||
|
controls: [
|
||||||
|
new VariableValueSelectors({}),
|
||||||
|
new SceneControlsSpacer(),
|
||||||
|
new SceneTimePicker({}),
|
||||||
|
new SceneRefreshPicker({}),
|
||||||
|
],
|
||||||
|
body: new SceneFlexLayout({
|
||||||
|
direction: 'column',
|
||||||
|
children: [
|
||||||
|
new NestedScene({
|
||||||
|
title: 'Overview',
|
||||||
|
canCollapse: true,
|
||||||
|
isCollapsed: false,
|
||||||
|
body: new SceneFlexLayout({
|
||||||
|
direction: 'column',
|
||||||
|
children: [
|
||||||
|
new SceneFlexLayout({
|
||||||
|
height: 200,
|
||||||
|
children: [
|
||||||
|
getTotalAlertGroupsScene(config),
|
||||||
|
getTotalAlertGroupsByStateScene(config),
|
||||||
|
getNewAlertGroupsForSelectedPeriodScene(config),
|
||||||
|
getMTTRScene(config),
|
||||||
|
getMTTRChangedForPeriodStatScene(config),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new SceneFlexLayout({
|
||||||
|
height: 400,
|
||||||
|
children: [getNewAlertGroupsDuringTimePeriodScene(config)],
|
||||||
|
}),
|
||||||
|
new SceneFlexLayout({
|
||||||
|
height: 400,
|
||||||
|
children: [getMTTRChangedForPeriodTimeseriesScene(config)],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
new NestedScene({
|
||||||
|
title: 'Integrations data',
|
||||||
|
canCollapse: true,
|
||||||
|
isCollapsed: false,
|
||||||
|
body: new SceneFlexLayout({
|
||||||
|
height: 400,
|
||||||
|
children: [getAlertGroupsByIntegrationScene(config), getMTTRByIntegrationScene(config)],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
new NestedScene({
|
||||||
|
title: 'Notified alert groups by Users (based on all Integrations)',
|
||||||
|
canCollapse: true,
|
||||||
|
isCollapsed: false,
|
||||||
|
body: new SceneFlexLayout({
|
||||||
|
direction: 'column',
|
||||||
|
children: [
|
||||||
|
new SceneFlexLayout({
|
||||||
|
height: 400,
|
||||||
|
children: [getNewAlertGroupsNotificationsDuringTimePeriodScene(config)],
|
||||||
|
}),
|
||||||
|
new SceneFlexLayout({
|
||||||
|
height: 400,
|
||||||
|
children: [
|
||||||
|
getNewAlertGroupsNotificationsInTotalScene(config),
|
||||||
|
getNewAlertGroupsNotificationsForPeriodTableScene(config),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
new NestedScene({
|
||||||
|
title: 'Teams data',
|
||||||
|
canCollapse: true,
|
||||||
|
isCollapsed: false,
|
||||||
|
body: new SceneFlexLayout({
|
||||||
|
direction: 'column',
|
||||||
|
children: [
|
||||||
|
new SceneFlexLayout({
|
||||||
|
height: 400,
|
||||||
|
children: [getAlertGroupsByTeamScene(config), getMTTRByTeamScene(config)],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Insights;
|
||||||
6
grafana-plugin/src/pages/insights/Insights.types.ts
Normal file
6
grafana-plugin/src/pages/insights/Insights.types.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { DataSourceRef } from '@grafana/schema';
|
||||||
|
|
||||||
|
export interface InsightsConfig {
|
||||||
|
isOpenSource: boolean;
|
||||||
|
datasource: DataSourceRef;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getAlertGroupsByIntegrationScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'sort_desc(max_over_time(sum by(integration) (avg without(pod, instance)($alert_groups_total{slug=~"$instance", team=~"$team", integration=~"$integration"}))[1d:]))',
|
||||||
|
format: 'table',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'seriesToRows',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {
|
||||||
|
Time: true,
|
||||||
|
},
|
||||||
|
indexByName: {},
|
||||||
|
renameByName: {
|
||||||
|
Metric: 'Integration',
|
||||||
|
Value: 'Alert groups',
|
||||||
|
integration: 'Integration',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'Alert groups by Integration',
|
||||||
|
pluginId: 'table',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
align: 'auto',
|
||||||
|
cellOptions: {
|
||||||
|
mode: 'gradient',
|
||||||
|
type: 'gauge',
|
||||||
|
valueDisplayMode: 'color',
|
||||||
|
},
|
||||||
|
filterable: false,
|
||||||
|
inspect: false,
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Integration',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.cellOptions',
|
||||||
|
value: {
|
||||||
|
type: 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom.width',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
cellHeight: 'sm',
|
||||||
|
footer: {
|
||||||
|
countRows: false,
|
||||||
|
fields: '',
|
||||||
|
reducer: ['sum'],
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
showHeader: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
111
grafana-plugin/src/pages/insights/scenes/AlertGroupsByTeam.tsx
Normal file
111
grafana-plugin/src/pages/insights/scenes/AlertGroupsByTeam.tsx
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getAlertGroupsByTeamScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'sort_desc(max_over_time(sum by(team) (avg without(pod, instance)($alert_groups_total{slug=~"$instance", team=~"$team", integration=~"$integration"}))[1d:]))',
|
||||||
|
format: 'table',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'seriesToRows',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {
|
||||||
|
Time: true,
|
||||||
|
},
|
||||||
|
indexByName: {},
|
||||||
|
renameByName: {
|
||||||
|
Metric: 'Integration',
|
||||||
|
Value: 'Alert groups',
|
||||||
|
team: 'Team',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'Alert groups by Team',
|
||||||
|
pluginId: 'table',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
align: 'auto',
|
||||||
|
cellOptions: {
|
||||||
|
mode: 'gradient',
|
||||||
|
type: 'gauge',
|
||||||
|
valueDisplayMode: 'color',
|
||||||
|
},
|
||||||
|
filterable: false,
|
||||||
|
inspect: false,
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Team',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.cellOptions',
|
||||||
|
value: {
|
||||||
|
type: 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom.width',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
cellHeight: 'sm',
|
||||||
|
footer: {
|
||||||
|
countRows: false,
|
||||||
|
fields: '',
|
||||||
|
reducer: ['sum'],
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
showHeader: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
74
grafana-plugin/src/pages/insights/scenes/MTTR.tsx
Normal file
74
grafana-plugin/src/pages/insights/scenes/MTTR.tsx
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getMTTRScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'avg_over_time((sum($alert_groups_response_time_seconds_sum{slug=~"$instance", team=~"$team", integration=~"$integration"}) / sum($alert_groups_response_time_seconds_count{slug=~"$instance", team=~"$team", integration=~"$integration"}))[$__range:])',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'Mean time to respond (MTTR)',
|
||||||
|
description: 'Mean time between the start and first action of all alert groups for the last 7 days',
|
||||||
|
pluginId: 'stat',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'text',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 's',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Value',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'displayName',
|
||||||
|
value: 'MTTR',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
colorMode: 'value',
|
||||||
|
graphMode: 'none',
|
||||||
|
justifyMode: 'center',
|
||||||
|
orientation: 'auto',
|
||||||
|
reduceOptions: {
|
||||||
|
calcs: ['lastNotNull'],
|
||||||
|
fields: '',
|
||||||
|
values: false,
|
||||||
|
},
|
||||||
|
textMode: 'auto',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
126
grafana-plugin/src/pages/insights/scenes/MTTRByIntegration.tsx
Normal file
126
grafana-plugin/src/pages/insights/scenes/MTTRByIntegration.tsx
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getMTTRByIntegrationScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'sort_desc(avg_over_time((sum by (integration)($alert_groups_response_time_seconds_sum{slug=~"$instance", team=~"$team", integration=~"$integration"}) / sum by (integration)($alert_groups_response_time_seconds_count{slug=~"$instance", team=~"$team", integration=~"$integration"}))[$__range:]))',
|
||||||
|
format: 'table',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'seriesToRows',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {
|
||||||
|
Time: true,
|
||||||
|
cluster: true,
|
||||||
|
container: true,
|
||||||
|
id: true,
|
||||||
|
instance: true,
|
||||||
|
job: true,
|
||||||
|
namespace: true,
|
||||||
|
org_id: true,
|
||||||
|
pod: true,
|
||||||
|
slug: true,
|
||||||
|
team: true,
|
||||||
|
},
|
||||||
|
indexByName: {},
|
||||||
|
renameByName: {
|
||||||
|
Metric: 'Integration',
|
||||||
|
Value: 'MTTR',
|
||||||
|
integration: 'Integration',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'Mean time to respond (MTTR) by Integration',
|
||||||
|
pluginId: 'table',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'continuous-GrYlRd',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
align: 'auto',
|
||||||
|
cellOptions: {
|
||||||
|
mode: 'gradient',
|
||||||
|
type: 'gauge',
|
||||||
|
valueDisplayMode: 'text',
|
||||||
|
},
|
||||||
|
filterable: false,
|
||||||
|
inspect: false,
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'red',
|
||||||
|
value: 5400,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 's',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Integration',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.cellOptions',
|
||||||
|
value: {
|
||||||
|
type: 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom.width',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
cellHeight: 'sm',
|
||||||
|
footer: {
|
||||||
|
countRows: false,
|
||||||
|
fields: '',
|
||||||
|
reducer: ['sum'],
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
showHeader: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
116
grafana-plugin/src/pages/insights/scenes/MTTRByTeam.tsx
Normal file
116
grafana-plugin/src/pages/insights/scenes/MTTRByTeam.tsx
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getMTTRByTeamScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'sort_desc(avg_over_time((sum by(team) ($alert_groups_response_time_seconds_sum{slug=~"$instance", team=~"$team", integration=~"$integration"}) / sum by(team)($alert_groups_response_time_seconds_count{slug=~"$instance", team=~"$team", integration=~"$integration"}))[$__range:]))',
|
||||||
|
format: 'table',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'seriesToRows',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {
|
||||||
|
Time: true,
|
||||||
|
},
|
||||||
|
indexByName: {},
|
||||||
|
renameByName: {
|
||||||
|
Metric: 'Integration',
|
||||||
|
Value: 'MTTR',
|
||||||
|
team: 'Team',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'Mean time to respond by Team (MTTR)',
|
||||||
|
pluginId: 'table',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'continuous-GrYlRd',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
align: 'left',
|
||||||
|
cellOptions: {
|
||||||
|
mode: 'gradient',
|
||||||
|
type: 'gauge',
|
||||||
|
valueDisplayMode: 'text',
|
||||||
|
},
|
||||||
|
filterable: false,
|
||||||
|
inspect: false,
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'red',
|
||||||
|
value: 5400,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 's',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Team',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.cellOptions',
|
||||||
|
value: {
|
||||||
|
type: 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom.width',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
cellHeight: 'sm',
|
||||||
|
footer: {
|
||||||
|
countRows: false,
|
||||||
|
fields: '',
|
||||||
|
reducer: ['sum'],
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
showHeader: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getMTTRChangedForPeriodStatScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'avg(sum($alert_groups_response_time_seconds_sum{slug=~"$instance", team=~"$team", integration=~"$integration"}) / sum($alert_groups_response_time_seconds_count{slug=~"$instance", team=~"$team", integration=~"$integration"}))',
|
||||||
|
instant: false,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: true,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'MTTR changed for period',
|
||||||
|
pluginId: 'stat',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'blue',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: -10000000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'super-light-yellow',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 's',
|
||||||
|
},
|
||||||
|
overrides: [],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
colorMode: 'value',
|
||||||
|
graphMode: 'none',
|
||||||
|
justifyMode: 'center',
|
||||||
|
orientation: 'auto',
|
||||||
|
reduceOptions: {
|
||||||
|
calcs: ['diff'],
|
||||||
|
fields: '',
|
||||||
|
values: false,
|
||||||
|
},
|
||||||
|
textMode: 'auto',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getMTTRChangedForPeriodTimeseriesScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'avg(sum($alert_groups_response_time_seconds_sum{slug=~"$instance", team=~"$team", integration=~"$integration"}) / sum($alert_groups_response_time_seconds_count{slug=~"$instance", team=~"$team", integration=~"$integration"}))',
|
||||||
|
instant: false,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: true,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'MTTR changed for period',
|
||||||
|
pluginId: 'timeseries',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
fixedColor: 'green',
|
||||||
|
mode: 'fixed',
|
||||||
|
seriesBy: 'min',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
axisCenteredZero: false,
|
||||||
|
axisColorMode: 'text',
|
||||||
|
axisLabel: '',
|
||||||
|
axisPlacement: 'auto',
|
||||||
|
barAlignment: 0,
|
||||||
|
drawStyle: 'line',
|
||||||
|
fillOpacity: 54,
|
||||||
|
gradientMode: 'opacity',
|
||||||
|
hideFrom: {
|
||||||
|
legend: false,
|
||||||
|
tooltip: false,
|
||||||
|
viz: false,
|
||||||
|
},
|
||||||
|
lineInterpolation: 'linear',
|
||||||
|
lineStyle: {
|
||||||
|
fill: 'solid',
|
||||||
|
},
|
||||||
|
lineWidth: 1,
|
||||||
|
pointSize: 5,
|
||||||
|
scaleDistribution: {
|
||||||
|
type: 'linear',
|
||||||
|
},
|
||||||
|
showPoints: 'auto',
|
||||||
|
spanNulls: true,
|
||||||
|
stacking: {
|
||||||
|
group: 'A',
|
||||||
|
mode: 'none',
|
||||||
|
},
|
||||||
|
thresholdsStyle: {
|
||||||
|
mode: 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'text',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 's',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Value',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'displayName',
|
||||||
|
value: 'MTTR',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
legend: {
|
||||||
|
displayMode: 'list',
|
||||||
|
placement: 'bottom',
|
||||||
|
showLegend: false,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
mode: 'single',
|
||||||
|
sort: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getNewAlertGroupsDuringTimePeriodScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
disableTextWrap: false,
|
||||||
|
editorMode: 'code',
|
||||||
|
excludeNullMetadata: false,
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'increase(max_over_time(sum by (integration) (avg without(pod, instance) ($alert_groups_total{slug=~"$instance", team=~"$team", integration=~"$integration"}))[30m:])[1h:])',
|
||||||
|
fullMetaSearch: false,
|
||||||
|
instant: false,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: true,
|
||||||
|
refId: 'A',
|
||||||
|
useBackend: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'New alert groups during time period',
|
||||||
|
pluginId: 'timeseries',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'palette-classic',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
axisCenteredZero: false,
|
||||||
|
axisColorMode: 'text',
|
||||||
|
axisLabel: '',
|
||||||
|
axisPlacement: 'auto',
|
||||||
|
barAlignment: 0,
|
||||||
|
drawStyle: 'line',
|
||||||
|
fillOpacity: 80,
|
||||||
|
gradientMode: 'opacity',
|
||||||
|
hideFrom: {
|
||||||
|
legend: false,
|
||||||
|
tooltip: false,
|
||||||
|
viz: false,
|
||||||
|
},
|
||||||
|
lineInterpolation: 'linear',
|
||||||
|
lineStyle: {
|
||||||
|
fill: 'solid',
|
||||||
|
},
|
||||||
|
lineWidth: 1,
|
||||||
|
pointSize: 5,
|
||||||
|
scaleDistribution: {
|
||||||
|
type: 'linear',
|
||||||
|
},
|
||||||
|
showPoints: 'auto',
|
||||||
|
spanNulls: false,
|
||||||
|
stacking: {
|
||||||
|
group: 'A',
|
||||||
|
mode: 'normal',
|
||||||
|
},
|
||||||
|
thresholdsStyle: {
|
||||||
|
mode: 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decimals: 0,
|
||||||
|
displayName: '${__field.labels.integration}',
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byValue',
|
||||||
|
options: {
|
||||||
|
op: 'gte',
|
||||||
|
reducer: 'allIsZero',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.hideFrom',
|
||||||
|
value: {
|
||||||
|
legend: true,
|
||||||
|
tooltip: true,
|
||||||
|
viz: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
legend: {
|
||||||
|
displayMode: 'list',
|
||||||
|
placement: 'bottom',
|
||||||
|
showLegend: true,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
mode: 'multi',
|
||||||
|
sort: 'desc',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getNewAlertGroupsForSelectedPeriodScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
disableTextWrap: false,
|
||||||
|
editorMode: 'code',
|
||||||
|
excludeNullMetadata: false,
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'increase(max_over_time(sum(avg without(pod, instance) ($alert_groups_total{slug=~"$instance", team=~"$team", integration=~"$integration"}))[1d:])[$__range:])',
|
||||||
|
format: 'time_series',
|
||||||
|
fullMetaSearch: false,
|
||||||
|
includeNullMetadata: true,
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
useBackend: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'New alert groups for selected period',
|
||||||
|
pluginId: 'stat',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
decimals: 0,
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'text',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 'none',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Value',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'displayName',
|
||||||
|
value: 'New alert groups',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
colorMode: 'value',
|
||||||
|
graphMode: 'none',
|
||||||
|
justifyMode: 'center',
|
||||||
|
orientation: 'auto',
|
||||||
|
reduceOptions: {
|
||||||
|
calcs: ['lastNotNull'],
|
||||||
|
fields: '',
|
||||||
|
values: false,
|
||||||
|
},
|
||||||
|
textMode: 'auto',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getNewAlertGroupsNotificationsDuringTimePeriodScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
disableTextWrap: false,
|
||||||
|
editorMode: 'code',
|
||||||
|
excludeNullMetadata: false,
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'increase(max_over_time(sum by (username) (avg without(pod, instance) ($user_was_notified_of_alert_groups_total{slug=~"$instance"}))[30m:])[1h:])',
|
||||||
|
fullMetaSearch: false,
|
||||||
|
instant: false,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: true,
|
||||||
|
refId: 'A',
|
||||||
|
useBackend: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'New alert groups notifications during time period',
|
||||||
|
pluginId: 'timeseries',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'palette-classic',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
axisCenteredZero: false,
|
||||||
|
axisColorMode: 'text',
|
||||||
|
axisLabel: '',
|
||||||
|
axisPlacement: 'auto',
|
||||||
|
barAlignment: 0,
|
||||||
|
drawStyle: 'line',
|
||||||
|
fillOpacity: 80,
|
||||||
|
gradientMode: 'opacity',
|
||||||
|
hideFrom: {
|
||||||
|
legend: false,
|
||||||
|
tooltip: false,
|
||||||
|
viz: false,
|
||||||
|
},
|
||||||
|
insertNulls: false,
|
||||||
|
lineInterpolation: 'linear',
|
||||||
|
lineStyle: {
|
||||||
|
fill: 'solid',
|
||||||
|
},
|
||||||
|
lineWidth: 1,
|
||||||
|
pointSize: 5,
|
||||||
|
scaleDistribution: {
|
||||||
|
type: 'linear',
|
||||||
|
},
|
||||||
|
showPoints: 'auto',
|
||||||
|
spanNulls: false,
|
||||||
|
stacking: {
|
||||||
|
group: 'A',
|
||||||
|
mode: 'normal',
|
||||||
|
},
|
||||||
|
thresholdsStyle: {
|
||||||
|
mode: 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decimals: 0,
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byValue',
|
||||||
|
options: {
|
||||||
|
op: 'gte',
|
||||||
|
reducer: 'allIsZero',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.hideFrom',
|
||||||
|
value: {
|
||||||
|
legend: true,
|
||||||
|
tooltip: true,
|
||||||
|
viz: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
legend: {
|
||||||
|
displayMode: 'list',
|
||||||
|
placement: 'bottom',
|
||||||
|
showLegend: true,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
mode: 'multi',
|
||||||
|
sort: 'desc',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getNewAlertGroupsNotificationsForPeriodTableScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'sort_desc(increase(max_over_time(sum by (username) (avg without(pod, instance) ($user_was_notified_of_alert_groups_total{slug=~"$instance"}))[1h:])[$__range:]))',
|
||||||
|
format: 'table',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'seriesToRows',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {
|
||||||
|
Time: true,
|
||||||
|
username: false,
|
||||||
|
},
|
||||||
|
indexByName: {},
|
||||||
|
renameByName: {
|
||||||
|
Metric: 'Integration',
|
||||||
|
Value: 'Alert groups',
|
||||||
|
team: 'Team',
|
||||||
|
username: 'Username',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'New alert groups notifications for period',
|
||||||
|
pluginId: 'table',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
align: 'auto',
|
||||||
|
cellOptions: {
|
||||||
|
type: 'gauge',
|
||||||
|
},
|
||||||
|
filterable: false,
|
||||||
|
inspect: false,
|
||||||
|
},
|
||||||
|
decimals: 0,
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 'none',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Username',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.cellOptions',
|
||||||
|
value: {
|
||||||
|
type: 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom.width',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
cellHeight: 'sm',
|
||||||
|
footer: {
|
||||||
|
countRows: false,
|
||||||
|
fields: '',
|
||||||
|
reducer: ['sum'],
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
showHeader: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getNewAlertGroupsNotificationsInTotalScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
editorMode: 'code',
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'sort_desc(max_over_time(sum by(username) (avg without(pod, instance)($user_was_notified_of_alert_groups_total{slug=~"$instance"}))[1d:]))',
|
||||||
|
format: 'table',
|
||||||
|
instant: true,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: false,
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'seriesToRows',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {
|
||||||
|
Time: true,
|
||||||
|
username: false,
|
||||||
|
},
|
||||||
|
indexByName: {},
|
||||||
|
renameByName: {
|
||||||
|
Metric: 'Integration',
|
||||||
|
Value: 'Alert groups',
|
||||||
|
team: 'Team',
|
||||||
|
username: 'Username',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'New alert groups notifications in total',
|
||||||
|
pluginId: 'table',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
align: 'auto',
|
||||||
|
cellOptions: {
|
||||||
|
mode: 'gradient',
|
||||||
|
type: 'gauge',
|
||||||
|
valueDisplayMode: 'color',
|
||||||
|
},
|
||||||
|
filterable: false,
|
||||||
|
inspect: false,
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Username',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'custom.cellOptions',
|
||||||
|
value: {
|
||||||
|
type: 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom.width',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
cellHeight: 'sm',
|
||||||
|
footer: {
|
||||||
|
countRows: false,
|
||||||
|
fields: '',
|
||||||
|
reducer: ['sum'],
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
showHeader: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getTotalAlertGroupsScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
disableTextWrap: false,
|
||||||
|
editorMode: 'code',
|
||||||
|
excludeNullMetadata: false,
|
||||||
|
exemplar: false,
|
||||||
|
expr: 'max_over_time(sum(avg without(pod, instance) ($alert_groups_total{slug=~"$instance", team=~"$team", integration=~"$integration"}))[1d:])',
|
||||||
|
format: 'time_series',
|
||||||
|
fullMetaSearch: false,
|
||||||
|
instant: false,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: true,
|
||||||
|
refId: 'A',
|
||||||
|
useBackend: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: query,
|
||||||
|
body: new VizPanel({
|
||||||
|
pluginId: 'stat',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'text',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
unit: 'none',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'Value',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'displayName',
|
||||||
|
value: 'Total alert groups',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
colorMode: 'value',
|
||||||
|
graphMode: 'none',
|
||||||
|
justifyMode: 'center',
|
||||||
|
orientation: 'auto',
|
||||||
|
reduceOptions: {
|
||||||
|
calcs: ['lastNotNull'],
|
||||||
|
fields: '',
|
||||||
|
values: false,
|
||||||
|
},
|
||||||
|
textMode: 'auto',
|
||||||
|
},
|
||||||
|
pluginVersion: '9.5.2',
|
||||||
|
title: 'Total alert groups',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
import { ThresholdsMode } from '@grafana/data';
|
||||||
|
import { SceneDataTransformer, SceneFlexItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from 'pages/insights/Insights.types';
|
||||||
|
|
||||||
|
export default function getTotalAlertGroupsByStateScene({ datasource }: InsightsConfig) {
|
||||||
|
const query = new SceneQueryRunner({
|
||||||
|
datasource,
|
||||||
|
queries: [
|
||||||
|
{
|
||||||
|
disableTextWrap: false,
|
||||||
|
editorMode: 'code',
|
||||||
|
excludeNullMetadata: false,
|
||||||
|
expr: 'sum by (state) (avg without(pod, instance) ($alert_groups_total{slug=~"$instance", team=~"$team", integration=~"$integration"}))',
|
||||||
|
fullMetaSearch: false,
|
||||||
|
legendFormat: '__auto',
|
||||||
|
range: true,
|
||||||
|
refId: 'A',
|
||||||
|
useBackend: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const transformedData = new SceneDataTransformer({
|
||||||
|
$data: query,
|
||||||
|
transformations: [
|
||||||
|
{
|
||||||
|
id: 'joinByLabels',
|
||||||
|
options: {
|
||||||
|
value: 'state',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'organize',
|
||||||
|
options: {
|
||||||
|
excludeByName: {},
|
||||||
|
indexByName: {
|
||||||
|
acknowledged: 1,
|
||||||
|
firing: 0,
|
||||||
|
resolved: 2,
|
||||||
|
silenced: 3,
|
||||||
|
},
|
||||||
|
renameByName: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return new SceneFlexItem({
|
||||||
|
$data: transformedData,
|
||||||
|
body: new VizPanel({
|
||||||
|
title: 'Total alert groups by state',
|
||||||
|
pluginId: 'bargauge',
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {
|
||||||
|
color: {
|
||||||
|
mode: 'thresholds',
|
||||||
|
},
|
||||||
|
mappings: [],
|
||||||
|
thresholds: {
|
||||||
|
mode: ThresholdsMode.Absolute,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
color: 'green',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'firing',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'color',
|
||||||
|
value: {
|
||||||
|
fixedColor: 'red',
|
||||||
|
mode: 'fixed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'acknowledged',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'color',
|
||||||
|
value: {
|
||||||
|
fixedColor: 'dark-yellow',
|
||||||
|
mode: 'fixed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matcher: {
|
||||||
|
id: 'byName',
|
||||||
|
options: 'silenced',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
id: 'color',
|
||||||
|
value: {
|
||||||
|
mode: 'fixed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
displayMode: 'gradient',
|
||||||
|
minVizHeight: 10,
|
||||||
|
minVizWidth: 0,
|
||||||
|
orientation: 'vertical',
|
||||||
|
reduceOptions: {
|
||||||
|
calcs: ['lastNotNull'],
|
||||||
|
fields: '',
|
||||||
|
values: false,
|
||||||
|
},
|
||||||
|
showUnfilled: true,
|
||||||
|
valueMode: 'color',
|
||||||
|
},
|
||||||
|
pluginVersion: '9.5.2',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
138
grafana-plugin/src/pages/insights/variables.ts
Normal file
138
grafana-plugin/src/pages/insights/variables.ts
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
import { DataSourceVariable, QueryVariable } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { InsightsConfig } from './Insights.types';
|
||||||
|
|
||||||
|
const DEFAULT_VARIABLE_CONFIG: Partial<ConstructorParameters<typeof QueryVariable>[0]> = {
|
||||||
|
hide: 0,
|
||||||
|
includeAll: true,
|
||||||
|
isMulti: true,
|
||||||
|
options: [],
|
||||||
|
refresh: 1,
|
||||||
|
regex: '',
|
||||||
|
skipUrlSync: false,
|
||||||
|
sort: 0,
|
||||||
|
type: 'query',
|
||||||
|
};
|
||||||
|
|
||||||
|
const getVariables = ({ isOpenSource, datasource }: InsightsConfig) => [
|
||||||
|
// Selectable
|
||||||
|
...(isOpenSource
|
||||||
|
? [
|
||||||
|
new DataSourceVariable({
|
||||||
|
name: 'datasource',
|
||||||
|
label: 'Data source',
|
||||||
|
pluginId: 'prometheus',
|
||||||
|
value: 'grafanacloud-usage',
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'instance',
|
||||||
|
label: 'Instance',
|
||||||
|
text: ['All'],
|
||||||
|
value: ['$__all'],
|
||||||
|
datasource,
|
||||||
|
definition: 'label_values(${alert_groups_total},slug)',
|
||||||
|
query: {
|
||||||
|
query: 'label_values(${alert_groups_total},slug)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'team',
|
||||||
|
label: 'Team',
|
||||||
|
text: ['All'],
|
||||||
|
value: ['$__all'],
|
||||||
|
datasource,
|
||||||
|
definition: 'label_values(${alert_groups_total}{slug=~"$instance"},team)',
|
||||||
|
query: {
|
||||||
|
query: 'label_values(${alert_groups_total}{slug=~"$instance"},team)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
refresh: 2,
|
||||||
|
}),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'integration',
|
||||||
|
label: 'Integration',
|
||||||
|
text: ['All'],
|
||||||
|
value: ['$__all'],
|
||||||
|
datasource,
|
||||||
|
definition: 'label_values(${alert_groups_total}{team=~"$team",slug=~"$instance"},integration)',
|
||||||
|
query: {
|
||||||
|
query: 'label_values(${alert_groups_total}{team=~"$team",slug=~"$instance"},integration)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
refresh: 2,
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Non-selectable
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'alert_groups_total',
|
||||||
|
label: 'alert_groups_total',
|
||||||
|
datasource,
|
||||||
|
query: {
|
||||||
|
query: 'metrics(alert_groups_total)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
text: ['oncall_alert_groups_total', 'grafanacloud_oncall_instance_alert_groups_total'],
|
||||||
|
value: ['oncall_alert_groups_total', 'grafanacloud_oncall_instance_alert_groups_total'],
|
||||||
|
definition: 'metrics(alert_groups_total)',
|
||||||
|
hide: 2,
|
||||||
|
includeAll: false,
|
||||||
|
}),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'user_was_notified_of_alert_groups_total',
|
||||||
|
label: 'user_was_notified_of_alert_groups_total',
|
||||||
|
datasource,
|
||||||
|
definition: 'metrics(user_was_notified_of_alert_groups_total)',
|
||||||
|
query: {
|
||||||
|
query: 'metrics(user_was_notified_of_alert_groups_total)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
hide: 2,
|
||||||
|
refresh: 2,
|
||||||
|
}),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'alert_groups_response_time_seconds_bucket',
|
||||||
|
label: 'alert_groups_response_time_seconds_bucket',
|
||||||
|
datasource,
|
||||||
|
definition: 'metrics(alert_groups_response_time_seconds_bucket)',
|
||||||
|
query: {
|
||||||
|
query: 'metrics(alert_groups_response_time_seconds_bucket)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
hide: 2,
|
||||||
|
}),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'alert_groups_response_time_seconds_sum',
|
||||||
|
label: 'alert_groups_response_time_seconds_sum',
|
||||||
|
datasource,
|
||||||
|
definition: 'metrics(alert_groups_response_time_seconds_sum)',
|
||||||
|
query: {
|
||||||
|
query: 'metrics(alert_groups_response_time_seconds_sum)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
hide: 2,
|
||||||
|
}),
|
||||||
|
new QueryVariable({
|
||||||
|
...DEFAULT_VARIABLE_CONFIG,
|
||||||
|
name: 'alert_groups_response_time_seconds_count',
|
||||||
|
label: 'alert_groups_response_time_seconds_count',
|
||||||
|
datasource,
|
||||||
|
definition: 'metrics(alert_groups_response_time_seconds_count)',
|
||||||
|
query: {
|
||||||
|
query: 'metrics(alert_groups_response_time_seconds_count)',
|
||||||
|
refId: 'PrometheusVariableQueryEditor-VariableQuery',
|
||||||
|
},
|
||||||
|
hide: 2,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
export default getVariables;
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import EscalationsChainsPage from 'pages/escalation-chains/EscalationChains';
|
import EscalationsChainsPage from 'pages/escalation-chains/EscalationChains';
|
||||||
import IncidentPage from 'pages/incident/Incident';
|
import IncidentPage from 'pages/incident/Incident';
|
||||||
import IncidentsPage from 'pages/incidents/Incidents';
|
import IncidentsPage from 'pages/incidents/Incidents';
|
||||||
|
import Insights from 'pages/insights/Insights';
|
||||||
import OutgoingWebhooks from 'pages/outgoing_webhooks/OutgoingWebhooks';
|
import OutgoingWebhooks from 'pages/outgoing_webhooks/OutgoingWebhooks';
|
||||||
import SchedulePage from 'pages/schedule/Schedule';
|
import SchedulePage from 'pages/schedule/Schedule';
|
||||||
import SchedulesPage from 'pages/schedules/Schedules';
|
import SchedulesPage from 'pages/schedules/Schedules';
|
||||||
|
|
@ -66,6 +67,10 @@ export const routes: { [id: string]: NavRoute } = [
|
||||||
component: CloudPage,
|
component: CloudPage,
|
||||||
id: 'cloud',
|
id: 'cloud',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: Insights,
|
||||||
|
id: 'insights',
|
||||||
|
},
|
||||||
].reduce((prev, current) => {
|
].reduce((prev, current) => {
|
||||||
prev[current.id] = {
|
prev[current.id] = {
|
||||||
id: current.id,
|
id: current.id,
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class ChatOpsPage extends React.Component<ChatOpsProps, ChatOpsState> {
|
||||||
const { activeTab } = this.state;
|
const { activeTab } = this.state;
|
||||||
const { store } = this.props;
|
const { store } = this.props;
|
||||||
|
|
||||||
if (!this.isChatOpsConfigured() && store.isOpenSource()) {
|
if (!this.isChatOpsConfigured() && store.isOpenSource) {
|
||||||
return this.renderNoChatOpsBannerInfo();
|
return this.renderNoChatOpsBannerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,14 @@
|
||||||
"action": "grafana-oncall-app.other-settings:read",
|
"action": "grafana-oncall-app.other-settings:read",
|
||||||
"addToNav": true
|
"addToNav": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "page",
|
||||||
|
"name": "Insights",
|
||||||
|
"path": "/a/grafana-oncall-app/insights",
|
||||||
|
"role": "Viewer",
|
||||||
|
"action": "grafana-oncall-app.other-settings:read",
|
||||||
|
"addToNav": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "dashboard",
|
"type": "dashboard",
|
||||||
"path": "dashboards/oncall_metrics_dashboard.json",
|
"path": "dashboards/oncall_metrics_dashboard.json",
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import NoMatch from 'pages/NoMatch';
|
||||||
import EscalationChains from 'pages/escalation-chains/EscalationChains';
|
import EscalationChains from 'pages/escalation-chains/EscalationChains';
|
||||||
import Incident from 'pages/incident/Incident';
|
import Incident from 'pages/incident/Incident';
|
||||||
import Incidents from 'pages/incidents/Incidents';
|
import Incidents from 'pages/incidents/Incidents';
|
||||||
|
import Insights from 'pages/insights/Insights';
|
||||||
import Integration from 'pages/integration/Integration';
|
import Integration from 'pages/integration/Integration';
|
||||||
import Integrations from 'pages/integrations/Integrations';
|
import Integrations from 'pages/integrations/Integrations';
|
||||||
import OutgoingWebhooks from 'pages/outgoing_webhooks/OutgoingWebhooks';
|
import OutgoingWebhooks from 'pages/outgoing_webhooks/OutgoingWebhooks';
|
||||||
|
|
@ -181,6 +182,9 @@ export const Root = observer((props: AppRootProps) => {
|
||||||
<Route path={getRoutesForPage('cloud')} exact>
|
<Route path={getRoutesForPage('cloud')} exact>
|
||||||
<CloudPage />
|
<CloudPage />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path={getRoutesForPage('insights')} exact>
|
||||||
|
<Insights />
|
||||||
|
</Route>
|
||||||
|
|
||||||
{/* Backwards compatibility redirect routes */}
|
{/* Backwards compatibility redirect routes */}
|
||||||
<Route
|
<Route
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { locationService } from '@grafana/runtime';
|
import { locationService } from '@grafana/runtime';
|
||||||
import { contextSrv } from 'grafana/app/core/core';
|
import { contextSrv } from 'grafana/app/core/core';
|
||||||
import { action, makeObservable, observable, runInAction } from 'mobx';
|
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
|
||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
import { OnCallAppPluginMeta } from 'types';
|
import { OnCallAppPluginMeta } from 'types';
|
||||||
|
|
@ -188,7 +188,7 @@ export class RootBaseStore {
|
||||||
return this.setupPluginError('🚫 Plugin has not been initialized');
|
return this.setupPluginError('🚫 Plugin has not been initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isOpenSource() && !meta.secureJsonFields?.onCallApiToken) {
|
if (this.isOpenSource && !meta.secureJsonFields?.onCallApiToken) {
|
||||||
// Reinstall plugin if onCallApiToken is missing
|
// Reinstall plugin if onCallApiToken is missing
|
||||||
const errorMsg = await PluginState.selfHostedInstallPlugin(this.onCallApiUrl, true);
|
const errorMsg = await PluginState.selfHostedInstallPlugin(this.onCallApiUrl, true);
|
||||||
if (errorMsg) {
|
if (errorMsg) {
|
||||||
|
|
@ -296,7 +296,8 @@ export class RootBaseStore {
|
||||||
return GRAFANA_LICENSE_OSS;
|
return GRAFANA_LICENSE_OSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
isOpenSource(): boolean {
|
@computed
|
||||||
|
get isOpenSource(): boolean {
|
||||||
return this.license === GRAFANA_LICENSE_OSS;
|
return this.license === GRAFANA_LICENSE_OSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1863,6 +1863,15 @@
|
||||||
uplot "1.6.22"
|
uplot "1.6.22"
|
||||||
xss "1.0.13"
|
xss "1.0.13"
|
||||||
|
|
||||||
|
"@grafana/e2e-selectors@10.0.2":
|
||||||
|
version "10.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@grafana/e2e-selectors/-/e2e-selectors-10.0.2.tgz#98cd7fa01ca21b416db8827980508195554fb5a4"
|
||||||
|
integrity sha512-3dc+2hL/AJLkOMXiN2UmWU3kOHO4Eqv10AJVOTkpDwecQvWoSS5vtflyPCEWshDqDSE/6k2gB9N2rlZk9O/R5g==
|
||||||
|
dependencies:
|
||||||
|
"@grafana/tsconfig" "^1.2.0-rc1"
|
||||||
|
tslib "2.5.0"
|
||||||
|
typescript "4.8.4"
|
||||||
|
|
||||||
"@grafana/e2e-selectors@10.1.4":
|
"@grafana/e2e-selectors@10.1.4":
|
||||||
version "10.1.4"
|
version "10.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@grafana/e2e-selectors/-/e2e-selectors-10.1.4.tgz#150eab282458da06bc0fb44ce46602e47b14ebed"
|
resolved "https://registry.yarnpkg.com/@grafana/e2e-selectors/-/e2e-selectors-10.1.4.tgz#150eab282458da06bc0fb44ce46602e47b14ebed"
|
||||||
|
|
@ -2055,6 +2064,17 @@
|
||||||
systemjs "0.20.19"
|
systemjs "0.20.19"
|
||||||
tslib "2.4.1"
|
tslib "2.4.1"
|
||||||
|
|
||||||
|
"@grafana/scenes@^1.28.0":
|
||||||
|
version "1.28.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@grafana/scenes/-/scenes-1.28.0.tgz#e5cf42fffd2f6f1ec37c338b884d93f0041e72bd"
|
||||||
|
integrity sha512-AWuR7+47hoB/yrqwNzOf9uaZrND3LJdYxPMEfbpvvfKTS1o3WGAq3JXG5xS25i0Bj/dfZCfMysHQXbTa0oBLVQ==
|
||||||
|
dependencies:
|
||||||
|
"@grafana/e2e-selectors" "10.0.2"
|
||||||
|
react-grid-layout "1.3.4"
|
||||||
|
react-use "17.4.0"
|
||||||
|
react-virtualized-auto-sizer "1.0.7"
|
||||||
|
uuid "^9.0.0"
|
||||||
|
|
||||||
"@grafana/schema@10.1.4":
|
"@grafana/schema@10.1.4":
|
||||||
version "10.1.4"
|
version "10.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@grafana/schema/-/schema-10.1.4.tgz#b6bb598de15fbdd73be62cd4b06e11c49b497c7c"
|
resolved "https://registry.yarnpkg.com/@grafana/schema/-/schema-10.1.4.tgz#b6bb598de15fbdd73be62cd4b06e11c49b497c7c"
|
||||||
|
|
@ -2090,6 +2110,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib "2.5.0"
|
tslib "2.5.0"
|
||||||
|
|
||||||
|
"@grafana/schema@^10.2.2":
|
||||||
|
version "10.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@grafana/schema/-/schema-10.2.2.tgz#7bcb44ffccd72c2a30f99c85bcc188dd4bddfd19"
|
||||||
|
integrity sha512-VDMO2Ev/mSsQxOkwo2u3uQocoyfxJGaGTfAMRGgeejmYJVQsK3Ka6/ImGmqvCViE5uade5/rx7kKfLnj6Yc0Yg==
|
||||||
|
dependencies:
|
||||||
|
tslib "2.6.0"
|
||||||
|
|
||||||
"@grafana/toolkit@^9.5.2":
|
"@grafana/toolkit@^9.5.2":
|
||||||
version "9.5.2"
|
version "9.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@grafana/toolkit/-/toolkit-9.5.2.tgz#39f58b32050bbc7ca6860e1ebfe7378f68a0abca"
|
resolved "https://registry.yarnpkg.com/@grafana/toolkit/-/toolkit-9.5.2.tgz#39f58b32050bbc7ca6860e1ebfe7378f68a0abca"
|
||||||
|
|
@ -10663,7 +10690,7 @@ lodash.get@^4.4.2:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||||
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
|
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
|
||||||
|
|
||||||
lodash.isequal@^4.5.0:
|
lodash.isequal@^4.0.0, lodash.isequal@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||||
|
|
@ -13351,6 +13378,14 @@ react-dom@18.2.0, react-dom@^18.0.0:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
scheduler "^0.23.0"
|
scheduler "^0.23.0"
|
||||||
|
|
||||||
|
react-draggable@^4.0.0, react-draggable@^4.0.3:
|
||||||
|
version "4.4.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.6.tgz#63343ee945770881ca1256a5b6fa5c9f5983fe1e"
|
||||||
|
integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==
|
||||||
|
dependencies:
|
||||||
|
clsx "^1.1.1"
|
||||||
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
react-draggable@^4.4.5:
|
react-draggable@^4.4.5:
|
||||||
version "4.4.5"
|
version "4.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.5.tgz#9e37fe7ce1a4cf843030f521a0a4cc41886d7e7c"
|
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.5.tgz#9e37fe7ce1a4cf843030f521a0a4cc41886d7e7c"
|
||||||
|
|
@ -13394,6 +13429,17 @@ react-from-dom@^0.6.2:
|
||||||
resolved "https://registry.yarnpkg.com/react-from-dom/-/react-from-dom-0.6.2.tgz#9da903a508c91c013b55afcd59348b8b0a39bdb4"
|
resolved "https://registry.yarnpkg.com/react-from-dom/-/react-from-dom-0.6.2.tgz#9da903a508c91c013b55afcd59348b8b0a39bdb4"
|
||||||
integrity sha512-qvWWTL/4xw4k/Dywd41RBpLQUSq97csuv15qrxN+izNeLYlD9wn5W8LspbfYe5CWbaSdkZ72BsaYBPQf2x4VbQ==
|
integrity sha512-qvWWTL/4xw4k/Dywd41RBpLQUSq97csuv15qrxN+izNeLYlD9wn5W8LspbfYe5CWbaSdkZ72BsaYBPQf2x4VbQ==
|
||||||
|
|
||||||
|
react-grid-layout@1.3.4:
|
||||||
|
version "1.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-1.3.4.tgz#4fa819be24a1ba9268aa11b82d63afc4762a32ff"
|
||||||
|
integrity sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==
|
||||||
|
dependencies:
|
||||||
|
clsx "^1.1.1"
|
||||||
|
lodash.isequal "^4.0.0"
|
||||||
|
prop-types "^15.8.1"
|
||||||
|
react-draggable "^4.0.0"
|
||||||
|
react-resizable "^3.0.4"
|
||||||
|
|
||||||
react-highlight-words@0.18.0:
|
react-highlight-words@0.18.0:
|
||||||
version "0.18.0"
|
version "0.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-highlight-words/-/react-highlight-words-0.18.0.tgz#ff3b3ef7cb497fa2e8fa4d54c1a1a98ac6390d0e"
|
resolved "https://registry.yarnpkg.com/react-highlight-words/-/react-highlight-words-0.18.0.tgz#ff3b3ef7cb497fa2e8fa4d54c1a1a98ac6390d0e"
|
||||||
|
|
@ -13512,6 +13558,14 @@ react-redux@^7.2.0:
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
react-is "^17.0.2"
|
react-is "^17.0.2"
|
||||||
|
|
||||||
|
react-resizable@^3.0.4:
|
||||||
|
version "3.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.5.tgz#362721f2efbd094976f1780ae13f1ad7739786c1"
|
||||||
|
integrity sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==
|
||||||
|
dependencies:
|
||||||
|
prop-types "15.x"
|
||||||
|
react-draggable "^4.0.3"
|
||||||
|
|
||||||
react-responsive@^8.1.0:
|
react-responsive@^8.1.0:
|
||||||
version "8.2.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-8.2.0.tgz#e0ffb306cfd8f38c9c12e26725b9e1245fa9debc"
|
resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-8.2.0.tgz#e0ffb306cfd8f38c9c12e26725b9e1245fa9debc"
|
||||||
|
|
@ -13704,6 +13758,11 @@ react-use@17.4.0:
|
||||||
ts-easing "^0.2.0"
|
ts-easing "^0.2.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
react-virtualized-auto-sizer@1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.7.tgz#bfb8414698ad1597912473de3e2e5f82180c1195"
|
||||||
|
integrity sha512-Mxi6lwOmjwIjC1X4gABXMJcKHsOo0xWl3E3ugOgufB8GJU+MqrtY35aBuvCYv/razQ1Vbp7h1gWJjGjoNN5pmA==
|
||||||
|
|
||||||
react-window@1.8.8:
|
react-window@1.8.8:
|
||||||
version "1.8.8"
|
version "1.8.8"
|
||||||
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.8.tgz#1b52919f009ddf91970cbdb2050a6c7be44df243"
|
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.8.tgz#1b52919f009ddf91970cbdb2050a6c7be44df243"
|
||||||
|
|
@ -15723,6 +15782,11 @@ uuid@^8.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
|
uuid@^9.0.0:
|
||||||
|
version "9.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||||
|
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||||
|
|
||||||
v8-compile-cache-lib@^3.0.1:
|
v8-compile-cache-lib@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||||
|
|
|
||||||
|
|
@ -33,3 +33,7 @@ dependencies:
|
||||||
version: 4.1.4
|
version: 4.1.4
|
||||||
repository: https://kubernetes.github.io/ingress-nginx
|
repository: https://kubernetes.github.io/ingress-nginx
|
||||||
condition: ingress-nginx.enabled
|
condition: ingress-nginx.enabled
|
||||||
|
- name: prometheus
|
||||||
|
version: 25.8.2
|
||||||
|
repository: https://prometheus-community.github.io/helm-charts
|
||||||
|
condition: prometheus.enabled
|
||||||
|
|
|
||||||
BIN
helm/oncall/charts/prometheus-25.8.2.tgz
Normal file
BIN
helm/oncall/charts/prometheus-25.8.2.tgz
Normal file
Binary file not shown.
|
|
@ -708,3 +708,12 @@ ui:
|
||||||
tag: dev
|
tag: dev
|
||||||
# Additional env vars for the ui container
|
# Additional env vars for the ui container
|
||||||
env: {}
|
env: {}
|
||||||
|
|
||||||
|
prometheus:
|
||||||
|
enabled: false
|
||||||
|
# extraScrapeConfigs: |
|
||||||
|
# - job_name: 'oncall-exporter'
|
||||||
|
# metrics_path: /metrics/
|
||||||
|
# static_configs:
|
||||||
|
# - targets:
|
||||||
|
# - oncall-dev-engine.default.svc.cluster.local:8080
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue