Merge pull request #4898 from grafana/dev

1.9.10
This commit is contained in:
Innokentii Konstantinov 2024-08-22 16:33:52 +08:00 committed by GitHub
commit ca5a5f554c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 441 additions and 124 deletions

View file

@ -0,0 +1,339 @@
---
title: Slack integration for Grafana IRM
menuTitle: IRM Slack
description: Learn more about Slack integration for Grafana IRM.
weight: 0
keywords:
- OnCall
- IRM
- Notifications
- ChatOps
- Slack
- Integration
- Channels
canonical: https://grafana.com/docs/oncall/latest/configure/integrations/references/slack/
aliases:
- /docs/grafana-cloud/alerting-and-irm/oncall/configure/integrations/references/slack/
- ../../references/slack/ # /docs/oncall/<ONCALL_VERSION>/configure/integrations/references/slack
---
# Slack integration for Grafana IRM
The Grafana IRM Slack integration incorporates your incident response workflow directly into your Slack workspace,
helping your team focus on alert resolution with less friction.
{{< admonition type="note" >}}
The OnCall Slack app has been rebranded as the Grafana IRM Slack app, which now has incident management features.
The legacy Incident Slack integration is being deprecated.
If you have an existing installation of the legacy Slack integrations, refer to the [migration instructions](#migrate-to-the-grafana-irm-slack-integration)
for more information on how to migrate to the Grafana IRM Slack integration.
{{< /admonition >}}
## Key features and benefits
Integrating your Slack workspace allows users and teams to be notified of alerts directly in Slack with automated alert escalation steps and user notification preferences.
Users can take a number of alert actions directly from Slack, including acknowledging and resolving alert groups, adding resolution notes, and more.
Refer to the following sections to learn more:
- [Configure Escalation Chains with Slack notifications](#configure-escalation-chains-with-slack-notifications)
- [Configure user notifications policies with Slack mentions](#configure-user-notifications-policies-with-slack-mentions)
- [Configure on-call notifications in Slack](#configure-on-call-notifications-in-slack)
When it comes to incidents, users can declare, collaborate on, and manage incident-worthy events without leaving Slack.
They can also automatically create incident-specific channels, track the timeline of events, interact with incidents via Slash commands, and more.
Refer to the following sections to learn more:
- [Create incident Slack channels](#configure-incident-slack-channels)
- [Configure incident announcements](#configure-incident-announcements)
- [Interact with incidents from Slack via Slash commands](#incident-related-commands)
## Before you begin
To install the Grafana IRM Slack app:
- You must have an Admin role in Grafana IRM
- You must be a Slack workspace admin or owner
- Allow Grafana IRM to access your Slack workspace
Once your IRM account has been added to your Slack workspace, Admins and Editors can configure escalation chains and other notifications to route to designated
Slack channels.
In order to use the Slack slash command `/grafana`, you must be an IRM user with a linked Slack account.
To learn more, refer to [Connect your Slack user to Grafana IRM](#connect-your-slack-user-to-grafana-irm).
## Install Slack integration for Grafana IRM
Currently, the Grafana IRM Slack integration can be installed from Grafana OnCall or Grafana Incident.
Installing the integration in either location will automatically install it for the other.
{{< admonition type="note" >}}
If you already have the OnCall or Incident Slack integration installed, use the instructions in [Migrate to the IRM Slack integration](#migrate-to-the-grafana-irm-slack-integration).
{{< /admonition >}}
Follow these steps to install the Slack integration from Grafana OnCall:
1. Navigate to the **Settings** tab in Grafana OnCall.
1. From the **ChatOps** tab, select **Slack** in the side menu.
1. Click **Install integration**.
1. Once redirected to the Slack connection page, verify the Slack workspace is correct or **Add another workspace**.
1. If needed, provide your Slack workspace URL and sign with your Slack credentials.
1. Follow the Slack prompts to review permissions and specify a default channel.
1. Click **Allow** to give Grafana IRM permission to access your Slack workspace.
Follow these steps to install the Slack integration from Grafana Incident:
1. Navigate to the **Integrations** tab in Grafana Incident.
1. Click the **Slack IRM** tile and then click **Install Integration**.
1. Once redirected to the Slack connection page, verify the Slack workspace is correct or **Add another workspace**.
1. If needed, provide your Slack workspace URL and sign with your Slack credentials.
1. Follow the Slack prompts to review permissions and specify a default channel.
1. Click **Allow** to give Grafana IRM permission to access your Slack workspace.
For more information about the required permissions, refer to the [Permissions](#permissions-scope-and-purpose) section.
## Migrate to the Grafana IRM Slack integration
The Grafana IRM Slack integration combines the features of both OnCall and Incident into a single app.
The OnCall Slack app has been rebranded as the Grafana IRM Slack app and now includes incident management capabilities.
This integration is IRM-wide, meaning that once the Grafana IRM Slack integration is installed or re-installed in OnCall,
it will automatically be available for use in Incident, and vice versa.
The same applies to the uninstall process—uninstalling the IRM app from OnCall will also remove it from Incident.
There are two ways to upgrade to the new integration, depending on your current installation.
### Migrate from the OnCall Slack app to the IRM Slack app
To upgrade from the OnCall Slack integration to the Grafana IRM Slack integration,
you only need to approve the additional permissions required for Incident management functionality.
Migrating to the IRM Slack app will not affect your existing OnCall Slack-related configuration, including channels, users, and schedules.
{{< admonition type="note" >}}
The `/escalate` command is deprecated, please use `/grafana escalate` instead. Refer to [Available Slack commands](#available-slack-commands) for more information.
{{< /admonition >}}
From OnCall, follow these steps to upgrade:
1. Navigate to the **Settings** tab in Grafana OnCall.
2. From the **ChatOps** tab, select **Slack** in the side menu.
3. Click **Migrate**
4. Once redirected to the Slack connection page, verify the Slack workspace and follow the Slack prompts to review permissions and specify a default channel.
5. Click **Allow** to reauthorize Grafana IRM to access your Slack workspace with additional permissions.
Migrating to the Grafana IRM Slack integration requires the following additional permissions:
- `Bookmarks:read`
- `Bookmarks:write`
- `Channels:manage`
- `Groups:write`
- `Pins:read`
- `Reactions:read`
- `Incoming-webhook`
Refer to the [Permissions](#permissions-scope-and-purpose) section for detailed information.
### Migrate from the Incident Slack app to the IRM Slack app
The Grafana Incident Slack integration is now considered legacy,
and you will need to migrate to the new Grafana IRM Slack integration by installing the updated Grafana IRM Slack app.
During this migration, your existing Incident Slack settings, including incident announcements and automatic channel creation, will be preserved.
The new Grafana IRM Slack app will be installed, along with the `/grafana incident` command.
You will still be able to manage incidents that were started before the migration using the legacy app and the `/incident` command.
From Incident, follow these steps to migrate:
1. Navigate to the **Integrations** tab in Grafana OnCall.
2. Click the **Slack IRM** tile and then click **Install Integration**.
3. Once redirected to the Slack connection page, verify the Slack workspace and follow the Slack prompts to review permissions and specify a default channel.
4. Click **Allow** to authorize Grafana IRM to access your Slack workspace.
Refer to the [Permissions](#permissions-scope-and-purpose) section for more information.
## Connect your Slack user to Grafana IRM
For users to gain full access to Grafana IRM functionality in Slack, follow these steps to map your Grafana IRM user account to your Slack user account:
1. In Grafana OnCall, navigate to the **Users** tab and click **View my profile**.
1. Under the **User Info** tab, find the Slack username section and click **Connect**.
1. Follow the prompts to verify and link your Slack account.
## Configure channels and notifications
Grafana IRM provides flexible configuration options to tailor Slack notifications to your team's needs.
This section outlines how to set up escalation chains, user notifications, on-call notifications, and incident channels within Slack.
### Configure Escalation Chains with Slack notifications
After setting up your Slack integration, you can configure escalation chains to send notifications via Slack for alerts in Grafana OnCall.
There are two Slack notification methods that can be integrated into escalation chains:
- Notify all members of a Slack channel
- Notify a specific Slack user group
To configure these in your escalation chains:
1. In Grafana OnCall, navigate to the **Escalation Chains** tab.
1. Select an existing escalation chain or create a new one by clicking **+ New escalation chain**.
1. Use the dropdown under **Add escalation step** to choose and configure your Slack notification preferences.
### Configure user notifications policies with Slack mentions
You can receive alert notifications directly via Slack mentions, ensuring that critical alerts reach you immediately:
1. From the **Users** tab in Grafana OnCall and click **Edit** next to the user you want to configure.
1. In the **User Info** tab, click **+ Add Notification step**.
1. Choose **Notify by** in the first dropdown, then select **Slack mentions** in the second dropdown to receive notifications through Slack mentions.
### Configure on-call notifications in Slack
The IRM Slack integration also supports automated notifications for on-call shifts, helping teams stay informed of their duties.
Admins can set up these notifications in the Notification Preferences section:
1. When an on-call shift notification is sent to a person or channel, click the **gear icon** to open **Notifications preferences**.
1. Configure the notification behavior for future shifts according to your team's preferences.
### Configure Incident Slack channels
Grafana IRM allows you to customize the names of incident-specific Slack channels by setting prefixes, making it easier to organize and search for incident channels.
To customize Slack channel prefixes:
1. Click **Incident** in the left-side menu.
1. Go to **Settings**.
1. Scroll down to the **Prefixes** section in the Settings page.
1. Click **+ Add Prefix** and provide a name and description.
1. Edit any existing prefixes as needed, then click **Update**.
1. Once your prefixes are defined, you can choose which prefix to use when declaring an incident in Grafana Incident.
### Configure Incident announcements
Incident announcements help keep your team aware and informed during critical events.
Configure these announcements to ensure that stakeholders are kept up-to-date in Slack during an incident.
To configure Incident announcements:
1. Navigate to **Incident** in the left-side menu, then click **Integrations**.
1. Click **Slack IRM** to open the Slack IRM integration page.
1. Select the Slack channel where you want to send notifications.
You can either choose from the dropdown menu or manually add your Channel ID. The Channel ID can be found in the Slack channels **About** tab.
1. Define the incident-specific fields:
- **Incident type**: Choose whether the incident is internal or private.
- **Include incidents**: Specify which types of incidents to announce—options include all incidents, drills, or non-drills.
1. Apply filters to your incident announcements to tailor the notifications to specific channels:
- **Incident filter**: For example, you might filter by label, such as `label: 'squad:datasources'`.
### Manage Slack attachments
When you use the 🤖 emoji reaction on a Slack message containing a file, the file is securely copied to Grafana Cloud storage.
This ensures your incident timeline remains intact, even if the file is later deleted from Slack. Heres how it works:
- **File retention**: Control attachment retention in your incident timeline. Removing the 🤖 reaction will delete the attached files from Grafana Cloud storage.
- **Incident web app**: Deleting an item from the timeline within the Incident web app also removes the associated file from Grafana Cloud storage.
- **File size limit**: Files in Grafana Incident are limited to 100MB. Files too large to persist will still be accessible via a link to the source file in Slack.
## Available Slack commands
{{< admonition type="note" >}}
The `/escalate` and `/incident` Slack commands have been deprecated. Use `/grafana` to learn more.
{{< / admonition >}}
The `/grafana` Slack commands allow users and teams to respond to alert groups and collaborate on incidents directly from Slack.
{{< admonition type="tip" >}}
Use the 🤖 robot emoji Slack reaction to add important messages to the incident timeline.
{{< /admonition >}}
| Command | Description |
|----------------------|--------------------------------------|
| `/grafana` | List of all `/grafana` commands |
| `/grafana stacks` | List all available stacks |
| `/grafana set-stack` | Set your default stack |
| `/grafana escalate` | Page a user or a team |
| `/grafana incident` | Prefix for Incident-related commands |
### Incident-related commands
| Command | Description |
|--------------------------------------------------------|---------------------------------------|
| `/grafana incident new` | Create new incident |
| `/grafana incident new “title”` | Create new incident with severity |
| `/grafana incident list` | List all active incidents |
| `/grafana incident roles` | Find out whos involved |
| `/grafana incident talk` | Set up a collaboration space |
| `/grafana incident status` | Get a live inline update |
| `/grafana incident severity` | Set the incident severity |
| `/grafana incident severity major` | Update the incident severity to major |
| `/grafana incident tasks` | Create, assign and manage tasks |
| `/grafana incident tasks help` | More information about tasks |
| `/grafana incident task add 'deploy new release'` | Add a new task |
| `/grafana incident task add 'deploy new release' @bob` | Add a new task and assign to @bob |
| `/grafana incident tasks list` | View current tasks |
| `/grafana incident notes` | Add and view incident notes |
| `/grafana incident notes help` | More information about notes |
| `/grafana incident note add "customers notified"` | Add a new note |
| `/grafana incident notes list` | View current notes |
## Permissions scope and purpose
The Grafana IRM Slack app only requests permissions that are essential to its proper function and integration with Slack.
Refer to the [Slack documentation](https://api.slack.com/scopes) for more information on permission scopes.
By granting access to the app, you are authorizing Grafana IRM the following permissions in your Slack workspace:
### Workspace and user access
| Permission | Description | Purpose |
|--------------------|----------------------------------------------------------------|------------------------------------------------------------------------------------------------|
| team:read | View the workspace name, email domain, and icon | Used for identification and to establish an association with your workspace |
| users:read | View people in a workspace | Used to find users by email and facilitate account matching between Grafana and your workspace |
| users.profile:read | View profile details about people in a workspace | This permission enables us to fetch profile data, such as Slack handles and avatars |
| users:write | Set presence for Grafana IRM Slack app | Allows @GrafanaIRM to be added to your workspace |
| usergroups:read | View user groups in a workspace | Required to connect on-call schedules and escalation chains to Slack user groups |
| usergroups:write | Create and manage user groups | Required to connect on-call schedule and escalation chains to Slack user groups |
| incoming-webhook | Create one-way webhooks to post messages to a specific channel | Used to display a channel picker in the installation sequence |
### Public channel access
| Permission | Description | Purpose |
|------------------|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| channels:read | View basic information about public channels | Used when adding a new channel to an escalation chain and to locate and update incident-specific channels |
| channels:manage | Manage public channels that Grafana IRM has been added to and create new ones | Allows the app to create new channels and invite users to these channels |
| channels:join | Join public channels in a workspace | Allows @GrafanaIRM to join channels |
| channels:history | View messages and other content in public channels that Grafana IRM has been added to | Allows @GrafanaIRM to list messages in channels where the app has access to be included in the resolution notes |
| bookmarks:read | List bookmarks | Used to access bookmarks, such as PIR documents and Google Meet links, related to incidents |
| bookmarks:write | Create, edit, and remove bookmarks | Necessary for managing incident-related bookmarks, including PIR documents and Google Meet links |
| files:read | View files shared in channels and conversations that Grafana IRM is a part of | For incident-related file sharing and collaboration within authorized channels |
| files:write | Upload, edit, and delete files as Grafana IRM | Used to upload image attachments so they appear in the Incident timeline |
| pins:read | View pinned content in channels and conversations that Grafana Incident has been added to | Used to access and display pinned content related to incidents |
### Private channel access
| Permission | Description | Purpose |
|------------------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|
| groups:read | View basic information about private channels that Grafana IRM has been added to | Used to access information from private incident-specific channels |
| groups:write | Manage private channels that Grafana IRM has been added to and create new ones | Required to create private incident-specific channels for private incidents |
| groups:history | List messages from private incident-specific channels | Allows @GrafanaIRM to list messages from private incident channels to be included in the resolution notes |
| usergroups:write | Create and manage user groups | Required for connecting on-call schedules to Slack user groups |
| usergroups:read | View user groups in a workspace | Required for connecting on-call schedules to Slack user groups |
### Message and conversation access
| Permission | Description | Purpose |
|----------------------|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| app_mentions:read | View messages and other content in public channels that Grafana IRM is a part of | Enables the app to read messages and related content within authorized channels |
| chat:write | Post messages in approved channels & conversations | Allows @GrafanaIRM to post messages to Slack |
| chat:write.customize | Send messages as Grafana IRM with a customized username and avatar | Allows @GrafanaIRM to post messages to Slack |
| chat:write.public | Send messages to channels GrafanaI RM isn't a member of | Allows @Grafan IRM to post messages to Slack |
| reaction:read | View emoji reactions and their associated content in channels and conversations that Grafana IRM has been added to | Allows @GrafanaIRM to monitor message events for the 🤖 emoji to be included in the incident timeline |
| reaction:write | Add and edit emoji reactions | Required to include messages with the 📝 emoji on resolution notes |
| im:read | View basic information about direct messages that Grafana IRM has been added to | Enables the app to send alert group notifications to users via direct message |
| im:write | Start direct messages with people | Used to notify users about alerts via direct message as well as invite users who create an incident to the incident channel |
| im:history | View messages and other content in direct messages that Grafana IRM has been added to | Allows @GrafanaIRM to monitor message events in direct messages that its a part of |
| mpim:history | View messages and other content in group direct messages that Grafana IRM has been added to | Allows @GrafanaIRM to monitor message events in group direct messages that its a part of |

View file

@ -26,10 +26,22 @@ refs:
destination: /docs/oncall/<ONCALL_VERSION>/set-up/open-source/#slack-setup
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/oncall/set-up/open-source/#slack-setup
irm-slack:
- pattern: /docs/oncall/
destination: /docs/oncall/<ONCALL_VERSION>/configure/integrations/references/slack/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/oncall/configure/integrations/references/slack/
---
# Slack integration for Grafana OnCall
{{< admonition type="warning" >}}
The OnCall Slack app is now a Grafana IRM app with new incident management features. Migrate now to access the enhanced capabilities.
Refer to the [Grafana IRM Slack integration](ref:irm-slack) documentation to learn more.
{{< /admonition >}}
{{< collapse title="Legacy Slack integration for Grafana OnCall" >}}
The Slack integration for Grafana OnCall incorporates your Slack workspace directly into your incident response workflow
to help your team focus on alert resolution with less friction.
@ -210,3 +222,4 @@ Use message shortcuts to add resolution notes directly from Slack. Message short
1. Hover over the message and select **More actions** from the menu options.
1. Select **Add as resolution note**.
1. The Grafana OnCall app will react to the message in Slack with the memo emoji and add the message to the alert group timeline.
{{< /collapse >}}

View file

@ -34,9 +34,9 @@ refs:
destination: /docs/grafana-cloud/alerting-and-irm/oncall/configure/escalation-chains-and-routes/#escalation-chains
slack-integration-for-grafana-oncall:
- pattern: /docs/oncall/
destination: /docs/oncall/<ONCALL_VERSION>/manage/notify/slack/
destination: /docs/oncall/<ONCALL_VERSION>/configure/integrations/references/slack/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/oncall/manage/notify/slack/
destination: /docs/grafana-cloud/alerting-and-irm/oncall/configure/integrations/references/slack/
user-and-team-management:
- pattern: /docs/oncall/
destination: /docs/oncall/<ONCALL_VERSION>/manage/user-and-team-management/
@ -233,7 +233,7 @@ To configure Slack for Grafana OnCall:
6. Ensure users verify their Slack accounts in their user profile in Grafana OnCall.
For further instruction on connecting to your Slack workspace, refer to
[Slack integration for Grafana OnCall](ref:slack-integration-for-grafana-oncall)
[Slack integration for Grafana IRM](ref:slack-integration-for-grafana-oncall).
Grafana OnCall also supports other ChatOps integration like Microsoft Teams and Telegram.
For a full list of supported integrations, refer to [Notify people](ref:notify-people).

View file

@ -145,12 +145,16 @@ class StartDirectPaging(scenario_step.ScenarioStep):
if settings.UNIFIED_SLACK_APP_ENABLED:
if slack_team_identity.needs_reinstall:
organizations = _get_available_organizations(slack_team_identity, slack_user_identity)
# Provide a link to web if user has access only to one organization
if len(organizations) == 1:
# Provide a link to web if user has access only to one organization
link = urljoin(organizations[0].web_link, "settings?tab=ChatOps&chatOpsTab=Slack")
upgrade = f"<{link}|Upgrade>"
else:
upgrade = "Upgrade" # TODO: Add link to docs are available
# Otherwise, provide a link to the documentation
link = (
"https://grafana.com/docs/grafana-cloud/alerting-and-irm/oncall/configure/integrations"
"/references/slack/#migrate-to-the-grafana-irm-slack-integration"
)
upgrade = f"<{link}|Upgrade>"
msg = (
f"The new Slack IRM integration is now available. f{upgrade} for a more powerful and flexible "
f"way to interact with Grafana IRM on Slack."

View file

@ -117,7 +117,7 @@ METRICS_ALL = [
METRIC_USER_WAS_NOTIFIED_OF_ALERT_GROUPS_NAME,
]
# List of metrics to collect. Collect all available application metrics by default
METRICS_TO_COLLECT = os.environ.get("METRICS_TO_COLLECT", METRICS_ALL)
METRICS_TO_COLLECT = getenv_list("METRICS_TO_COLLECT", METRICS_ALL)
# Database

View file

@ -120,7 +120,7 @@ export const ApiTokenForm = observer((props: TokenCreationModalProps) => {
<VerticalGroup>
<Label>Curl command example</Label>
<SourceCode noMinHeight showClipboardIconOnly>
{getCurlExample(token, store.onCallApiUrl)}
{getCurlExample(token, store.pluginStore.apiUrlFromStatus)}
</SourceCode>
</VerticalGroup>
);

View file

@ -5,7 +5,7 @@ import { OnCallPluginMetaJSONData } from 'types';
import { ActionKey } from 'models/loader/action-keys';
import { GrafanaApiClient } from 'network/grafana-api/http-client';
import { makeRequest } from 'network/network';
import { PluginConnection, PostStatusResponse } from 'network/oncall-api/api.types';
import { PluginConnection, StatusResponse } from 'network/oncall-api/api.types';
import { RootBaseStore } from 'state/rootBaseStore/RootBaseStore';
import { waitInMs } from 'utils/async';
import { AutoLoadingState } from 'utils/decorators';
@ -31,6 +31,7 @@ On Cloud:
export class PluginStore {
rootStore: RootBaseStore;
connectionStatus?: PluginConnection;
apiUrlFromStatus?: string;
isPluginConnected = false;
appliedOnCallApiUrl = '';
@ -53,9 +54,10 @@ export class PluginStore {
@AutoLoadingState(ActionKey.PLUGIN_VERIFY_CONNECTION)
async verifyPluginConnection() {
const { pluginConnection } = await makeRequest<PostStatusResponse>(`/plugin/status`, {});
const { pluginConnection, api_url } = await makeRequest<StatusResponse>(`/plugin/status`, {});
runInAction(() => {
this.connectionStatus = pluginConnection;
this.apiUrlFromStatus = api_url;
this.isPluginConnected = Object.keys(pluginConnection).every(
(key) => pluginConnection[key as keyof PluginConnection]?.ok
);

View file

@ -16,15 +16,10 @@ type PluginConnection = {
grafana_url_from_engine: PluginConnectionCheck;
};
export type PostStatusResponse = {
export type StatusResponse = {
pluginConnection: PluginConnection;
allow_signup: boolean;
api_url: string;
currently_undergoing_maintenance_message: string | null;
is_installed: boolean;
is_user_anonymous: boolean;
license: string;
recaptcha_site_key: string;
token_ok: boolean;
version: string;
};

View file

@ -31,7 +31,7 @@ import { WithStoreProps } from 'state/types';
import { useStore } from 'state/useStore';
import { withMobXProviderContext } from 'state/withStore';
import { UserActions } from 'utils/authorization/authorization';
import { DOCS_ROOT, DOCS_SLACK_SETUP, getPluginId } from 'utils/consts';
import { DOCS_SLACK_SETUP, getPluginId } from 'utils/consts';
import { useConfirmModal } from 'utils/hooks';
import { showApiError } from 'utils/utils';
@ -353,6 +353,8 @@ const UpgradeToUnifiedSlackBanner = observer(() => {
} = useStore();
const { modalProps, openModal } = useConfirmModal();
const SLACK_MIGRATION_DOCS =
'https://grafana.com/docs/grafana-cloud/alerting-and-irm/oncall/configure/integrations/references/slack/#migrate-to-the-grafana-irm-slack-integration';
return (
<>
<ConfirmModal {...modalProps} />
@ -360,8 +362,7 @@ const UpgradeToUnifiedSlackBanner = observer(() => {
<div className={styles.upgradeSlackAlertText}>
The OnCall Slack app is now a Grafana IRM app with new incident management features. Migrate now to access the
enhanced capabilities.{' '}
<a href={`${DOCS_ROOT}`} target="_blank" rel="noreferrer">
{/* TODO: update link to docs */}
<a href={`${SLACK_MIGRATION_DOCS}`} target="_blank" rel="noreferrer">
Learn more
</a>
</div>
@ -390,12 +391,7 @@ const UpgradeToUnifiedSlackBanner = observer(() => {
</li>
</ul>
</p>
<a
href={`${DOCS_ROOT}`} // TODO: update link to docs
target="_blank"
rel="noreferrer"
className={styles.marginTop}
>
<a href={`${SLACK_MIGRATION_DOCS}`} target="_blank" rel="noreferrer" className={styles.marginTop}>
<Text type="link">
<span>Learn more in the docs</span>
<Icon name="external-link-alt" className="u-margin-left-xs u-margin-bottom-xxs" />

View file

@ -1,7 +0,0 @@
.title {
margin-bottom: 20px;
}
.settings {
width: fit-content;
}

View file

@ -1,7 +1,7 @@
import React from 'react';
import { Field, Input, Switch } from '@grafana/ui';
import cn from 'classnames/bind';
import { css } from '@emotion/css';
import { Field, Input, Switch, useStyles2 } from '@grafana/ui';
import { observer } from 'mobx-react';
import { LegacyNavHeading } from 'navbar/LegacyNavHeading';
@ -10,86 +10,71 @@ import { ApiTokenSettings } from 'containers/ApiTokenSettings/ApiTokenSettings';
import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip';
import { TeamsSettings } from 'pages/settings/tabs/TeamsSettings/TeamsSettings';
import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers';
import { WithStoreProps } from 'state/types';
import { withMobXProviderContext } from 'state/withStore';
import { useStore } from 'state/useStore';
import { UserActions } from 'utils/authorization/authorization';
import styles from './MainSettings.module.css';
export const MainSettings = observer(() => {
const styles = useStyles2(getStyles);
const {
organizationStore: { currentOrganization, saveCurrentOrganization },
pluginStore: { apiUrlFromStatus },
} = useStore();
const cx = cn.bind(styles);
interface SettingsPageProps extends WithStoreProps {}
interface SettingsPageState {
apiUrl?: string;
}
@observer
class Settings extends React.Component<SettingsPageProps, SettingsPageState> {
state: SettingsPageState = {
apiUrl: '',
};
async componentDidMount() {
const { store } = this.props;
const url = await store.getApiUrlForSettings();
this.setState({ apiUrl: url });
}
render() {
const { organizationStore } = this.props.store;
const { currentOrganization } = organizationStore;
const { apiUrl } = this.state;
return (
<div className={cx('root')}>
<LegacyNavHeading>
<Text.Title level={3} className={cx('title')}>
Organization settings
</Text.Title>
</LegacyNavHeading>
<div className={cx('settings')}>
<Text.Title level={3} className={cx('title')}>
Resolution Note
</Text.Title>
<Field
loading={!currentOrganization}
label="Require a resolution note when resolving Alert Groups"
description={`Once user clicks "Resolve" for an Alert Group, they will be required to fill in a resolution note about the Alert Group`}
>
<WithPermissionControlTooltip userAction={UserActions.OtherSettingsWrite}>
<Switch
value={currentOrganization?.is_resolution_note_required}
onChange={(event) => {
organizationStore.saveCurrentOrganization({
is_resolution_note_required: event.currentTarget.checked,
});
}}
/>
</WithPermissionControlTooltip>
</Field>
</div>
{!isTopNavbar() && (
<div style={{ marginBottom: '20px' }}>
<Text.Title level={3} className={cx('title')}>
Teams and Access Settings
</Text.Title>
<TeamsSettings />
</div>
)}
<Text.Title level={3} className={cx('title')}>
API URL
return (
<div>
<LegacyNavHeading>
<Text.Title level={3} className={styles.title}>
Organization settings
</Text.Title>
<div>
<Field>
<Input value={apiUrl} disabled />
</Field>
</div>
<ApiTokenSettings />
</div>
);
}
}
</LegacyNavHeading>
export const MainSettings = withMobXProviderContext(Settings);
<div className={styles.settings}>
<Text.Title level={3} className={styles.title}>
Resolution Note
</Text.Title>
<Field
loading={!currentOrganization}
label="Require a resolution note when resolving Alert Groups"
description={`Once user clicks "Resolve" for an Alert Group, they will be required to fill in a resolution note about the Alert Group`}
>
<WithPermissionControlTooltip userAction={UserActions.OtherSettingsWrite}>
<Switch
value={currentOrganization?.is_resolution_note_required}
onChange={(event) => {
saveCurrentOrganization({
is_resolution_note_required: event.currentTarget.checked,
});
}}
/>
</WithPermissionControlTooltip>
</Field>
</div>
{!isTopNavbar() && (
<div style={{ marginBottom: '20px' }}>
<Text.Title level={3} className={styles.title}>
Teams and Access Settings
</Text.Title>
<TeamsSettings />
</div>
)}
<Text.Title level={3} className={styles.title}>
API URL
</Text.Title>
<div>
<Field>
<Input value={apiUrlFromStatus} disabled />
</Field>
</div>
<ApiTokenSettings />
</div>
);
});
const getStyles = () => ({
settings: css`
width: fit-content;
`,
title: css`
margin-bottom: 20px;
`,
});

View file

@ -69,9 +69,6 @@ export class RootBaseStore {
@observable
pageTitle = '';
@observable
onCallApiUrl: string;
@observable
insightsDatasource = 'grafanacloud-usage';
@ -186,11 +183,6 @@ export class RootBaseStore {
this.pageTitle = title;
}
@action.bound
async getApiUrlForSettings() {
return this.onCallApiUrl;
}
@action.bound
async loadRecaptcha() {
const { recaptcha_site_key } = await makeRequest<{ recaptcha_site_key: string }>('/plugin/recaptcha');

View file

@ -1,4 +1,4 @@
import { AppRootProps as BaseAppRootProps, AppPluginMeta, PluginConfigPageProps, BootData } from '@grafana/data';
import { AppRootProps as BaseAppRootProps, AppPluginMeta, PluginConfigPageProps } from '@grafana/data';
import { getPluginId } from 'utils/consts';
@ -30,8 +30,6 @@ export type OnCallPluginExtensionPoints =
declare global {
export interface Window {
// https://github.com/grafana/grafana/blob/78bef7a26a799209b5307d6bde8e25fcb4fbde7d/public/views/index-template.html#L251-L258
grafanaBootData?: BootData;
RECAPTCHA_SITE_KEY: string;
grecaptcha: any;
dataLayer: any;

View file

@ -24,7 +24,7 @@ def api_call(method: str, base_url: str, path: str, **kwargs) -> requests.Respon
if e.response.status_code == 429:
cooldown_seconds = int(e.response.headers["Retry-After"])
sleep(cooldown_seconds)
return api_call(method, path, **kwargs)
return api_call(method, base_url, path, **kwargs)
elif e.response.status_code == 400:
resp_json = None
with suppress(requests.exceptions.JSONDecodeError):