azuremonitor: more autocomplete suggestions for built-in functions

This commit is contained in:
Alexander Zobnin 2019-02-05 14:01:06 +03:00
parent 99ff8e68ff
commit 4b5bfd3da5
No known key found for this signature in database
GPG Key ID: E17E9ABACEFA59EB

View File

@ -96,57 +96,51 @@ export default class KustoQueryField extends QueryField {
const wrapperClasses = wrapperNode.classList; const wrapperClasses = wrapperNode.classList;
let typeaheadContext: string | null = null; let typeaheadContext: string | null = null;
// Built-in functions
if (wrapperClasses.contains('function-context')) { if (wrapperClasses.contains('function-context')) {
typeaheadContext = 'context-function'; typeaheadContext = 'context-function';
if (this.fields) { suggestionGroups = this.getColumnSuggestions();
suggestionGroups = this.getKeywordSuggestions();
} else { // where
this._fetchFields();
return;
}
} else if (modelPrefix.match(/(where\s(\w+\b)?$)/i)) { } else if (modelPrefix.match(/(where\s(\w+\b)?$)/i)) {
typeaheadContext = 'context-where'; typeaheadContext = 'context-where';
const fullQuery = Plain.serialize(this.state.value); suggestionGroups = this.getColumnSuggestions();
const table = this.getTableFromContext(fullQuery);
if (table) { // summarize by
suggestionGroups = this.getWhereSuggestions(table); } else if (modelPrefix.match(/(summarize\s(\w+\b)?$)/i)) {
} else { typeaheadContext = 'context-summarize';
return; suggestionGroups = this.getFunctionSuggestions();
} } else if (modelPrefix.match(/(summarize\s(.+\s)?by\s+([^,\s]+,\s*)*([^,\s]+\b)?$)/i)) {
} else if (modelPrefix.match(/(,\s*$)/)) { typeaheadContext = 'context-summarize-by';
typeaheadContext = 'context-multiple-fields'; suggestionGroups = this.getColumnSuggestions();
if (this.fields) {
suggestionGroups = this.getKeywordSuggestions(); // order by, top X by, ... by ...
} else { } else if (modelPrefix.match(/(by\s+([^,\s]+,\s*)*([^,\s]+\b)?$)/i)) {
this._fetchFields(); typeaheadContext = 'context-by';
return; suggestionGroups = this.getColumnSuggestions();
}
} else if (modelPrefix.match(/(from\s$)/i)) { // join
typeaheadContext = 'context-from'; } else if (modelPrefix.match(/(on\s(.+\b)?$)/i)) {
if (this.events) { typeaheadContext = 'context-join-on';
suggestionGroups = this.getKeywordSuggestions(); suggestionGroups = this.getColumnSuggestions();
} else { } else if (modelPrefix.match(/(join\s+(\(\s+)?(\w+\b)?$)/i)) {
this._fetchEvents(); typeaheadContext = 'context-join';
return; suggestionGroups = this.getTableSuggestions();
}
} else if (modelPrefix.match(/(^select\s\w*$)/i)) { // distinct
typeaheadContext = 'context-select'; } else if (modelPrefix.match(/(distinct\s(.+\b)?$)/i)) {
if (this.fields) { typeaheadContext = 'context-distinct';
suggestionGroups = this.getKeywordSuggestions(); suggestionGroups = this.getColumnSuggestions();
} else {
this._fetchFields(); // database()
return; } else if (modelPrefix.match(/(database\(\"(\w+)\"\)\.(.+\b)?$)/i)) {
} typeaheadContext = 'context-database-table';
} else if (modelPrefix.match(/from\s\S+\s\w*$/i)) { const db = this.getDBFromDatabaseFunction(modelPrefix);
prefix = ''; console.log(db);
typeaheadContext = 'context-since'; suggestionGroups = this.getTableSuggestions(db);
suggestionGroups = this.getKeywordSuggestions(); prefix = prefix.replace('.', '');
// } else if (modelPrefix.match(/\d+\s\w*$/)) {
// typeaheadContext = 'context-number'; // built-in
// suggestionGroups = this._getAfterNumberSuggestions();
} else if (modelPrefix.match(/ago\b/i) || modelPrefix.match(/facet\b/i) || modelPrefix.match(/\$__timefilter\b/i)) {
typeaheadContext = 'context-timeseries';
suggestionGroups = this.getKeywordSuggestions();
} else if (prefix && !wrapperClasses.contains('argument')) { } else if (prefix && !wrapperClasses.contains('argument')) {
if (modelPrefix.match(/\s$/i)) { if (modelPrefix.match(/\s$/i)) {
prefix = ''; prefix = '';
@ -156,7 +150,7 @@ export default class KustoQueryField extends QueryField {
} else if (Plain.serialize(this.state.value) === '') { } else if (Plain.serialize(this.state.value) === '') {
typeaheadContext = 'context-new'; typeaheadContext = 'context-new';
if (this.schema) { if (this.schema) {
suggestionGroups = this._getInitialSuggestions(); suggestionGroups = this.getInitialSuggestions();
} else { } else {
this.fetchSchema(); this.fetchSchema();
setTimeout(this.onTypeahead, 0); setTimeout(this.onTypeahead, 0);
@ -187,7 +181,7 @@ export default class KustoQueryField extends QueryField {
.filter(group => group.items.length > 0); .filter(group => group.items.length > 0);
// console.log('onTypeahead', selection.anchorNode, wrapperClasses, text, offset, prefix, typeaheadContext); // console.log('onTypeahead', selection.anchorNode, wrapperClasses, text, offset, prefix, typeaheadContext);
// console.log('onTypeahead', modelPrefix, prefix, typeaheadContext); console.log('onTypeahead', modelPrefix, prefix, typeaheadContext);
this.setState({ this.setState({
typeaheadPrefix: prefix, typeaheadPrefix: prefix,
@ -293,6 +287,10 @@ export default class KustoQueryField extends QueryField {
// ]; // ];
// } // }
private getInitialSuggestions(): SuggestionGroup[] {
return this.getTableSuggestions();
}
private getKeywordSuggestions(): SuggestionGroup[] { private getKeywordSuggestions(): SuggestionGroup[] {
return [ return [
{ {
@ -323,40 +321,38 @@ export default class KustoQueryField extends QueryField {
]; ];
} }
private _getInitialSuggestions(): SuggestionGroup[] { private getFunctionSuggestions(): SuggestionGroup[] {
return [
{
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; })
}
];
}
getTableSuggestions(db = 'Default'): SuggestionGroup[] {
if (this.schema.Databases[db]) {
return [ return [
{ {
prefixMatch: true, prefixMatch: true,
label: 'Tables', label: 'Tables',
items: _.map(this.schema.Databases.Default.Tables, (t: any) => ({ text: t.Name })) items: _.map(this.schema.Databases[db].Tables, (t: any) => ({ text: t.Name }))
} }
]; ];
} else {
// return [ 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 getWhereSuggestions(table: string): SuggestionGroup[] { private getColumnSuggestions(): SuggestionGroup[] {
const table = this.getTableFromContext();
if (table) {
const tableSchema = this.schema.Databases.Default.Tables[table]; const tableSchema = this.schema.Databases.Default.Tables[table];
if (tableSchema) { if (tableSchema) {
return [ return [
@ -369,12 +365,13 @@ export default class KustoQueryField extends QueryField {
})) }))
} }
]; ];
} else { }
}
return []; return [];
} }
}
private getTableFromContext(query: string) { private getTableFromContext() {
const query = Plain.serialize(this.state.value);
const tablePattern = /^\s*(\w+)\s*|/g; const tablePattern = /^\s*(\w+)\s*|/g;
const normalizedQuery = normalizeQuery(query); const normalizedQuery = normalizeQuery(query);
const match = tablePattern.exec(normalizedQuery); const match = tablePattern.exec(normalizedQuery);
@ -385,30 +382,14 @@ export default class KustoQueryField extends QueryField {
} }
} }
private async _fetchEvents() { private getDBFromDatabaseFunction(prefix: string) {
// const query = 'events'; const databasePattern = /database\(\"(\w+)\"\)/gi;
// const result = await this.request(query); const match = databasePattern.exec(prefix);
if (match && match.length > 1 && match[0] && match[1]) {
// if (result === undefined) { return match[1];
// this.events = []; } else {
// } else { return null;
// this.events = result;
// }
// setTimeout(this.onTypeahead, 0);
//Stub
this.events = [];
} }
private async _fetchFields() {
// const query = 'fields';
// const result = await this.request(query);
// this.fields = result || [];
// setTimeout(this.onTypeahead, 0);
// Stub
this.fields = [];
} }
private async fetchSchema() { private async fetchSchema() {