mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Improve parsing ranges from URL (#72498)
* Fix parsing absolute range * Silence warning issued by moment js * Introduce URLRangeValue to enforce better type-checking * Fix unit tests * Allow not passing range to generate ExploreUrl * Use updated time range format in a test * Allow empty object to be passed as a data link for backward compatibility * Update mocks * Post-merge fixes * Simplify checking if range is passed as an empty object * Update docs
This commit is contained in:
parent
654d99fbca
commit
ab451d76ac
@ -173,9 +173,7 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
|
||||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
|
|
||||||
],
|
],
|
||||||
"packages/grafana-data/src/field/overrides/processors.ts:5381": [
|
"packages/grafana-data/src/field/overrides/processors.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
|
@ -847,8 +847,8 @@ describe('getLinksSupplier', () => {
|
|||||||
|
|
||||||
const links = supplier({ valueRowIndex: 0 });
|
const links = supplier({ valueRowIndex: 0 });
|
||||||
const rangeStr = JSON.stringify({
|
const rangeStr = JSON.stringify({
|
||||||
from: range.from.toISOString(),
|
from: range.from.valueOf().toString(),
|
||||||
to: range.to.toISOString(),
|
to: range.to.valueOf().toString(),
|
||||||
});
|
});
|
||||||
const encodeURIParams = `{"range":${rangeStr},"datasource":"${datasourceUid}","queries":["12345"]}`;
|
const encodeURIParams = `{"range":${rangeStr},"datasource":"${datasourceUid}","queries":["12345"]}`;
|
||||||
expect(links.length).toBe(1);
|
expect(links.length).toBe(1);
|
||||||
|
@ -400,7 +400,7 @@ const defaultInternalLinkPostProcessor: DataLinkPostProcessor = (options) => {
|
|||||||
internalLink: link.internal,
|
internalLink: link.internal,
|
||||||
scopedVars: dataLinkScopedVars,
|
scopedVars: dataLinkScopedVars,
|
||||||
field,
|
field,
|
||||||
range: link.internal.range ?? ({} as any),
|
range: link.internal.range,
|
||||||
replaceVariables,
|
replaceVariables,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
import { DataQuery } from '@grafana/schema';
|
import { DataQuery } from '@grafana/schema';
|
||||||
|
|
||||||
import { PreferredVisualisationType } from './data';
|
import { PreferredVisualisationType } from './data';
|
||||||
import { RawTimeRange, TimeRange } from './time';
|
import { TimeRange } from './time';
|
||||||
|
|
||||||
type AnyQuery = DataQuery & Record<string, any>;
|
type AnyQuery = DataQuery & Record<string, any>;
|
||||||
|
|
||||||
|
// enforce type-incompatibility with RawTimeRange to ensure it's parsed and converted.
|
||||||
|
// URLRangeValue may be a string representing UTC time in ms, which is not a compatible
|
||||||
|
// value for RawTimeRange when used as a string (it could only be an ISO formatted date)
|
||||||
|
export type URLRangeValue = string | { __brand: 'URL Range Value' };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export type URLRange = {
|
||||||
|
from: URLRangeValue;
|
||||||
|
to: URLRangeValue;
|
||||||
|
};
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export interface ExploreUrlState<T extends DataQuery = AnyQuery> {
|
export interface ExploreUrlState<T extends DataQuery = AnyQuery> {
|
||||||
datasource: string | null;
|
datasource: string | null;
|
||||||
queries: T[];
|
queries: T[];
|
||||||
range: RawTimeRange;
|
range: URLRange;
|
||||||
panelsState?: ExplorePanelsState;
|
panelsState?: ExplorePanelsState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,21 @@
|
|||||||
|
import { DateTime, toUtc } from '../datetime';
|
||||||
import { DataLink, FieldType, TimeRange } from '../types';
|
import { DataLink, FieldType, TimeRange } from '../types';
|
||||||
|
|
||||||
import { mapInternalLinkToExplore } from './dataLinks';
|
import { mapInternalLinkToExplore } from './dataLinks';
|
||||||
|
|
||||||
|
const createTimeRange = (from: DateTime, to: DateTime): TimeRange => ({
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
raw: {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const DATE_AS_DATE_TIME = toUtc([2000, 1, 1]);
|
||||||
|
const DATE_AS_MS = '949363200000';
|
||||||
|
const TIME_RANGE = createTimeRange(DATE_AS_DATE_TIME, DATE_AS_DATE_TIME);
|
||||||
|
|
||||||
describe('mapInternalLinkToExplore', () => {
|
describe('mapInternalLinkToExplore', () => {
|
||||||
it('creates internal link', () => {
|
it('creates internal link', () => {
|
||||||
const dataLink = {
|
const dataLink = {
|
||||||
@ -18,7 +32,6 @@ describe('mapInternalLinkToExplore', () => {
|
|||||||
link: dataLink,
|
link: dataLink,
|
||||||
internalLink: dataLink.internal,
|
internalLink: dataLink.internal,
|
||||||
scopedVars: {},
|
scopedVars: {},
|
||||||
range: {} as unknown as TimeRange,
|
|
||||||
field: {
|
field: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
@ -59,7 +72,6 @@ describe('mapInternalLinkToExplore', () => {
|
|||||||
link: dataLink,
|
link: dataLink,
|
||||||
internalLink: dataLink.internal!,
|
internalLink: dataLink.internal!,
|
||||||
scopedVars: {},
|
scopedVars: {},
|
||||||
range: {} as unknown as TimeRange,
|
|
||||||
field: {
|
field: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
@ -106,7 +118,7 @@ describe('mapInternalLinkToExplore', () => {
|
|||||||
scopedVars: {
|
scopedVars: {
|
||||||
var1: { text: '', value: 'val1' },
|
var1: { text: '', value: 'val1' },
|
||||||
},
|
},
|
||||||
range: {} as unknown as TimeRange,
|
range: TIME_RANGE,
|
||||||
field: {
|
field: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
type: FieldType.number,
|
type: FieldType.number,
|
||||||
@ -118,6 +130,10 @@ describe('mapInternalLinkToExplore', () => {
|
|||||||
|
|
||||||
expect(decodeURIComponent(link.href)).toEqual(
|
expect(decodeURIComponent(link.href)).toEqual(
|
||||||
`/explore?left=${JSON.stringify({
|
`/explore?left=${JSON.stringify({
|
||||||
|
range: {
|
||||||
|
from: DATE_AS_MS,
|
||||||
|
to: DATE_AS_MS,
|
||||||
|
},
|
||||||
datasource: 'uid',
|
datasource: 'uid',
|
||||||
queries: [
|
queries: [
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import { locationUtil } from './location';
|
import { locationUtil } from './location';
|
||||||
import { serializeStateToUrlParam } from './url';
|
import { serializeStateToUrlParam, toURLRange } from './url';
|
||||||
|
|
||||||
export const DataLinkBuiltInVars = {
|
export const DataLinkBuiltInVars = {
|
||||||
keepTime: '__url_time_range',
|
keepTime: '__url_time_range',
|
||||||
@ -33,7 +33,7 @@ export const DataLinkBuiltInVars = {
|
|||||||
export type LinkToExploreOptions = {
|
export type LinkToExploreOptions = {
|
||||||
link: DataLink;
|
link: DataLink;
|
||||||
scopedVars: ScopedVars;
|
scopedVars: ScopedVars;
|
||||||
range: TimeRange;
|
range?: TimeRange;
|
||||||
field: Field;
|
field: Field;
|
||||||
internalLink: InternalDataLink;
|
internalLink: InternalDataLink;
|
||||||
onClickFn?: SplitOpen;
|
onClickFn?: SplitOpen;
|
||||||
@ -77,13 +77,16 @@ export function mapInternalLinkToExplore(options: LinkToExploreOptions): LinkMod
|
|||||||
function generateInternalHref<T extends DataQuery = any>(
|
function generateInternalHref<T extends DataQuery = any>(
|
||||||
datasourceUid: string,
|
datasourceUid: string,
|
||||||
query: T,
|
query: T,
|
||||||
range: TimeRange,
|
range?: TimeRange,
|
||||||
panelsState?: ExplorePanelsState
|
panelsState?: ExplorePanelsState
|
||||||
): string {
|
): string {
|
||||||
return locationUtil.assureBaseUrl(
|
return locationUtil.assureBaseUrl(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
serializeStateToUrlParam({
|
serializeStateToUrlParam({
|
||||||
range: range.raw,
|
// @deprecated mapInternalLinkToExplore required passing range. Some consumers to generate the URL
|
||||||
|
// with defaults pass range as `{} as any`. This is why we need to check for `range?.raw` not just
|
||||||
|
// `range ? ...` here. This behavior will be marked as deprecated in #72498
|
||||||
|
...(range?.raw ? { range: toURLRange(range.raw) } : {}),
|
||||||
datasource: datasourceUid,
|
datasource: datasourceUid,
|
||||||
queries: [query],
|
queries: [query],
|
||||||
panelsState: panelsState,
|
panelsState: panelsState,
|
||||||
|
@ -16,7 +16,7 @@ export { PanelOptionsEditorBuilder, FieldConfigEditorBuilder } from './OptionsUI
|
|||||||
export { arrayUtils };
|
export { arrayUtils };
|
||||||
export { getFlotPairs, getFlotPairsConstant } from './flotPairs';
|
export { getFlotPairs, getFlotPairsConstant } from './flotPairs';
|
||||||
export { locationUtil } from './location';
|
export { locationUtil } from './location';
|
||||||
export { urlUtil, type UrlQueryMap, type UrlQueryValue, serializeStateToUrlParam } from './url';
|
export { urlUtil, type UrlQueryMap, type UrlQueryValue, serializeStateToUrlParam, toURLRange } from './url';
|
||||||
export { DataLinkBuiltInVars, mapInternalLinkToExplore } from './dataLinks';
|
export { DataLinkBuiltInVars, mapInternalLinkToExplore } from './dataLinks';
|
||||||
export { DocsId } from './docs';
|
export { DocsId } from './docs';
|
||||||
export { makeClassES5Compatible } from './makeClassES5Compatible';
|
export { makeClassES5Compatible } from './makeClassES5Compatible';
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
* @preserve jquery-param (c) 2015 KNOWLEDGECODE | MIT
|
* @preserve jquery-param (c) 2015 KNOWLEDGECODE | MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isDateTime } from '../datetime';
|
||||||
|
import { URLRange, RawTimeRange } from '../types';
|
||||||
import { ExploreUrlState } from '../types/explore';
|
import { ExploreUrlState } from '../types/explore';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,14 +202,37 @@ export const urlUtil = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an string that is used in URL to represent the Explore state. This is basically just a stringified json
|
* Create an string that is used in URL to represent the Explore state. This is basically just a stringified json
|
||||||
* that is that used as a state of a single Explore pane so it does not represent full Explore URL.
|
* that is used as a state of a single Explore pane so it does not represent full Explore URL so some properties
|
||||||
|
* may be omitted (they will be filled in with default values).
|
||||||
*
|
*
|
||||||
* @param urlState
|
* @param urlState
|
||||||
* @param compact this parameter is deprecated and will be removed in a future release.
|
* @param compact this parameter is deprecated and will be removed in a future release.
|
||||||
*/
|
*/
|
||||||
export function serializeStateToUrlParam(urlState: ExploreUrlState, compact?: boolean): string {
|
export function serializeStateToUrlParam(urlState: Partial<ExploreUrlState>, compact?: boolean): string {
|
||||||
if (compact !== undefined) {
|
if (compact !== undefined) {
|
||||||
console.warn('`compact` parameter is deprecated and will be removed in a future release');
|
console.warn('`compact` parameter is deprecated and will be removed in a future release');
|
||||||
}
|
}
|
||||||
return JSON.stringify(urlState);
|
return JSON.stringify(urlState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts RawTimeRange to a string that is stored in the URL
|
||||||
|
* - relative - stays as it is (e.g. "now")
|
||||||
|
* - absolute - converted to ms
|
||||||
|
*/
|
||||||
|
export const toURLRange = (range: RawTimeRange): URLRange => {
|
||||||
|
let from = range.from;
|
||||||
|
if (isDateTime(from)) {
|
||||||
|
from = from.valueOf().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
let to = range.to;
|
||||||
|
if (isDateTime(to)) {
|
||||||
|
to = to.valueOf().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -87,7 +87,7 @@ describe('getExploreUrl', () => {
|
|||||||
getDataSourceById: jest.fn(),
|
getDataSourceById: jest.fn(),
|
||||||
},
|
},
|
||||||
timeSrv: {
|
timeSrv: {
|
||||||
timeRangeForUrl: () => '1',
|
timeRange: () => ({ raw: { from: 'now-1h', to: 'now' } }),
|
||||||
},
|
},
|
||||||
} as unknown as GetExploreUrlArguments;
|
} as unknown as GetExploreUrlArguments;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
|
toURLRange,
|
||||||
urlUtil,
|
urlUtil,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { DataSourceSrv, getDataSourceSrv } from '@grafana/runtime';
|
import { DataSourceSrv, getDataSourceSrv } from '@grafana/runtime';
|
||||||
@ -76,8 +77,8 @@ export async function getExploreUrl(args: GetExploreUrlArguments): Promise<strin
|
|||||||
let url: string | undefined;
|
let url: string | undefined;
|
||||||
|
|
||||||
if (exploreDatasource) {
|
if (exploreDatasource) {
|
||||||
const range = timeSrv.timeRangeForUrl();
|
const range = timeSrv.timeRange().raw;
|
||||||
let state: Partial<ExploreUrlState> = { range };
|
let state: Partial<ExploreUrlState> = { range: toURLRange(range) };
|
||||||
if (exploreDatasource.interpolateVariablesInQueries) {
|
if (exploreDatasource.interpolateVariablesInQueries) {
|
||||||
const scopedVars = panel.scopedVars || {};
|
const scopedVars = panel.scopedVars || {};
|
||||||
state = {
|
state = {
|
||||||
|
@ -61,7 +61,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"{cluster=\\"cluster1\\", hostname=\\"hostname1\\", service_namespace=\\"namespace1\\"}","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"expr":"{cluster=\\"cluster1\\", hostname=\\"hostname1\\", service_namespace=\\"namespace1\\"}","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -87,7 +87,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"{ip=\\"192.168.0.1\\"}","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"expr":"{ip=\\"192.168.0.1\\"}","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -113,34 +113,35 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"{ip=\\"192.168.0.1\\", host=\\"host\\"}","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"expr":"{ip=\\"192.168.0.1\\", host=\\"host\\"}","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with adjusted start and end time', () => {
|
it('with adjusted start and end time', () => {
|
||||||
const createLink = setupSpanLinkFactory({
|
const createLink = setupSpanLinkFactory({
|
||||||
spanStartTimeShift: '1m',
|
spanStartTimeShift: '-1m',
|
||||||
spanEndTimeShift: '1m',
|
spanEndTimeShift: '1m',
|
||||||
});
|
});
|
||||||
expect(createLink).toBeDefined();
|
expect(createLink).toBeDefined();
|
||||||
const links = createLink!(
|
const span = createTraceSpan({
|
||||||
createTraceSpan({
|
process: {
|
||||||
process: {
|
serviceName: 'service',
|
||||||
serviceName: 'service',
|
tags: [
|
||||||
tags: [
|
{ key: 'hostname', value: 'hostname1' },
|
||||||
{ key: 'hostname', value: 'hostname1' },
|
{ key: 'ip', value: '192.168.0.1' },
|
||||||
{ key: 'ip', value: '192.168.0.1' },
|
],
|
||||||
],
|
},
|
||||||
},
|
});
|
||||||
})
|
const links = createLink!(span);
|
||||||
);
|
|
||||||
const linkDef = links?.[0];
|
const linkDef = links?.[0];
|
||||||
expect(linkDef).toBeDefined();
|
expect(linkDef).toBeDefined();
|
||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:01:00.000Z","to":"2020-10-14T01:01:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"{hostname=\\"hostname1\\"}","refId":""}]}'
|
`{"range":{"from":"${span.startTime / 1000 - 60000}","to":"${
|
||||||
|
span.startTime / 1000 + span.duration / 1000 + 60000
|
||||||
|
}"},"datasource":"loki1_uid","queries":[{"expr":"{hostname=\\"hostname1\\"}","refId":""}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -159,7 +160,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(decodeURIComponent(linkDef!.href)).toBe(
|
expect(decodeURIComponent(linkDef!.href)).toBe(
|
||||||
'/explore?left=' +
|
'/explore?left=' +
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
range: { from: '2020-10-14T01:00:00.000Z', to: '2020-10-14T01:00:01.000Z' },
|
range: { from: '1602637200000', to: '1602637201000' },
|
||||||
datasource: 'loki1_uid',
|
datasource: 'loki1_uid',
|
||||||
queries: [
|
queries: [
|
||||||
{
|
{
|
||||||
@ -221,7 +222,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"{service=\\"serviceName\\", pod=\\"podName\\"}","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"expr":"{service=\\"serviceName\\", pod=\\"podName\\"}","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -251,7 +252,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"{service.name=\\"serviceName\\", pod=\\"podName\\"}","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"expr":"{service.name=\\"serviceName\\", pod=\\"podName\\"}","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -326,10 +327,10 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef).toBeDefined();
|
expect(linkDef).toBeDefined();
|
||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toContain(
|
expect(linkDef!.href).toContain(
|
||||||
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"}')}`
|
`${encodeURIComponent('{"range":{"from":"1602637200000","to":"1602637201000"}')}`
|
||||||
);
|
);
|
||||||
expect(linkDef!.href).not.toContain(
|
expect(linkDef!.href).not.toContain(
|
||||||
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:00.000Z"}')}`
|
`${encodeURIComponent('{"range":{"from":"1602637200000","to":"1602637200000"}')}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -348,7 +349,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"splunkUID","queries":[{"query":"cluster=\\"cluster1\\" hostname=\\"hostname1\\" service_namespace=\\"namespace1\\" \\"7946b05c2e2e4e5a\\" \\"6605c7b08e715d6c\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"splunkUID","queries":[{"query":"cluster=\\"cluster1\\" hostname=\\"hostname1\\" service_namespace=\\"namespace1\\" \\"7946b05c2e2e4e5a\\" \\"6605c7b08e715d6c\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -372,7 +373,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"splunkUID","queries":[{"query":"ip=\\"192.168.0.1\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"splunkUID","queries":[{"query":"ip=\\"192.168.0.1\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -399,7 +400,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"splunkUID","queries":[{"query":"hostname=\\"hostname1\\" ip=\\"192.168.0.1\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"splunkUID","queries":[{"query":"hostname=\\"hostname1\\" ip=\\"192.168.0.1\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -429,7 +430,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"splunkUID","queries":[{"query":"service=\\"serviceName\\" pod=\\"podName\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"splunkUID","queries":[{"query":"service=\\"serviceName\\" pod=\\"podName\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -466,7 +467,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Metrics);
|
expect(linkDef?.type).toBe(SpanLinkType.Metrics);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T00:58:00.000Z","to":"2020-10-14T01:02:01.000Z"},"datasource":"prom1Uid","queries":[{"expr":"customQuery","refId":"A"}]}'
|
'{"range":{"from":"1602637080000","to":"1602637321000"},"datasource":"prom1Uid","queries":[{"expr":"customQuery","refId":"A"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -515,7 +516,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(namedLink!.title).toBe('Named Query');
|
expect(namedLink!.title).toBe('Named Query');
|
||||||
expect(namedLink!.href).toBe(
|
expect(namedLink!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T00:58:00.000Z","to":"2020-10-14T01:02:01.000Z"},"datasource":"prom1Uid","queries":[{"expr":"customQuery","refId":"A"}]}'
|
'{"range":{"from":"1602637080000","to":"1602637321000"},"datasource":"prom1Uid","queries":[{"expr":"customQuery","refId":"A"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -525,7 +526,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(defaultLink!.title).toBe('defaultQuery');
|
expect(defaultLink!.title).toBe('defaultQuery');
|
||||||
expect(defaultLink!.href).toBe(
|
expect(defaultLink!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T00:58:00.000Z","to":"2020-10-14T01:02:01.000Z"},"datasource":"prom1Uid","queries":[{"expr":"histogram_quantile(0.5, sum(rate(traces_spanmetrics_latency_bucket{service=\\"test service\\"}[5m])) by (le))","refId":"A"}]}'
|
'{"range":{"from":"1602637080000","to":"1602637321000"},"datasource":"prom1Uid","queries":[{"expr":"histogram_quantile(0.5, sum(rate(traces_spanmetrics_latency_bucket{service=\\"test service\\"}[5m])) by (le))","refId":"A"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -535,7 +536,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(unnamedQuery!.title).toBeUndefined();
|
expect(unnamedQuery!.title).toBeUndefined();
|
||||||
expect(unnamedQuery!.href).toBe(
|
expect(unnamedQuery!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T00:58:00.000Z","to":"2020-10-14T01:02:01.000Z"},"datasource":"prom1Uid","queries":[{"expr":"no_name_here","refId":"A"}]}'
|
'{"range":{"from":"1602637080000","to":"1602637321000"},"datasource":"prom1Uid","queries":[{"expr":"no_name_here","refId":"A"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -561,7 +562,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Metrics);
|
expect(linkDef?.type).toBe(SpanLinkType.Metrics);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T00:00:00.000Z","to":"2020-10-14T02:00:01.000Z"},"datasource":"prom1Uid","queries":[{"expr":"customQuery","refId":"A"}]}'
|
'{"range":{"from":"1602633600000","to":"1602640801000"},"datasource":"prom1Uid","queries":[{"expr":"customQuery","refId":"A"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -599,7 +600,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(links![0].type).toBe(SpanLinkType.Metrics);
|
expect(links![0].type).toBe(SpanLinkType.Metrics);
|
||||||
expect(links![0].href).toBe(
|
expect(links![0].href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T00:58:00.000Z","to":"2020-10-14T01:02:01.000Z"},"datasource":"prom1Uid","queries":[{"expr":"metric{job=\\"tns/app\\", pod=\\"sample-pod\\", job=\\"tns/app\\", pod=\\"sample-pod\\"}[5m]","refId":"A"}]}'
|
'{"range":{"from":"1602637080000","to":"1602637321000"},"datasource":"prom1Uid","queries":[{"expr":"metric{job=\\"tns/app\\", pod=\\"sample-pod\\", job=\\"tns/app\\", pod=\\"sample-pod\\"}[5m]","refId":"A"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -703,10 +704,10 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef).toBeDefined();
|
expect(linkDef).toBeDefined();
|
||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toContain(
|
expect(linkDef!.href).toContain(
|
||||||
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"}')}`
|
`${encodeURIComponent('{"range":{"from":"1602637200000","to":"1602637201000"}')}`
|
||||||
);
|
);
|
||||||
expect(linkDef!.href).not.toContain(
|
expect(linkDef!.href).not.toContain(
|
||||||
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:00.000Z"}')}`
|
`${encodeURIComponent('{"range":{"from":"1602637200000","to":"1602637200000"}')}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -728,7 +729,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"\\"6605c7b08e715d6c\\" AND \\"7946b05c2e2e4e5a\\" AND cluster:\\"cluster1\\" AND hostname:\\"hostname1\\" AND service_namespace:\\"namespace1\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"\\"6605c7b08e715d6c\\" AND \\"7946b05c2e2e4e5a\\" AND cluster:\\"cluster1\\" AND hostname:\\"hostname1\\" AND service_namespace:\\"namespace1\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -756,7 +757,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef).toBeDefined();
|
expect(linkDef).toBeDefined();
|
||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(decodeURIComponent(linkDef!.href)).toBe(
|
expect(decodeURIComponent(linkDef!.href)).toBe(
|
||||||
`/explore?left={"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"searchUID","queries":[{"query":"\\"7946b05c2e2e4e5a\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
`/explore?left={"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"searchUID","queries":[{"query":"\\"7946b05c2e2e4e5a\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -782,7 +783,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"ip:\\"192.168.0.1\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"ip:\\"192.168.0.1\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -812,7 +813,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"hostname:\\"hostname1\\" AND ip:\\"192.168.0.1\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"hostname:\\"hostname1\\" AND ip:\\"192.168.0.1\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -845,7 +846,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"service:\\"serviceName\\" AND pod:\\"podName\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"service:\\"serviceName\\" AND pod:\\"podName\\"","refId":"","metrics":[{"id":"1","type":"logs"}]}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -893,10 +894,10 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef).toBeDefined();
|
expect(linkDef).toBeDefined();
|
||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toContain(
|
expect(linkDef!.href).toContain(
|
||||||
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"}')}`
|
`${encodeURIComponent('{"range":{"from":"1602637200000","to":"1602637201000"}')}`
|
||||||
);
|
);
|
||||||
expect(linkDef!.href).not.toContain(
|
expect(linkDef!.href).not.toContain(
|
||||||
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:00.000Z"}')}`
|
`${encodeURIComponent('{"range":{"from":"1602637200000","to":"1602637200000"}')}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -918,7 +919,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"\\"6605c7b08e715d6c\\" AND \\"7946b05c2e2e4e5a\\" AND cluster=\\"cluster1\\" AND hostname=\\"hostname1\\" AND service_namespace=\\"namespace1\\"","refId":""}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"\\"6605c7b08e715d6c\\" AND \\"7946b05c2e2e4e5a\\" AND cluster=\\"cluster1\\" AND hostname=\\"hostname1\\" AND service_namespace=\\"namespace1\\"","refId":""}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -946,7 +947,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef).toBeDefined();
|
expect(linkDef).toBeDefined();
|
||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(decodeURIComponent(linkDef!.href)).toBe(
|
expect(decodeURIComponent(linkDef!.href)).toBe(
|
||||||
`/explore?left={"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"searchUID","queries":[{"query":"\\"7946b05c2e2e4e5a\\"","refId":""}]}`
|
`/explore?left={"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"searchUID","queries":[{"query":"\\"7946b05c2e2e4e5a\\"","refId":""}]}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -972,7 +973,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"ip=\\"192.168.0.1\\"","refId":""}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"ip=\\"192.168.0.1\\"","refId":""}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1002,7 +1003,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"hostname=\\"hostname1\\" AND ip=\\"192.168.0.1\\"","refId":""}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"hostname=\\"hostname1\\" AND ip=\\"192.168.0.1\\"","refId":""}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1035,7 +1036,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
`{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"${searchUID}","queries":[{"query":"service=\\"serviceName\\" AND pod=\\"podName\\"","refId":""}]}`
|
`{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"${searchUID}","queries":[{"query":"service=\\"serviceName\\" AND pod=\\"podName\\"","refId":""}]}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1142,7 +1143,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"cluster=\\"cluster1\\" OR hostname=\\"hostname1\\" OR service_namespace=\\"namespace1\\" or \\"7946b05c2e2e4e5a\\" or \\"6605c7b08e715d6c\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"falconLogScaleUID","queries":[{"lsql":"cluster=\\"cluster1\\" OR hostname=\\"hostname1\\" OR service_namespace=\\"namespace1\\" or \\"7946b05c2e2e4e5a\\" or \\"6605c7b08e715d6c\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1166,7 +1167,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"ip=\\"192.168.0.1\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"falconLogScaleUID","queries":[{"lsql":"ip=\\"192.168.0.1\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1193,7 +1194,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"hostname=\\"hostname1\\" OR ip=\\"192.168.0.1\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"falconLogScaleUID","queries":[{"lsql":"hostname=\\"hostname1\\" OR ip=\\"192.168.0.1\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1223,7 +1224,7 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
expect(linkDef?.type).toBe(SpanLinkType.Logs);
|
||||||
expect(linkDef!.href).toBe(
|
expect(linkDef!.href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"service=\\"serviceName\\" OR pod=\\"podName\\"","refId":""}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"falconLogScaleUID","queries":[{"lsql":"service=\\"serviceName\\" OR pod=\\"podName\\"","refId":""}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1258,13 +1259,13 @@ describe('dataFrame links', () => {
|
|||||||
expect(links![0].type).toBe(SpanLinkType.Unknown);
|
expect(links![0].type).toBe(SpanLinkType.Unknown);
|
||||||
expect(links![1].href).toBe(
|
expect(links![1].href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"message":"SELECT * FROM superhero WHERE name=host"}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"message":"SELECT * FROM superhero WHERE name=host"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
expect(links![1].type).toBe(SpanLinkType.Unknown);
|
expect(links![1].type).toBe(SpanLinkType.Unknown);
|
||||||
expect(links![2].href).toBe(
|
expect(links![2].href).toBe(
|
||||||
`/explore?left=${encodeURIComponent(
|
`/explore?left=${encodeURIComponent(
|
||||||
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1_uid","queries":[{"expr":"go_memstats_heap_inuse_bytes{job=\'host\'}"}]}'
|
'{"range":{"from":"1602637200000","to":"1602637201000"},"datasource":"loki1_uid","queries":[{"expr":"go_memstats_heap_inuse_bytes{job=\'host\'}"}]}'
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
expect(links![2].type).toBe(SpanLinkType.Unknown);
|
expect(links![2].type).toBe(SpanLinkType.Unknown);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { identity, isEmpty, isEqual, isObject, mapValues, omitBy } from 'lodash';
|
import { identity, isEmpty, isEqual, isObject, mapValues, omitBy } from 'lodash';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import { CoreApp, ExploreUrlState, RawTimeRange, DataSourceApi } from '@grafana/data';
|
import { CoreApp, ExploreUrlState, DataSourceApi, toURLRange } from '@grafana/data';
|
||||||
import { DataQuery, DataSourceRef } from '@grafana/schema';
|
import { DataQuery, DataSourceRef } from '@grafana/schema';
|
||||||
import { useGrafana } from 'app/core/context/GrafanaContext';
|
import { useGrafana } from 'app/core/context/GrafanaContext';
|
||||||
import { clearQueryKeys, getLastUsedDatasourceUID } from 'app/core/utils/explore';
|
import { clearQueryKeys, getLastUsedDatasourceUID } from 'app/core/utils/explore';
|
||||||
@ -15,7 +15,7 @@ import { clearPanes, splitClose, splitOpen, syncTimesAction } from '../../state/
|
|||||||
import { runQueries, setQueriesAction } from '../../state/query';
|
import { runQueries, setQueriesAction } from '../../state/query';
|
||||||
import { selectPanes } from '../../state/selectors';
|
import { selectPanes } from '../../state/selectors';
|
||||||
import { changeRangeAction, updateTime } from '../../state/time';
|
import { changeRangeAction, updateTime } from '../../state/time';
|
||||||
import { DEFAULT_RANGE, fromURLRange, toURLTimeRange } from '../../state/utils';
|
import { DEFAULT_RANGE, fromURLRange } from '../../state/utils';
|
||||||
import { withUniqueRefIds } from '../../utils/queries';
|
import { withUniqueRefIds } from '../../utils/queries';
|
||||||
import { isFulfilled } from '../utils';
|
import { isFulfilled } from '../utils';
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ export function useStateSync(params: ExploreQueryParams) {
|
|||||||
exploreId,
|
exploreId,
|
||||||
datasource: datasource || '',
|
datasource: datasource || '',
|
||||||
queries: withUniqueRefIds(queries),
|
queries: withUniqueRefIds(queries),
|
||||||
range,
|
range: fromURLRange(range),
|
||||||
panelsState,
|
panelsState,
|
||||||
position: i,
|
position: i,
|
||||||
})
|
})
|
||||||
@ -207,7 +207,7 @@ export function useStateSync(params: ExploreQueryParams) {
|
|||||||
exploreId,
|
exploreId,
|
||||||
datasource,
|
datasource,
|
||||||
queries,
|
queries,
|
||||||
range,
|
range: fromURLRange(range),
|
||||||
panelsState,
|
panelsState,
|
||||||
})
|
})
|
||||||
).unwrap();
|
).unwrap();
|
||||||
@ -358,7 +358,7 @@ const urlDiff = (
|
|||||||
} => {
|
} => {
|
||||||
const datasource = !isEqual(currentUrlState?.datasource, oldUrlState?.datasource);
|
const datasource = !isEqual(currentUrlState?.datasource, oldUrlState?.datasource);
|
||||||
const queries = !isEqual(currentUrlState?.queries, oldUrlState?.queries);
|
const queries = !isEqual(currentUrlState?.queries, oldUrlState?.queries);
|
||||||
const range = !areRangesEqual(currentUrlState?.range || DEFAULT_RANGE, oldUrlState?.range || DEFAULT_RANGE);
|
const range = !isEqual(currentUrlState?.range || DEFAULT_RANGE, oldUrlState?.range || DEFAULT_RANGE);
|
||||||
const panelsState = !isEqual(currentUrlState?.panelsState, oldUrlState?.panelsState);
|
const panelsState = !isEqual(currentUrlState?.panelsState, oldUrlState?.panelsState);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -369,20 +369,13 @@ const urlDiff = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const areRangesEqual = (a: RawTimeRange, b: RawTimeRange): boolean => {
|
|
||||||
const parsedA = toURLTimeRange(a);
|
|
||||||
const parsedB = toURLTimeRange(b);
|
|
||||||
|
|
||||||
return parsedA.from === parsedB.from && parsedA.to === parsedB.to;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getUrlStateFromPaneState(pane: ExploreItemState): ExploreUrlState {
|
export function getUrlStateFromPaneState(pane: ExploreItemState): ExploreUrlState {
|
||||||
return {
|
return {
|
||||||
// datasourceInstance should not be undefined anymore here but in case there is some path for it to be undefined
|
// datasourceInstance should not be undefined anymore here but in case there is some path for it to be undefined
|
||||||
// lets just fallback instead of crashing.
|
// lets just fallback instead of crashing.
|
||||||
datasource: pane.datasourceInstance?.uid || '',
|
datasource: pane.datasourceInstance?.uid || '',
|
||||||
queries: pane.queries.map(clearQueryKeys),
|
queries: pane.queries.map(clearQueryKeys),
|
||||||
range: toURLTimeRange(pane.range.raw),
|
range: toURLRange(pane.range.raw),
|
||||||
// don't include panelsState in the url unless a piece of state is actually set
|
// don't include panelsState in the url unless a piece of state is actually set
|
||||||
panelsState: pruneObject(pane.panelsState),
|
panelsState: pruneObject(pane.panelsState),
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ jest.mock('app/features/plugins/datasource_srv', () => ({
|
|||||||
getDatasourceSrv: jest.fn(() => dataSourceMock),
|
getDatasourceSrv: jest.fn(() => dataSourceMock),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import { loadAndInitDatasource, getRange } from './utils';
|
import { loadAndInitDatasource, getRange, fromURLRange } from './utils';
|
||||||
|
|
||||||
const DEFAULT_DATASOURCE = { uid: 'abc123', name: 'Default' };
|
const DEFAULT_DATASOURCE = { uid: 'abc123', name: 'Default' };
|
||||||
const TEST_DATASOURCE = { uid: 'def789', name: 'Test' };
|
const TEST_DATASOURCE = { uid: 'def789', name: 'Test' };
|
||||||
@ -58,17 +58,17 @@ describe('getRange', () => {
|
|||||||
const result = getRange(range, 'browser');
|
const result = getRange(range, 'browser');
|
||||||
expect(result.raw).toEqual(range);
|
expect(result.raw).toEqual(range);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fromURLRange', () => {
|
||||||
it('should parse epoch strings', () => {
|
it('should parse epoch strings', () => {
|
||||||
const range = {
|
const range = {
|
||||||
from: dateTime('2020-10-22T10:00:00Z').valueOf().toString(),
|
from: dateTime('2020-10-22T10:00:00Z').valueOf().toString(),
|
||||||
to: dateTime('2020-10-22T11:00:00Z').valueOf().toString(),
|
to: dateTime('2020-10-22T11:00:00Z').valueOf().toString(),
|
||||||
};
|
};
|
||||||
const result = getRange(range, 'browser');
|
const result = fromURLRange(range);
|
||||||
expect(result.from.valueOf()).toEqual(dateTime('2020-10-22T10:00:00Z').valueOf());
|
expect(result.from.valueOf()).toEqual(dateTime('2020-10-22T10:00:00Z').valueOf());
|
||||||
expect(result.to.valueOf()).toEqual(dateTime('2020-10-22T11:00:00Z').valueOf());
|
expect(result.to.valueOf()).toEqual(dateTime('2020-10-22T11:00:00Z').valueOf());
|
||||||
expect(result.raw.from.valueOf()).toEqual(dateTime('2020-10-22T10:00:00Z').valueOf());
|
|
||||||
expect(result.raw.to.valueOf()).toEqual(dateTime('2020-10-22T11:00:00Z').valueOf());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse ISO strings', () => {
|
it('should parse ISO strings', () => {
|
||||||
@ -76,10 +76,8 @@ describe('getRange', () => {
|
|||||||
from: dateTime('2020-10-22T10:00:00Z').toISOString(),
|
from: dateTime('2020-10-22T10:00:00Z').toISOString(),
|
||||||
to: dateTime('2020-10-22T11:00:00Z').toISOString(),
|
to: dateTime('2020-10-22T11:00:00Z').toISOString(),
|
||||||
};
|
};
|
||||||
const result = getRange(range, 'browser');
|
const result = fromURLRange(range);
|
||||||
expect(result.from.valueOf()).toEqual(dateTime('2020-10-22T10:00:00Z').valueOf());
|
expect(result.from.valueOf()).toEqual(dateTime('2020-10-22T10:00:00Z').valueOf());
|
||||||
expect(result.to.valueOf()).toEqual(dateTime('2020-10-22T11:00:00Z').valueOf());
|
expect(result.to.valueOf()).toEqual(dateTime('2020-10-22T11:00:00Z').valueOf());
|
||||||
expect(result.raw.from.valueOf()).toEqual(dateTime('2020-10-22T10:00:00Z').valueOf());
|
|
||||||
expect(result.raw.to.valueOf()).toEqual(dateTime('2020-10-22T11:00:00Z').valueOf());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -16,6 +16,8 @@ import {
|
|||||||
DateTime,
|
DateTime,
|
||||||
isDateTime,
|
isDateTime,
|
||||||
toUtc,
|
toUtc,
|
||||||
|
URLRange,
|
||||||
|
URLRangeValue,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { DataQuery, DataSourceRef, TimeZone } from '@grafana/schema';
|
import { DataQuery, DataSourceRef, TimeZone } from '@grafana/schema';
|
||||||
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
||||||
@ -144,12 +146,7 @@ export function getResultsFromCache(
|
|||||||
return cacheValue;
|
return cacheValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRange(range: RawTimeRange, timeZone: TimeZone): TimeRange {
|
export function getRange(raw: RawTimeRange, timeZone: TimeZone): TimeRange {
|
||||||
const raw = {
|
|
||||||
from: parseRawTime(range.from)!,
|
|
||||||
to: parseRawTime(range.to)!,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
from: dateMath.parse(raw.from, false, timeZone)!,
|
from: dateMath.parse(raw.from, false, timeZone)!,
|
||||||
to: dateMath.parse(raw.to, true, timeZone)!,
|
to: dateMath.parse(raw.to, true, timeZone)!,
|
||||||
@ -157,10 +154,7 @@ export function getRange(range: RawTimeRange, timeZone: TimeZone): TimeRange {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export function fromURLRange(range: URLRange): RawTimeRange {
|
||||||
* @param range RawTimeRange - Note: Range in the URL is not RawTimeRange compliant (see #72578 for more details)
|
|
||||||
*/
|
|
||||||
export function fromURLRange(range: RawTimeRange): RawTimeRange {
|
|
||||||
let rawTimeRange: RawTimeRange = DEFAULT_RANGE;
|
let rawTimeRange: RawTimeRange = DEFAULT_RANGE;
|
||||||
let parsedRange = {
|
let parsedRange = {
|
||||||
from: parseRawTime(range.from),
|
from: parseRawTime(range.from),
|
||||||
@ -172,35 +166,22 @@ export function fromURLRange(range: RawTimeRange): RawTimeRange {
|
|||||||
return rawTimeRange;
|
return rawTimeRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function parseRawTime(urlRangeValue: URLRangeValue | DateTime): TimeFragment | null {
|
||||||
* @param range RawTimeRange - Note: Range in the URL is not RawTimeRange compliant (see #72578 for more details)
|
if (urlRangeValue === null) {
|
||||||
*/
|
|
||||||
export const toURLTimeRange = (range: RawTimeRange): RawTimeRange => {
|
|
||||||
let from = range.from;
|
|
||||||
if (isDateTime(from)) {
|
|
||||||
from = from.valueOf().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
let to = range.to;
|
|
||||||
if (isDateTime(to)) {
|
|
||||||
to = to.valueOf().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseRawTime(value: string | DateTime): TimeFragment | null {
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDateTime(value)) {
|
if (isDateTime(urlRangeValue)) {
|
||||||
return value;
|
return urlRangeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof urlRangeValue !== 'string') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it can only be a string now
|
||||||
|
const value = urlRangeValue;
|
||||||
|
|
||||||
if (value.indexOf('now') !== -1) {
|
if (value.indexOf('now') !== -1) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user