azuremonitor: suggest tables initially

This commit is contained in:
Alexander Zobnin
2019-01-30 15:24:37 +03:00
parent f2d2712a95
commit 0c3657da7e
4 changed files with 79 additions and 24 deletions

View File

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

View File

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

View File

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

View File

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