Przeglądaj źródła

azuremonitor: suggest tables initially

Alexander Zobnin 6 lat temu
rodzic
commit
0c3657da7e

+ 70 - 20
public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx

@@ -1,3 +1,4 @@
+import _ from 'lodash';
 import Plain from 'slate-plain-serializer';
 
 import QueryField from './query_field';
@@ -25,21 +26,43 @@ interface SuggestionGroup {
   skipFilter?: boolean;
 }
 
+interface KustoSchema {
+  Databases: {
+    Default?: KustoDBSchema;
+  };
+  Plugins?: any[];
+}
+
+interface KustoDBSchema {
+  Name?: string;
+  Functions?: any;
+  Tables?: any;
+}
+
+const defaultSchema = () => ({
+  Databases: {
+    Default: {}
+  }
+});
+
 const cleanText = s => s.replace(/[{}[\]="(),!~+\-*/^%]/g, '').trim();
 const wrapText = text => ({ text });
 
 export default class KustoQueryField extends QueryField {
   fields: any;
   events: any;
+  schema: KustoSchema;
 
   constructor(props, context) {
     super(props, context);
+    this.schema = defaultSchema();
 
     this.onTypeahead = debounce(this.onTypeahead, TYPEAHEAD_DELAY);
   }
 
   componentDidMount() {
     this.updateMenu();
+    this.fetchSchema();
   }
 
   onTypeahead = () => {
@@ -128,7 +151,13 @@ export default class KustoQueryField extends QueryField {
         suggestionGroups = this._getKeywordSuggestions();
       } else if (Plain.serialize(this.state.value) === '') {
         typeaheadContext = 'context-new';
-        suggestionGroups = this._getInitialSuggestions();
+        if (this.schema) {
+          suggestionGroups = this._getInitialSuggestions();
+        } else {
+          this.fetchSchema();
+          setTimeout(this.onTypeahead, 0);
+          return;
+        }
       }
 
       let results = 0;
@@ -263,7 +292,7 @@ export default class KustoQueryField extends QueryField {
       {
         prefixMatch: true,
         label: 'Operators',
-        items: operatorTokens.map((s: any) => { s.type = 'function'; return s; })
+        items: operatorTokens
       },
       {
         prefixMatch: true,
@@ -274,34 +303,46 @@ export default class KustoQueryField extends QueryField {
         prefixMatch: true,
         label: 'Macros',
         items: grafanaMacros.map((s: any) => { s.type = 'function'; return s; })
+      },
+      {
+        prefixMatch: true,
+        label: 'Tables',
+        items: _.map(this.schema.Databases.Default.Tables, (t: any) => ({ text: t.Name }))
       }
     ];
   }
 
   private _getInitialSuggestions(): SuggestionGroup[] {
-    // TODO: return datbase tables as an initial suggestion
     return [
       {
         prefixMatch: true,
-        label: 'Keywords',
-        items: KEYWORDS.map(wrapText)
-      },
-      {
-        prefixMatch: true,
-        label: 'Operators',
-        items: operatorTokens.map((s: any) => { s.type = 'function'; return s; })
-      },
-      {
-        prefixMatch: true,
-        label: 'Functions',
-        items: functionTokens.map((s: any) => { s.type = 'function'; return s; })
-      },
-      {
-        prefixMatch: true,
-        label: 'Macros',
-        items: grafanaMacros.map((s: any) => { s.type = 'function'; return s; })
+        label: 'Tables',
+        items: _.map(this.schema.Databases.Default.Tables, (t: any) => ({ text: t.Name }))
       }
     ];
+
+    // return [
+    //   {
+    //     prefixMatch: true,
+    //     label: 'Keywords',
+    //     items: KEYWORDS.map(wrapText)
+    //   },
+    //   {
+    //     prefixMatch: true,
+    //     label: 'Operators',
+    //     items: operatorTokens.map((s: any) => { s.type = 'function'; return s; })
+    //   },
+    //   {
+    //     prefixMatch: true,
+    //     label: 'Functions',
+    //     items: functionTokens.map((s: any) => { s.type = 'function'; return s; })
+    //   },
+    //   {
+    //     prefixMatch: true,
+    //     label: 'Macros',
+    //     items: grafanaMacros.map((s: any) => { s.type = 'function'; return s; })
+    //   }
+    // ];
   }
 
   private async _fetchEvents() {
@@ -329,4 +370,13 @@ export default class KustoQueryField extends QueryField {
     // Stub
     this.fields = [];
   }
+
+  private async fetchSchema() {
+    const schema = await this.props.getSchema();
+    if (schema) {
+      this.schema = schema;
+    } else {
+      this.schema = defaultSchema();
+    }
+  }
 }

+ 6 - 2
public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx

@@ -31,7 +31,7 @@ class Editor extends Component<any, any> {
   };
 
   render() {
-    const { request, variables } = this.props;
+    const { request, variables, getSchema } = this.props;
     const { edited, query } = this.state;
 
     return (
@@ -45,6 +45,7 @@ class Editor extends Component<any, any> {
           placeholder="Enter a query"
           request={request}
           templateVariables={variables}
+          getSchema={getSchema}
         />
       </div>
     );
@@ -54,6 +55,9 @@ class Editor extends Component<any, any> {
 coreModule.directive('kustoEditor', [
   'reactDirective',
   reactDirective => {
-    return reactDirective(Editor, ['change', 'database', 'execute', 'query', 'request', 'variables']);
+    return reactDirective(Editor, [
+      'change', 'database', 'execute', 'query', 'request', 'variables',
+      ['getSchema', { watchDepth: 'reference' }]
+    ]);
   },
 ]);

+ 1 - 0
public/app/plugins/datasource/grafana-azure-monitor-datasource/partials/query.editor.html

@@ -130,6 +130,7 @@
         change="ctrl.onLogAnalyticsQueryChange"
         execute="ctrl.onLogAnalyticsQueryExecute"
         variables="ctrl.templateVariables"
+        getSchema="ctrl.getAzureLogAnalyticsSchema"
       />
     </div>
 

+ 2 - 2
public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.ts

@@ -304,7 +304,7 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
 
   /* Azure Log Analytics */
 
-  getWorkspaces() {
+  getWorkspaces = () => {
     return this.datasource.azureLogAnalyticsDatasource
       .getWorkspaces()
       .then(list => {
@@ -316,7 +316,7 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
       .catch(this.handleQueryCtrlError.bind(this));
   }
 
-  getAzureLogAnalyticsSchema() {
+  getAzureLogAnalyticsSchema = () => {
     return this.getWorkspaces()
       .then(() => {
         return this.datasource.azureLogAnalyticsDatasource.getSchema(this.target.azureLogAnalytics.workspace);