Feat 380/311 - make plugin configuration error messages more human readable/actionable (#563)

* remove unused imports

* remove unused/redundant jsx comment

* don't show pluginStatusMessage as a styled link

* show more human readable plugin configuration errors
This commit is contained in:
Joey Orlando 2022-09-27 17:31:25 +02:00 committed by GitHub
parent 516b2c446a
commit 0afb377117
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 28 deletions

View file

@ -21,11 +21,13 @@ Developer-friendly incident response with brilliant Slack integration.
We prepared multiple environments: [production](https://grafana.com/docs/grafana-cloud/oncall/open-source/#production-environment), [developer](DEVELOPER.md) and hobby:
1. Download docker-compose.yaml:
```bash
curl -fsSL https://raw.githubusercontent.com/grafana/oncall/dev/docker-compose.yml -o docker-compose.yml
```
2. Set variables:
```bash
echo "DOMAIN=http://localhost:8080
SECRET_KEY=my_random_secret_must_be_more_than_32_characters_long
@ -37,26 +39,31 @@ GRAFANA_PASSWORD=admin" > .env_hobby
```
3. Launch services:
```bash
docker-compose --env-file .env_hobby -f docker-compose.yml up -d
```
4. Issue one-time invite token:
```bash
docker-compose --env-file .env_hobby -f docker-compose.yml run engine python manage.py issue_invite_for_the_frontend --override
```
**Note**: if you remove the plugin configuration and reconfigure it, you will need to generate a new one-time invite token for your new configuration.
5. Go to [OnCall Plugin Configuration](http://localhost:3000/plugins/grafana-oncall-app), using log in credentials as defined above: `admin`/`admin` (or find OnCall plugin in configuration->plugins) and connect OnCall _plugin_ with OnCall _backend_:
```
Invite token: ^^^ from the previous step.
OnCall backend URL: http://engine:8080
Grafana Url: http://grafana:3000
```
6. Enjoy! Check our [OSS docs](https://grafana.com/docs/grafana-cloud/oncall/open-source/) if you want to set up Slack, Telegram, Twilio or SMS/calls through Grafana Cloud.
6. Enjoy! Check our [OSS docs](https://grafana.com/docs/grafana-cloud/oncall/open-source/) if you want to set up Slack, Telegram, Twilio or SMS/calls through Grafana Cloud.
## Update version
To update your Grafana OnCall hobby environment:
```shell
@ -76,14 +83,13 @@ See [Grafana docs](https://grafana.com/docs/grafana/latest/administration/plugin
<a href="https://github.com/grafana/oncall/discussions"><img width="200px" src="docs/img/GH_discussions.png"></a>
<a href="https://slack.grafana.com/"><img width="200px" src="docs/img/slack.png"></a>
## Stargazers over time
[![Stargazers over time](https://starchart.cc/grafana/oncall.svg)](https://starchart.cc/grafana/oncall)
## Further Reading
- *Migration from the PagerDuty* - [Migrator](https://github.com/grafana/oncall/tree/dev/tools/pagerduty-migrator)
- *Documentation* - [Grafana OnCall](https://grafana.com/docs/grafana-cloud/oncall/)
- *Blog Post* - [Announcing Grafana OnCall, the easiest way to do on-call management](https://grafana.com/blog/2021/11/09/announcing-grafana-oncall/)
- *Presentation* - [Deep dive into the Grafana, Prometheus, and Alertmanager stack for alerting and on-call management](https://grafana.com/go/observabilitycon/2021/alerting/?pg=blog)
- _Migration from the PagerDuty_ - [Migrator](https://github.com/grafana/oncall/tree/dev/tools/pagerduty-migrator)
- _Documentation_ - [Grafana OnCall](https://grafana.com/docs/grafana-cloud/oncall/)
- _Blog Post_ - [Announcing Grafana OnCall, the easiest way to do on-call management](https://grafana.com/blog/2021/11/09/announcing-grafana-oncall/)
- _Presentation_ - [Deep dive into the Grafana, Prometheus, and Alertmanager stack for alerting and on-call management](https://grafana.com/go/observabilitycon/2021/alerting/?pg=blog)

View file

@ -11,12 +11,8 @@ import {
Label,
Legend,
LoadingPlaceholder,
Icon,
Alert,
Modal,
} from '@grafana/ui';
import cn from 'classnames/bind';
import CopyToClipboard from 'react-copy-to-clipboard';
import { OnCallAppSettings } from 'types';
import Block from 'components/GBlock/Block';
@ -28,6 +24,8 @@ import { createGrafanaToken, getPluginSyncStatus, startPluginSync, updateGrafana
import { GRAFANA_LICENSE_OSS } from 'utils/consts';
import { getItem, setItem } from 'utils/localStorage';
import { constructSyncErrorMessage, constructErrorActionMessage } from './helpers';
import styles from './PluginConfigPage.module.css';
const cx = cn.bind(styles);
@ -45,6 +43,8 @@ export const PluginConfigPage = (props: Props) => {
const [isSelfHostedInstall, setIsSelfHostedInstall] = useState<boolean>(true);
const [retrySync, setRetrySync] = useState<boolean>(false);
const INVALID_INVITE_TOKEN_ERROR_MSG = `It seems like your invite token may be invalid. ${constructErrorActionMessage('generating a new invite token')}`;
const setupPlugin = useCallback(async () => {
setItem('onCallApiUrl', onCallApiUrl);
setItem('grafanaUrl', grafanaUrl);
@ -129,25 +129,37 @@ export const PluginConfigPage = (props: Props) => {
}, []);
const handleSyncException = useCallback((e) => {
const buildErrMsg = (msg: string): string =>
constructSyncErrorMessage(msg, plugin.meta.jsonData.onCallApiUrl);
if (plugin.meta.jsonData?.onCallApiUrl) {
let statusMessage = plugin.meta.jsonData.onCallApiUrl + '\n' + e + ', retry or check settings & re-initialize.';
if (e.response.status == 404) {
statusMessage += '\nIf Grafana OnCall was just installed, restart Grafana for OnCall routes to be available.';
const { status: statusCode } = e.response;
let statusMessage: string;
if (statusCode == 403) {
statusMessage = buildErrMsg(INVALID_INVITE_TOKEN_ERROR_MSG);
} else if (statusCode === 404) {
statusMessage = buildErrMsg('If Grafana OnCall was just installed, restart Grafana for OnCall routes to be available.');
} else if (statusCode === 502) {
statusMessage = buildErrMsg(`Unable to communicate with either the Grafana API, or Grafana OnCall engine API. ${constructErrorActionMessage('verify that the API URLs that you entered are correct')}`);
} else {
statusMessage = buildErrMsg(`An unknown error occured. ${constructErrorActionMessage()}. If the error still occurs please reach out to support.`)
}
setPluginStatusMessage(statusMessage);
setRetrySync(true);
} else {
setPluginStatusMessage('OnCall has not been setup, configure & initialize below.');
setPluginStatusMessage(buildErrMsg('OnCall has not been setup, configure & initialize below.'));
}
setPluginStatusOk(false);
setPluginConfigLoading(false);
}, []);
const finishSync = useCallback((get_sync_response) => {
if (get_sync_response.token_ok) {
const finishSync = useCallback((getSyncResponse) => {
if (getSyncResponse.token_ok) {
const versionInfo =
get_sync_response.version && get_sync_response.license
? ` (${get_sync_response.license}, ${get_sync_response.version})`
getSyncResponse.version && getSyncResponse.license
? ` (${getSyncResponse.license}, ${getSyncResponse.version})`
: '';
let pluginStatusMessage = `Connected to OnCall${versionInfo}\n - OnCall URL: ${plugin.meta.jsonData.onCallApiUrl}\n`
@ -159,9 +171,8 @@ export const PluginConfigPage = (props: Props) => {
setIsSelfHostedInstall(plugin.meta.jsonData?.license === GRAFANA_LICENSE_OSS);
setPluginStatusOk(true);
} else {
setPluginStatusMessage(
`OnCall failed to connect to this grafana via: ${plugin.meta.jsonData.grafanaUrl} check URL, network, and API key.`
);
setPluginStatusMessage(constructSyncErrorMessage(INVALID_INVITE_TOKEN_ERROR_MSG,
plugin.meta.jsonData.grafanaUrl));
setRetrySync(true);
}
setPluginConfigLoading(false);
@ -221,14 +232,10 @@ export const PluginConfigPage = (props: Props) => {
)}
<p>{'Plugin <-> backend connection status'}</p>
<pre>
<Text type="link">{pluginStatusMessage}</Text>
<Text>{pluginStatusMessage}</Text>
</pre>
<HorizontalGroup>
{/* <p>{'Plugin <-> backend connection status'}</p>
<pre>
<Text type="link">{pluginStatusMessage}</Text>
</pre> */}
{retrySync && (
<Button variant="primary" onClick={startSync} size="md">
Retry

View file

@ -0,0 +1,5 @@
export const constructSyncErrorMessage = (errMsg: string, url?: string): string =>
`${url ? `${url}\n` : ''}${errMsg}`;
export const constructErrorActionMessage = (msg?: string): string =>
`Try removing your current configuration, ${msg ? msg : 'double checking your settings'}, and re-initializing the plugin.\nBy removing your current configuration, you will need to ensure that you regenerate a new invite token, and input this in your new configuration.`