mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
logs: restrict permalinks to datasources with id fields (#71729)
* logs: restrict permalinks to datasources with id fields * simplified code * more tests * more test * removed unnecessary comment * fixed tests * updated tests
This commit is contained in:
parent
ab58466d09
commit
d0351bac57
@ -55,6 +55,9 @@ export interface LogRowModel {
|
||||
// the same as rows final index when rendered.
|
||||
rowIndex: number;
|
||||
|
||||
// The value of the the dataframe's id field, if it exists
|
||||
rowId?: string;
|
||||
|
||||
// Full DataFrame from which we parsed this log.
|
||||
// TODO: refactor this so we do not need to pass whole dataframes in addition to also parsed data.
|
||||
dataFrame: DataFrame;
|
||||
|
@ -97,9 +97,9 @@ describe('Logs', () => {
|
||||
|
||||
const getComponent = (partialProps?: Partial<ComponentProps<typeof Logs>>, logs?: LogRowModel[]) => {
|
||||
const rows = [
|
||||
makeLog({ uid: '1', timeEpochMs: 1 }),
|
||||
makeLog({ uid: '2', timeEpochMs: 2 }),
|
||||
makeLog({ uid: '3', timeEpochMs: 3 }),
|
||||
makeLog({ uid: '1', rowId: 'id1', timeEpochMs: 1 }),
|
||||
makeLog({ uid: '2', rowId: 'id2', timeEpochMs: 2 }),
|
||||
makeLog({ uid: '3', rowId: 'id3', timeEpochMs: 3 }),
|
||||
];
|
||||
|
||||
const testDataFrame = {
|
||||
|
@ -374,6 +374,14 @@ class UnthemedLogs extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
onPermalinkClick = async (row: LogRowModel) => {
|
||||
// this is an extra check, to be sure that we are not
|
||||
// creating permalinks for logs without an id-field.
|
||||
// normally it should never happen, because we do not
|
||||
// display the permalink button in such cases.
|
||||
if (row.rowId === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get explore state, add log-row-id and make timerange absolute
|
||||
const urlState = getUrlStateFromPaneState(getState().explore.panes[this.props.exploreId]!);
|
||||
urlState.panelsState = { ...this.props.panelState, logs: { id: row.uid } };
|
||||
|
@ -102,7 +102,7 @@ export const LogRowMenuCell = React.memo(
|
||||
aria-label="Pin line"
|
||||
/>
|
||||
)}
|
||||
{onPermalinkClick && row.uid && (
|
||||
{onPermalinkClick && row.rowId !== undefined && row.uid && (
|
||||
<IconButton
|
||||
tooltip="Copy shortlink"
|
||||
aria-label="Copy shortlink"
|
||||
|
@ -66,12 +66,18 @@ describe('LogRowMessage', () => {
|
||||
});
|
||||
|
||||
describe('with permalinking', () => {
|
||||
it('should show permalinking button when `onPermalinkClick` is defined', async () => {
|
||||
setup({ onPermalinkClick: jest.fn() });
|
||||
it('should show permalinking button when `onPermalinkClick` is defined and rowId is defined', async () => {
|
||||
setup({ onPermalinkClick: jest.fn() }, { rowId: 'id1' });
|
||||
await userEvent.hover(screen.getByText('test123'));
|
||||
expect(screen.queryByLabelText('Copy shortlink')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show permalinking button when `onPermalinkClick` is defined and rowId is not defined', async () => {
|
||||
setup({ onPermalinkClick: jest.fn() });
|
||||
await userEvent.hover(screen.getByText('test123'));
|
||||
expect(screen.queryByLabelText('Copy shortlink')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show permalinking button when `onPermalinkClick` is not defined', () => {
|
||||
setup();
|
||||
expect(screen.queryByLabelText('Copy shortlink')).not.toBeInTheDocument();
|
||||
@ -79,7 +85,7 @@ describe('LogRowMessage', () => {
|
||||
|
||||
it('should call `onPermalinkClick` with row on click', async () => {
|
||||
const permalinkClick = jest.fn();
|
||||
const props = setup({ onPermalinkClick: permalinkClick });
|
||||
const props = setup({ onPermalinkClick: permalinkClick }, { rowId: 'id1' });
|
||||
await userEvent.hover(screen.getByText('test123'));
|
||||
const button = screen.getByLabelText('Copy shortlink');
|
||||
|
||||
|
@ -424,7 +424,7 @@ export function logSeriesToLogsModel(logSeries: DataFrame[], queries: DataQuery[
|
||||
|
||||
const datasourceType = queries.find((query) => query.refId === series.refId)?.datasource?.type;
|
||||
|
||||
rows.push({
|
||||
const row: LogRowModel = {
|
||||
entryFieldIndex: stringField.index,
|
||||
rowIndex: j,
|
||||
dataFrame: series,
|
||||
@ -444,7 +444,13 @@ export function logSeriesToLogsModel(logSeries: DataFrame[], queries: DataQuery[
|
||||
// prepend refId to uid to make it unique across all series in a case when series contain duplicates
|
||||
uid: `${series.refId}_${idField ? idField.values[j] : j.toString()}`,
|
||||
datasourceType,
|
||||
});
|
||||
};
|
||||
|
||||
if (idField !== null) {
|
||||
row.rowId = idField.values[j];
|
||||
}
|
||||
|
||||
rows.push(row);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,6 +137,7 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
rows: [
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
rowId: 'id1',
|
||||
datasourceType: undefined,
|
||||
entry: 'line1',
|
||||
entryFieldIndex: 1,
|
||||
@ -164,6 +165,7 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
},
|
||||
{
|
||||
dataFrame: frames[1],
|
||||
rowId: 'id2',
|
||||
datasourceType: undefined,
|
||||
entry: 'line2',
|
||||
entryFieldIndex: 1,
|
||||
@ -191,6 +193,7 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
},
|
||||
{
|
||||
dataFrame: frames[2],
|
||||
rowId: 'id3',
|
||||
datasourceType: undefined,
|
||||
entry: 'line3',
|
||||
entryFieldIndex: 1,
|
||||
@ -290,6 +293,7 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
rows: [
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
rowId: 'id1',
|
||||
datasourceType: undefined,
|
||||
entry: 'line1',
|
||||
entryFieldIndex: 2,
|
||||
@ -318,6 +322,7 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
},
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
rowId: 'id2',
|
||||
datasourceType: undefined,
|
||||
entry: 'line2',
|
||||
entryFieldIndex: 2,
|
||||
@ -346,6 +351,7 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
},
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
rowId: 'id3',
|
||||
datasourceType: undefined,
|
||||
entry: 'line3',
|
||||
entryFieldIndex: 2,
|
||||
@ -925,4 +931,158 @@ describe('logSeriesToLogsModel should parse different logs-dataframe formats', (
|
||||
|
||||
expect(logSeriesToLogsModel(frames)).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it('should add rowId when id field exists)', () => {
|
||||
const frames: DataFrame[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{
|
||||
name: 'Time',
|
||||
type: FieldType.time,
|
||||
config: {},
|
||||
values: [1686142519756, 1686142520411],
|
||||
nanos: [641000, 0],
|
||||
},
|
||||
{
|
||||
name: 'Line',
|
||||
type: FieldType.string,
|
||||
config: {},
|
||||
values: ['line1', 'line2'],
|
||||
},
|
||||
{
|
||||
name: 'id',
|
||||
type: FieldType.string,
|
||||
config: {},
|
||||
values: ['id1', 'id2'],
|
||||
},
|
||||
],
|
||||
length: 2,
|
||||
},
|
||||
];
|
||||
|
||||
const expected = {
|
||||
hasUniqueLabels: false,
|
||||
meta: [],
|
||||
rows: [
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
rowId: 'id1',
|
||||
datasourceType: undefined,
|
||||
entry: 'line1',
|
||||
entryFieldIndex: 1,
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
logLevel: 'unknown',
|
||||
raw: 'line1',
|
||||
rowIndex: 0,
|
||||
searchWords: [],
|
||||
timeEpochMs: 1686142519756,
|
||||
timeEpochNs: '1686142519756641000',
|
||||
timeFromNow: 'mock:dateTimeFormatTimeAgo:2023-06-07T06:55:19-06:00',
|
||||
timeLocal: '2023-06-07 06:55:19',
|
||||
timeUtc: '2023-06-07 12:55:19',
|
||||
uid: 'A_id1',
|
||||
uniqueLabels: {},
|
||||
},
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
rowId: 'id2',
|
||||
datasourceType: undefined,
|
||||
entry: 'line2',
|
||||
entryFieldIndex: 1,
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
logLevel: 'unknown',
|
||||
raw: 'line2',
|
||||
rowIndex: 1,
|
||||
searchWords: [],
|
||||
timeEpochMs: 1686142520411,
|
||||
timeEpochNs: '1686142520411000000',
|
||||
timeFromNow: 'mock:dateTimeFormatTimeAgo:2023-06-07T06:55:20-06:00',
|
||||
timeLocal: '2023-06-07 06:55:20',
|
||||
timeUtc: '2023-06-07 12:55:20',
|
||||
uid: 'A_id2',
|
||||
uniqueLabels: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(logSeriesToLogsModel(frames)).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it('should not add rowId when id field does not exist)', () => {
|
||||
const frames: DataFrame[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{
|
||||
name: 'Time',
|
||||
type: FieldType.time,
|
||||
config: {},
|
||||
values: [1686142519756, 1686142520411],
|
||||
nanos: [641000, 0],
|
||||
},
|
||||
{
|
||||
name: 'Line',
|
||||
type: FieldType.string,
|
||||
config: {},
|
||||
values: ['line1', 'line2'],
|
||||
},
|
||||
],
|
||||
length: 2,
|
||||
},
|
||||
];
|
||||
|
||||
const expected = {
|
||||
hasUniqueLabels: false,
|
||||
meta: [],
|
||||
rows: [
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
datasourceType: undefined,
|
||||
entry: 'line1',
|
||||
entryFieldIndex: 1,
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
logLevel: 'unknown',
|
||||
raw: 'line1',
|
||||
rowIndex: 0,
|
||||
searchWords: [],
|
||||
timeEpochMs: 1686142519756,
|
||||
timeEpochNs: '1686142519756641000',
|
||||
timeFromNow: 'mock:dateTimeFormatTimeAgo:2023-06-07T06:55:19-06:00',
|
||||
timeLocal: '2023-06-07 06:55:19',
|
||||
timeUtc: '2023-06-07 12:55:19',
|
||||
uid: 'A_0',
|
||||
uniqueLabels: {},
|
||||
},
|
||||
{
|
||||
dataFrame: frames[0],
|
||||
datasourceType: undefined,
|
||||
entry: 'line2',
|
||||
entryFieldIndex: 1,
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {},
|
||||
logLevel: 'unknown',
|
||||
raw: 'line2',
|
||||
rowIndex: 1,
|
||||
searchWords: [],
|
||||
timeEpochMs: 1686142520411,
|
||||
timeEpochNs: '1686142520411000000',
|
||||
timeFromNow: 'mock:dateTimeFormatTimeAgo:2023-06-07T06:55:20-06:00',
|
||||
timeLocal: '2023-06-07 06:55:20',
|
||||
timeUtc: '2023-06-07 12:55:20',
|
||||
uid: 'A_1',
|
||||
uniqueLabels: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(logSeriesToLogsModel(frames)).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user