mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #14256 from grafana/davkal/fix-14245
Explore: Fix label and history suggestions
This commit is contained in:
commit
c441b9eec3
@ -8,9 +8,10 @@ describe('Language completion provider', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('empty query suggestions', () => {
|
describe('empty query suggestions', () => {
|
||||||
it('returns default suggestions on emtpty context', () => {
|
it('returns no suggestions on emtpty context', () => {
|
||||||
const instance = new LanguageProvider(datasource);
|
const instance = new LanguageProvider(datasource);
|
||||||
const result = instance.provideCompletionItems({ text: '', prefix: '', wrapperClasses: [] });
|
const value = Plain.deserialize('');
|
||||||
|
const result = instance.provideCompletionItems({ text: '', prefix: '', value, wrapperClasses: [] });
|
||||||
expect(result.context).toBeUndefined();
|
expect(result.context).toBeUndefined();
|
||||||
expect(result.refresher).toBeUndefined();
|
expect(result.refresher).toBeUndefined();
|
||||||
expect(result.suggestions.length).toEqual(0);
|
expect(result.suggestions.length).toEqual(0);
|
||||||
@ -38,6 +39,32 @@ describe('Language completion provider', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns no suggestions within regexp', () => {
|
||||||
|
const instance = new LanguageProvider(datasource);
|
||||||
|
const value = Plain.deserialize('{} ()');
|
||||||
|
const range = value.selection.merge({
|
||||||
|
anchorOffset: 4,
|
||||||
|
});
|
||||||
|
const valueWithSelection = value.change().select(range).value;
|
||||||
|
const history = [
|
||||||
|
{
|
||||||
|
query: { refId: '1', expr: '{app="foo"}' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const result = instance.provideCompletionItems(
|
||||||
|
{
|
||||||
|
text: '',
|
||||||
|
prefix: '',
|
||||||
|
value: valueWithSelection,
|
||||||
|
wrapperClasses: [],
|
||||||
|
},
|
||||||
|
{ history }
|
||||||
|
);
|
||||||
|
expect(result.context).toBeUndefined();
|
||||||
|
expect(result.refresher).toBeUndefined();
|
||||||
|
expect(result.suggestions.length).toEqual(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('label suggestions', () => {
|
describe('label suggestions', () => {
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
HistoryItem,
|
HistoryItem,
|
||||||
} from 'app/types/explore';
|
} from 'app/types/explore';
|
||||||
import { parseSelector, labelRegexp, selectorRegexp } from 'app/plugins/datasource/prometheus/language_utils';
|
import { parseSelector, labelRegexp, selectorRegexp } from 'app/plugins/datasource/prometheus/language_utils';
|
||||||
import PromqlSyntax from 'app/plugins/datasource/prometheus/promql';
|
import syntax from './syntax';
|
||||||
import { DataQuery } from 'app/types';
|
import { DataQuery } from 'app/types';
|
||||||
|
|
||||||
const DEFAULT_KEYS = ['job', 'namespace'];
|
const DEFAULT_KEYS = ['job', 'namespace'];
|
||||||
@ -55,7 +55,7 @@ export default class LoggingLanguageProvider extends LanguageProvider {
|
|||||||
cleanText = s => s.replace(/[{}[\]="(),!~+\-*/^%]/g, '').trim();
|
cleanText = s => s.replace(/[{}[\]="(),!~+\-*/^%]/g, '').trim();
|
||||||
|
|
||||||
getSyntax() {
|
getSyntax() {
|
||||||
return PromqlSyntax;
|
return syntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
request = url => {
|
request = url => {
|
||||||
@ -70,19 +70,14 @@ export default class LoggingLanguageProvider extends LanguageProvider {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Keep this DOM-free for testing
|
// Keep this DOM-free for testing
|
||||||
provideCompletionItems({ prefix, wrapperClasses, text }: TypeaheadInput, context?: any): TypeaheadOutput {
|
provideCompletionItems({ prefix, wrapperClasses, text, value }: TypeaheadInput, context?: any): TypeaheadOutput {
|
||||||
// Syntax spans have 3 classes by default. More indicate a recognized token
|
// Local text properties
|
||||||
const tokenRecognized = wrapperClasses.length > 3;
|
const empty = value.document.text.length === 0;
|
||||||
// Determine candidates by CSS context
|
// Determine candidates by CSS context
|
||||||
if (_.includes(wrapperClasses, 'context-labels')) {
|
if (_.includes(wrapperClasses, 'context-labels')) {
|
||||||
// Suggestions for metric{|} and metric{foo=|}, as well as metric-independent label queries like {|}
|
// Suggestions for {|} and {foo=|}
|
||||||
return this.getLabelCompletionItems.apply(this, arguments);
|
return this.getLabelCompletionItems.apply(this, arguments);
|
||||||
} else if (
|
} else if (empty) {
|
||||||
// Show default suggestions in a couple of scenarios
|
|
||||||
(prefix && !tokenRecognized) || // Non-empty prefix, but not inside known token
|
|
||||||
(prefix === '' && !text.match(/^[\]})\s]+$/)) || // Empty prefix, but not following a closing brace
|
|
||||||
text.match(/[+\-*/^%]/) // Anything after binary operator
|
|
||||||
) {
|
|
||||||
return this.getEmptyCompletionItems(context || {});
|
return this.getEmptyCompletionItems(context || {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
public/app/plugins/datasource/logging/syntax.ts
Normal file
28
public/app/plugins/datasource/logging/syntax.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* tslint:disable max-line-length */
|
||||||
|
|
||||||
|
const tokenizer = {
|
||||||
|
comment: {
|
||||||
|
pattern: /(^|[^\n])#.*/,
|
||||||
|
lookbehind: true,
|
||||||
|
},
|
||||||
|
'context-labels': {
|
||||||
|
pattern: /(^|\s)\{[^}]*(?=})/,
|
||||||
|
lookbehind: true,
|
||||||
|
inside: {
|
||||||
|
'label-key': {
|
||||||
|
pattern: /[a-z_]\w*(?=\s*(=|!=|=~|!~))/,
|
||||||
|
alias: 'attr-name',
|
||||||
|
},
|
||||||
|
'label-value': {
|
||||||
|
pattern: /"(?:\\.|[^\\"])*"/,
|
||||||
|
greedy: true,
|
||||||
|
alias: 'attr-value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// number: /\b-?\d+((\.\d*)?([eE][+-]?\d+)?)?\b/,
|
||||||
|
operator: new RegExp(`/&&?|\\|?\\||!=?|<(?:=>?|<|>)?|>[>=]?`, 'i'),
|
||||||
|
punctuation: /[{}`,.]/,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default tokenizer;
|
Loading…
Reference in New Issue
Block a user