浏览代码

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

* better pluin feedback

* add server side check for module.js
Ryan McKinley 6 年之前
父节点
当前提交
f7c55d3968

+ 11 - 0
pkg/plugins/plugins.go

@@ -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)
 }

+ 4 - 4
public/app/core/components/AlertBox/AlertBox.tsx

@@ -1,10 +1,10 @@
-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}>

+ 1 - 1
public/app/core/components/AppNotifications/AppNotificationItem.tsx

@@ -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)}
       />

+ 1 - 1
public/app/features/dashboard/containers/DashboardPage.tsx

@@ -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>
     );

+ 24 - 6
public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx → public/app/features/dashboard/dashgrid/PanelPluginError.tsx

@@ -1,19 +1,20 @@
 // 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}`} />;
     }
   };
 

+ 3 - 3
public/app/features/plugins/plugin_loader.ts

@@ -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);
     });
 }