mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[CSV] Include custom field label in CSV reports (#181565)
- Closes https://github.com/elastic/kibana/issues/100374 ## Summary This PR adds `field.customLabel` to CSV reports (column names) if available. Before: <img width="800" alt="Screenshot 2024-04-24 at 15 16 45" src="870c9146
-dd3a-4cc6-a12f-f67fbd7196f5"> After: <img width="800" alt="Screenshot 2024-04-24 at 15 17 04" src="7f870899
-71a2-42e7-ade4-d92acca9b96a"> ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
41fd6432be
commit
43311754f6
4 changed files with 41 additions and 16 deletions
|
@ -271,8 +271,8 @@ exports[`CsvGenerator fields from job.searchSource.getFields() (7.12 generated)
|
|||
`;
|
||||
|
||||
exports[`CsvGenerator formats a search result to CSV content 1`] = `
|
||||
"date,ip,message
|
||||
\\"2020-12-31T00:14:28.000Z\\",\\"110.135.176.89\\",\\"This is a great message!\\"
|
||||
"date,ip,message,\\"bytes_custom_label (bytes)\\"
|
||||
\\"2020-12-31T00:14:28.000Z\\",\\"110.135.176.89\\",\\"This is a great message!\\",100
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ import {
|
|||
savedObjectsClientMock,
|
||||
uiSettingsServiceMock,
|
||||
} from '@kbn/core/server/mocks';
|
||||
import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub';
|
||||
import { stubLogstashFieldSpecMap } from '@kbn/data-views-plugin/common/field.stub';
|
||||
import { ISearchClient, ISearchStartSearchSource } from '@kbn/data-plugin/common';
|
||||
import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks';
|
||||
import type { IScopedSearchClient } from '@kbn/data-plugin/server';
|
||||
|
@ -132,20 +134,31 @@ describe('CsvGenerator', () => {
|
|||
|
||||
mockConfig = getMockConfig();
|
||||
|
||||
const dataView = createStubDataView({
|
||||
spec: {
|
||||
id: 'test',
|
||||
title: 'logstash-*',
|
||||
fields: {
|
||||
...stubLogstashFieldSpecMap,
|
||||
bytes: {
|
||||
...stubLogstashFieldSpecMap.bytes,
|
||||
customLabel: 'bytes_custom_label',
|
||||
},
|
||||
},
|
||||
},
|
||||
opts: {
|
||||
metaFields: ['_id', '_index', '_type', '_score'],
|
||||
},
|
||||
});
|
||||
|
||||
dataView.getFormatterForField = jest.fn();
|
||||
|
||||
searchSourceMock.getField = jest.fn((key: string) => {
|
||||
switch (key) {
|
||||
case 'pit':
|
||||
return { id: mockCursorId };
|
||||
case 'index':
|
||||
return {
|
||||
fields: {
|
||||
getByName: jest.fn(() => []),
|
||||
getByType: jest.fn(() => []),
|
||||
},
|
||||
metaFields: ['_id', '_index', '_type', '_score'],
|
||||
getFormatterForField: jest.fn(),
|
||||
getIndexPattern: () => 'logstash-*',
|
||||
};
|
||||
return dataView;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -184,13 +197,14 @@ describe('CsvGenerator', () => {
|
|||
date: `["2020-12-31T00:14:28.000Z"]`,
|
||||
ip: `["110.135.176.89"]`,
|
||||
message: `["This is a great message!"]`,
|
||||
bytes: `[100]`,
|
||||
},
|
||||
} as unknown as estypes.SearchHit,
|
||||
]),
|
||||
})
|
||||
);
|
||||
const generateCsv = new CsvGenerator(
|
||||
createMockJob({ columns: ['date', 'ip', 'message'] }),
|
||||
createMockJob({ columns: ['date', 'ip', 'message', 'bytes'] }),
|
||||
mockConfig,
|
||||
mockTaskInstanceFields,
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@ import type { Writable } from 'stream';
|
|||
|
||||
import { errors as esErrors, estypes } from '@elastic/elasticsearch';
|
||||
import type { IScopedClusterClient, IUiSettingsClient, Logger } from '@kbn/core/server';
|
||||
import type { ISearchClient, ISearchStartSearchSource } from '@kbn/data-plugin/common';
|
||||
import type { DataView, ISearchClient, ISearchStartSearchSource } from '@kbn/data-plugin/common';
|
||||
import { cellHasFormulas, tabifyDocs } from '@kbn/data-plugin/common';
|
||||
import type { Datatable } from '@kbn/expressions-plugin/server';
|
||||
import type {
|
||||
|
@ -146,11 +146,21 @@ export class CsvGenerator {
|
|||
private generateHeader(
|
||||
columns: Set<string>,
|
||||
builder: MaxSizeStringBuilder,
|
||||
settings: CsvExportSettings
|
||||
settings: CsvExportSettings,
|
||||
dataView: DataView
|
||||
) {
|
||||
this.logger.debug(`Building CSV header row`);
|
||||
const header =
|
||||
Array.from(columns).map(this.escapeValues(settings)).join(settings.separator) + '\n';
|
||||
Array.from(columns)
|
||||
.map((column) => {
|
||||
const field = dataView?.fields.getByName(column);
|
||||
if (field && field.customLabel && field.customLabel !== column) {
|
||||
return `${field.customLabel} (${column})`;
|
||||
}
|
||||
return column;
|
||||
})
|
||||
.map(this.escapeValues(settings))
|
||||
.join(settings.separator) + '\n';
|
||||
|
||||
if (!builder.tryAppend(header)) {
|
||||
return {
|
||||
|
@ -364,7 +374,7 @@ export class CsvGenerator {
|
|||
|
||||
if (first) {
|
||||
first = false;
|
||||
this.generateHeader(columns, builder, settings);
|
||||
this.generateHeader(columns, builder, settings, index);
|
||||
}
|
||||
|
||||
if (table.rows.length < 1) {
|
||||
|
|
|
@ -29,5 +29,6 @@
|
|||
"@kbn/es-query",
|
||||
"@kbn/es-types",
|
||||
"@kbn/esql-utils",
|
||||
"@kbn/data-views-plugin",
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue