Commit f7c55d39 by Ryan McKinley Committed by Torkel Ödegaard

Plugins: better warning when plugins fail to load (#18671)

* better pluin feedback

* add server side check for module.js
parent c98c5c3c
......@@ -216,6 +216,17 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
}
loader = reflect.New(reflect.TypeOf(pluginGoType)).Interface().(PluginLoader)
// External plugins need a module.js file for SystemJS to load
if !strings.HasPrefix(pluginJsonFilePath, setting.StaticRootPath) {
module := filepath.Join(filepath.Dir(pluginJsonFilePath), "module.js")
if _, err := os.Stat(module); os.IsNotExist(err) {
plog.Warn("Plugin missing module.js",
"name", pluginCommon.Name,
"warning", "Missing module.js, If you loaded this plugin from git, make sure to compile it.",
"path", module)
}
}
reader.Seek(0, 0)
return loader.Load(jsonParser, currentDir)
}
......
import React, { FunctionComponent } from 'react';
import React, { FunctionComponent, ReactNode } from 'react';
import { AppNotificationSeverity } from 'app/types';
interface Props {
title: string;
icon?: string;
text?: string;
body?: ReactNode;
severity: AppNotificationSeverity;
onClose?: () => void;
}
......@@ -22,7 +22,7 @@ function getIconFromSeverity(severity: AppNotificationSeverity): string {
}
}
export const AlertBox: FunctionComponent<Props> = ({ title, icon, text, severity, onClose }) => {
export const AlertBox: FunctionComponent<Props> = ({ title, icon, body, severity, onClose }) => {
return (
<div className={`alert alert-${severity}`}>
<div className="alert-icon">
......@@ -30,7 +30,7 @@ export const AlertBox: FunctionComponent<Props> = ({ title, icon, text, severity
</div>
<div className="alert-body">
<div className="alert-title">{title}</div>
{text && <div className="alert-text">{text}</div>}
{body && <div className="alert-text">{body}</div>}
</div>
{onClose && (
<button type="button" className="alert-close" onClick={onClose}>
......
......@@ -26,7 +26,7 @@ export default class AppNotificationItem extends Component<Props> {
<AlertBox
severity={appNotification.severity}
title={appNotification.title}
text={appNotification.text}
body={appNotification.text}
icon={appNotification.icon}
onClose={() => onClearNotification(appNotification.id)}
/>
......
......@@ -245,7 +245,7 @@ export class DashboardPage extends PureComponent<Props, State> {
<AlertBox
severity={AppNotificationSeverity.Error}
title={initError.message}
text={getMessageFromError(initError.error)}
body={getMessageFromError(initError.error)}
/>
</div>
);
......
// Libraries
import _ from 'lodash';
import React, { PureComponent } from 'react';
import React, { PureComponent, ReactNode } from 'react';
// Components
import { AlertBox } from 'app/core/components/AlertBox/AlertBox';
// Types
import { AppNotificationSeverity } from 'app/types';
import { PanelProps, PanelPlugin, PluginType } from '@grafana/ui';
import { PanelProps, PanelPlugin, PluginType, PanelPluginMeta } from '@grafana/ui';
interface Props {
pluginId: string;
title: string;
text?: ReactNode;
}
class PanelPluginNotFound extends PureComponent<Props> {
class PanelPluginError extends PureComponent<Props> {
constructor(props: Props) {
super(props);
}
......@@ -28,16 +29,33 @@ class PanelPluginNotFound extends PureComponent<Props> {
return (
<div style={style}>
<AlertBox severity={AppNotificationSeverity.Error} title={`Panel plugin not found: ${this.props.pluginId}`} />
<AlertBox severity={AppNotificationSeverity.Error} {...this.props} />
</div>
);
}
}
export function getPanelPluginLoadError(meta: PanelPluginMeta, err: any): PanelPlugin {
const NotFound = class NotFound extends PureComponent<PanelProps> {
render() {
const text = (
<>
Check the server startup logs for more information. <br />
If this plugin was loaded from git, make sure it was compiled.
</>
);
return <PanelPluginError title={`Error loading: ${meta.id}`} text={text} />;
}
};
const plugin = new PanelPlugin(NotFound);
plugin.meta = meta;
return plugin;
}
export function getPanelPluginNotFound(id: string): PanelPlugin {
const NotFound = class NotFound extends PureComponent<PanelProps> {
render() {
return <PanelPluginNotFound pluginId={id} />;
return <PanelPluginError title={`Panel plugin not found: ${id}`} />;
}
};
......
......@@ -199,7 +199,7 @@ export function importAppPlugin(meta: PluginMeta): Promise<AppPlugin> {
});
}
import { getPanelPluginNotFound } from '../dashboard/dashgrid/PanelPluginNotFound';
import { getPanelPluginNotFound, getPanelPluginLoadError } from '../dashboard/dashgrid/PanelPluginError';
interface PanelCache {
[key: string]: PanelPlugin;
......@@ -233,7 +233,7 @@ export function importPanelPlugin(id: string): Promise<PanelPlugin> {
})
.catch(err => {
// TODO, maybe a different error plugin
console.log('Error loading panel plugin', err);
return getPanelPluginNotFound(id);
console.warn('Error loading panel plugin: ' + id, err);
return getPanelPluginLoadError(meta, err);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment