mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Fix history rendering for DataQuery
This commit is contained in:
parent
331d419d4f
commit
bbaa5b63c8
@ -1,5 +1,13 @@
|
||||
import { DEFAULT_RANGE, serializeStateToUrlParam, parseUrlState } from './explore';
|
||||
import {
|
||||
DEFAULT_RANGE,
|
||||
serializeStateToUrlParam,
|
||||
parseUrlState,
|
||||
updateHistory,
|
||||
clearHistory,
|
||||
hasNonEmptyQuery,
|
||||
} from './explore';
|
||||
import { ExploreState } from 'app/types/explore';
|
||||
import store from 'app/core/store';
|
||||
|
||||
const DEFAULT_EXPLORE_STATE: ExploreState = {
|
||||
datasource: null,
|
||||
@ -144,3 +152,38 @@ describe('state functions', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateHistory()', () => {
|
||||
const datasourceId = 'myDatasource';
|
||||
const key = `grafana.explore.history.${datasourceId}`;
|
||||
|
||||
beforeEach(() => {
|
||||
clearHistory(datasourceId);
|
||||
expect(store.exists(key)).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should save history item to localStorage', () => {
|
||||
const expected = [
|
||||
{
|
||||
query: { refId: '1', expr: 'metric' },
|
||||
},
|
||||
];
|
||||
expect(updateHistory([], datasourceId, [{ refId: '1', expr: 'metric' }])).toMatchObject(expected);
|
||||
expect(store.exists(key)).toBeTruthy();
|
||||
expect(store.getObject(key)).toMatchObject(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasNonEmptyQuery', () => {
|
||||
test('should return true if one query is non-empty', () => {
|
||||
expect(hasNonEmptyQuery([{ refId: '1', key: '2', expr: 'foo' }])).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should return false if query is empty', () => {
|
||||
expect(hasNonEmptyQuery([{ refId: '1', key: '2' }])).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should return false if no queries exist', () => {
|
||||
expect(hasNonEmptyQuery([])).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
@ -66,6 +66,8 @@ export async function getExploreUrl(
|
||||
return url;
|
||||
}
|
||||
|
||||
const clearQueryKeys: ((query: DataQuery) => object) = ({ key, refId, ...rest }) => rest;
|
||||
|
||||
export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
if (initial) {
|
||||
try {
|
||||
@ -93,7 +95,7 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
export function serializeStateToUrlParam(state: ExploreState, compact?: boolean): string {
|
||||
const urlState: ExploreUrlState = {
|
||||
datasource: state.datasourceName,
|
||||
queries: state.initialQueries.map(({ key, refId, ...rest }) => rest),
|
||||
queries: state.initialQueries.map(clearQueryKeys),
|
||||
range: state.range,
|
||||
};
|
||||
if (compact) {
|
||||
@ -182,3 +184,8 @@ export function updateHistory(history: HistoryItem[], datasourceId: string, quer
|
||||
store.setObject(historyKey, history);
|
||||
return history;
|
||||
}
|
||||
|
||||
export function clearHistory(datasourceId: string) {
|
||||
const historyKey = `grafana.explore.history.${datasourceId}`;
|
||||
store.delete(historyKey);
|
||||
}
|
||||
|
@ -7,12 +7,37 @@ describe('Language completion provider', () => {
|
||||
metadataRequest: () => ({ data: { data: [] } }),
|
||||
};
|
||||
|
||||
it('returns default suggestions on emtpty context', () => {
|
||||
const instance = new LanguageProvider(datasource);
|
||||
const result = instance.provideCompletionItems({ text: '', prefix: '', wrapperClasses: [] });
|
||||
expect(result.context).toBeUndefined();
|
||||
expect(result.refresher).toBeUndefined();
|
||||
expect(result.suggestions.length).toEqual(0);
|
||||
describe('empty query suggestions', () => {
|
||||
it('returns default suggestions on emtpty context', () => {
|
||||
const instance = new LanguageProvider(datasource);
|
||||
const result = instance.provideCompletionItems({ text: '', prefix: '', wrapperClasses: [] });
|
||||
expect(result.context).toBeUndefined();
|
||||
expect(result.refresher).toBeUndefined();
|
||||
expect(result.suggestions.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('returns default suggestions with history on emtpty context when history was provided', () => {
|
||||
const instance = new LanguageProvider(datasource);
|
||||
const value = Plain.deserialize('');
|
||||
const history = [
|
||||
{
|
||||
query: { refId: '1', expr: '{app="foo"}' },
|
||||
},
|
||||
];
|
||||
const result = instance.provideCompletionItems({ text: '', prefix: '', value, wrapperClasses: [] }, { history });
|
||||
expect(result.context).toBeUndefined();
|
||||
expect(result.refresher).toBeUndefined();
|
||||
expect(result.suggestions).toMatchObject([
|
||||
{
|
||||
label: 'History',
|
||||
items: [
|
||||
{
|
||||
label: '{app="foo"}',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('label suggestions', () => {
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
LanguageProvider,
|
||||
TypeaheadInput,
|
||||
TypeaheadOutput,
|
||||
HistoryItem,
|
||||
} from 'app/types/explore';
|
||||
import { parseSelector, labelRegexp, selectorRegexp } from 'app/plugins/datasource/prometheus/language_utils';
|
||||
import PromqlSyntax from 'app/plugins/datasource/prometheus/promql';
|
||||
@ -19,9 +20,9 @@ const HISTORY_COUNT_CUTOFF = 1000 * 60 * 60 * 24; // 24h
|
||||
|
||||
const wrapLabel = (label: string) => ({ label });
|
||||
|
||||
export function addHistoryMetadata(item: CompletionItem, history: any[]): CompletionItem {
|
||||
export function addHistoryMetadata(item: CompletionItem, history: HistoryItem[]): CompletionItem {
|
||||
const cutoffTs = Date.now() - HISTORY_COUNT_CUTOFF;
|
||||
const historyForItem = history.filter(h => h.ts > cutoffTs && h.query === item.label);
|
||||
const historyForItem = history.filter(h => h.ts > cutoffTs && (h.query.expr as string) === item.label);
|
||||
const count = historyForItem.length;
|
||||
const recent = historyForItem[0];
|
||||
let hint = `Queried ${count} times in the last 24h.`;
|
||||
@ -96,9 +97,9 @@ export default class LoggingLanguageProvider extends LanguageProvider {
|
||||
|
||||
if (history && history.length > 0) {
|
||||
const historyItems = _.chain(history)
|
||||
.uniqBy('query')
|
||||
.uniqBy('query.expr')
|
||||
.take(HISTORY_ITEM_COUNT)
|
||||
.map(h => h.query)
|
||||
.map(h => h.query.expr)
|
||||
.map(wrapLabel)
|
||||
.map(item => addHistoryMetadata(item, history))
|
||||
.value();
|
||||
|
@ -125,9 +125,9 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
|
||||
if (history && history.length > 0) {
|
||||
const historyItems = _.chain(history)
|
||||
.uniqBy('query')
|
||||
.uniqBy('query.expr')
|
||||
.take(HISTORY_ITEM_COUNT)
|
||||
.map(h => h.query)
|
||||
.map(h => h.query.expr)
|
||||
.map(wrapLabel)
|
||||
.map(item => addHistoryMetadata(item, history))
|
||||
.value();
|
||||
|
@ -36,6 +36,32 @@ describe('Language completion provider', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns default suggestions with history on emtpty context when history was provided', () => {
|
||||
const instance = new LanguageProvider(datasource);
|
||||
const value = Plain.deserialize('');
|
||||
const history = [
|
||||
{
|
||||
query: { refId: '1', expr: 'metric' },
|
||||
},
|
||||
];
|
||||
const result = instance.provideCompletionItems({ text: '', prefix: '', value, wrapperClasses: [] }, { history });
|
||||
expect(result.context).toBeUndefined();
|
||||
expect(result.refresher).toBeUndefined();
|
||||
expect(result.suggestions).toMatchObject([
|
||||
{
|
||||
label: 'History',
|
||||
items: [
|
||||
{
|
||||
label: 'metric',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Functions',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('range suggestions', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user