mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[SecuritySolution] Reveal data quality entry on the side-nav in serverless (#180816)
## Summary Test env serverless: https://p.elstc.co/paste/4JjGBmXv#Yogkkphe2hFyBRWIhsAZ3ivsvAve4TJkS2BzOqPQp3w ~ESS: https://p.elstc.co/paste/EsCQBV7V#P18h4HGLZkrPm66+KB2WVH6srVwDwXqVsciQDtI8vbc~ <img width="2559" alt="Screenshot 2024-04-17 at 13 48 08" src="558075d9
-f58a-458e-8006-7506ab432f5a"> <img width="2558" alt="Screenshot 2024-04-17 at 13 48 26" src="7010e3c0
-e0bb-4981-8a09-f478ed0fe018">5776c9c2
-2957-480e-8a2c-fdd687cdebc5 We can merge this PR once all the dependencies are merged. dependencies: 1. https://github.com/elastic/kibana/pull/179666 2. https://github.com/elastic/elasticsearch-serverless/pull/1482 3. ~https://github.com/elastic/elasticsearch-serverless/pull/1705~ 4. https://github.com/elastic/elasticsearch-serverless/pull/1753 Steps to verify: 0. Enable Docker 1. Start serverless ES with the commit where the stats api was merged: ``` yarn es serverless --projectType security --tag git-2eb724699bc0 ``` start Kibana ``` yarn serverless-security --no-base-path ``` 2. ~Endable the settings~ This step in no longer needed. ``` curl -u {YOUR_ELASTIC_USERNAME}:{ELASTIC_PASSWORD} -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d' { "persistent" : { "metering.index-info-task.enabled" : true } } ``` 3. In Kibana dev tool, add some testing data: ``` PUT my-test-index PUT my-test-index/_mapping { "properties": { "@timestamp": { "type": "date" }, "agent.type": { "type": "constant_keyword" }, "event.category": { "type": "constant_keyword" } } } POST my-test-index/_doc { "@timestamp": "2024-04-22T09:41:49.668Z", "host": { "name": "foo" }, "event": { "category": "an_invalid_category" }, "some.field": "this", "source": { "port": 90210, "ip": "10.1.2.3" } } POST my-test-index/_doc { "@timestamp": "2024-04-22T09:42:22.123Z", "host": { "name": "bar" }, "event": { "category": "an_invalid_category" }, "some.field": "space", "source": { "port": 867, "ip": "10.9.8.7" } } ``` 5. Go to /app/management/kibana/dataViews/dataView/security-solution-default , and add `my-test-*` to default index pattern 6. Go to `/app/security/data_quality` and verify that there's no doc size in the dashboard. Dashboard and treemap render correctly. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Sergi Massaneda <sergi.massaneda@elastic.co>
This commit is contained in:
parent
8aa7606a21
commit
98c596a5e1
9 changed files with 50 additions and 43 deletions
|
@ -270,7 +270,7 @@ const IndexPropertiesComponent: React.FC<Props> = ({
|
|||
};
|
||||
updatePatternRollup(updatedRollup);
|
||||
|
||||
if (indexId && requestTime != null && requestTime > 0 && partitionedFieldMetadata) {
|
||||
if (indexName && requestTime != null && requestTime > 0 && partitionedFieldMetadata) {
|
||||
const report = {
|
||||
batchId: uuidv4(),
|
||||
ecsVersion: EcsVersion,
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
getShowPagination,
|
||||
getSummaryTableColumns,
|
||||
getSummaryTableILMPhaseColumn,
|
||||
getSummaryTableSizeInBytesColumn,
|
||||
getToggleButtonId,
|
||||
IndexSummaryTableItem,
|
||||
} from './helpers';
|
||||
|
@ -468,6 +469,25 @@ describe('helpers', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getSummaryTableSizeInBytesColumn', () => {
|
||||
test('it returns the expected column configuration when `isILMAvailable` is true', () => {
|
||||
const column = getSummaryTableSizeInBytesColumn({
|
||||
isILMAvailable: true,
|
||||
formatBytes: jest.fn(),
|
||||
});
|
||||
expect(column.length).toEqual(1);
|
||||
expect(column[0].name).toEqual('Size');
|
||||
});
|
||||
|
||||
test('it returns an emptry array when `isILMAvailable` is false', () => {
|
||||
const column = getSummaryTableSizeInBytesColumn({
|
||||
isILMAvailable: false,
|
||||
formatBytes: jest.fn(),
|
||||
});
|
||||
expect(column.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ilmPhase column render()', () => {
|
||||
test('it renders the expected ilmPhase badge content', () => {
|
||||
const columns = getSummaryTableColumns({
|
||||
|
|
|
@ -121,23 +121,29 @@ export const getSummaryTableILMPhaseColumn = (
|
|||
: [];
|
||||
|
||||
export const getSummaryTableSizeInBytesColumn = ({
|
||||
isILMAvailable,
|
||||
formatBytes,
|
||||
}: {
|
||||
isILMAvailable: boolean;
|
||||
formatBytes: (value: number | undefined) => string;
|
||||
}): Array<EuiBasicTableColumn<IndexSummaryTableItem>> => [
|
||||
{
|
||||
field: 'sizeInBytes',
|
||||
name: i18n.SIZE,
|
||||
render: (_, { sizeInBytes }) =>
|
||||
Number.isInteger(sizeInBytes) ? (
|
||||
<EuiToolTip content={INDEX_SIZE_TOOLTIP}>
|
||||
<span data-test-subj="sizeInBytes">{formatBytes(sizeInBytes)}</span>
|
||||
</EuiToolTip>
|
||||
) : null,
|
||||
sortable: true,
|
||||
truncateText: false,
|
||||
},
|
||||
];
|
||||
}): Array<EuiBasicTableColumn<IndexSummaryTableItem>> =>
|
||||
isILMAvailable
|
||||
? [
|
||||
{
|
||||
field: 'sizeInBytes',
|
||||
name: i18n.SIZE,
|
||||
render: (_, { sizeInBytes }) =>
|
||||
Number.isInteger(sizeInBytes) ? (
|
||||
<EuiToolTip content={INDEX_SIZE_TOOLTIP}>
|
||||
<span data-test-subj="sizeInBytes">{formatBytes(sizeInBytes)}</span>
|
||||
</EuiToolTip>
|
||||
) : null,
|
||||
sortable: true,
|
||||
truncateText: false,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
export const getSummaryTableColumns = ({
|
||||
formatBytes,
|
||||
formatNumber,
|
||||
|
@ -247,18 +253,7 @@ export const getSummaryTableColumns = ({
|
|||
truncateText: false,
|
||||
},
|
||||
...getSummaryTableILMPhaseColumn(isILMAvailable),
|
||||
{
|
||||
field: 'sizeInBytes',
|
||||
name: i18n.SIZE,
|
||||
render: (_, { sizeInBytes }) =>
|
||||
Number.isInteger(sizeInBytes) ? (
|
||||
<EuiToolTip content={INDEX_SIZE_TOOLTIP}>
|
||||
<span data-test-subj="sizeInBytes">{formatBytes(sizeInBytes)}</span>
|
||||
</EuiToolTip>
|
||||
) : null,
|
||||
sortable: true,
|
||||
truncateText: false,
|
||||
},
|
||||
...getSummaryTableSizeInBytesColumn({ isILMAvailable, formatBytes }),
|
||||
{
|
||||
field: 'checkedAt',
|
||||
name: i18n.LAST_CHECK,
|
||||
|
|
|
@ -199,7 +199,7 @@ export interface MeteringIndicesStatsResponse {
|
|||
export type DataQualityIndexCheckedParams = DataQualityCheckAllCompletedParams & {
|
||||
errorCount?: number;
|
||||
ilmPhase?: string;
|
||||
indexId?: string;
|
||||
indexId?: string | null;
|
||||
indexName: string;
|
||||
sameFamilyFields?: string[];
|
||||
unallowedMappingFields?: string[];
|
||||
|
|
|
@ -185,10 +185,8 @@ export const useResultsRollup = ({ ilmPhases, patterns }: Props): UseResultsRoll
|
|||
const indexId = getIndexId({ indexName, stats });
|
||||
|
||||
if (
|
||||
indexId != null &&
|
||||
stats &&
|
||||
results &&
|
||||
ilmExplain &&
|
||||
requestTime != null &&
|
||||
requestTime > 0 &&
|
||||
partitionedFieldMetadata
|
||||
|
@ -197,7 +195,7 @@ export const useResultsRollup = ({ ilmPhases, patterns }: Props): UseResultsRoll
|
|||
batchId,
|
||||
ecsVersion: EcsVersion,
|
||||
errorCount: error ? 1 : 0,
|
||||
ilmPhase: getIlmPhase(ilmExplain[indexName], isILMAvailable),
|
||||
ilmPhase: getIlmPhase(ilmExplain?.[indexName], isILMAvailable),
|
||||
indexId,
|
||||
indexName,
|
||||
isCheckAll: true,
|
||||
|
|
|
@ -24,9 +24,9 @@ export const resultsFieldMap: FieldMap = {
|
|||
unallowedMappingFields: { type: 'keyword', required: true, array: true },
|
||||
unallowedValueFields: { type: 'keyword', required: true, array: true },
|
||||
sizeInBytes: { type: 'long', required: true },
|
||||
ilmPhase: { type: 'keyword', required: true },
|
||||
ilmPhase: { type: 'keyword', required: false },
|
||||
markdownComments: { type: 'text', required: true, array: true },
|
||||
ecsVersion: { type: 'keyword', required: true },
|
||||
indexId: { type: 'keyword', required: true },
|
||||
indexId: { type: 'keyword', required: false },
|
||||
error: { type: 'text', required: false },
|
||||
};
|
||||
|
|
|
@ -22,16 +22,16 @@ const ResultDocumentInterface = t.interface({
|
|||
unallowedMappingFields: t.array(t.string),
|
||||
unallowedValueFields: t.array(t.string),
|
||||
sizeInBytes: t.number,
|
||||
ilmPhase: t.string,
|
||||
markdownComments: t.array(t.string),
|
||||
ecsVersion: t.string,
|
||||
indexId: t.string,
|
||||
error: t.union([t.string, t.null]),
|
||||
});
|
||||
|
||||
const ResultDocumentOptional = t.partial({
|
||||
indexPattern: t.string,
|
||||
checkedBy: t.string,
|
||||
indexId: t.string,
|
||||
ilmPhase: t.string,
|
||||
});
|
||||
|
||||
export const ResultDocument = t.intersection([ResultDocumentInterface, ResultDocumentOptional]);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { SecurityPageName } from '@kbn/security-solution-navigation';
|
||||
import { cloneDeep, find, remove } from 'lodash';
|
||||
import { cloneDeep, remove } from 'lodash';
|
||||
import type { AppLinkItems, LinkItem } from '../../../common/links/types';
|
||||
import { createInvestigationsLinkFromTimeline } from './sections/investigations_links';
|
||||
import { mlAppLink } from './sections/ml_links';
|
||||
|
@ -26,12 +26,6 @@ export const solutionAppLinksSwitcher = (appLinks: AppLinkItems): AppLinkItems =
|
|||
solutionAppLinks.push(createInvestigationsLinkFromTimeline(timelineLinkItem));
|
||||
}
|
||||
|
||||
// Remove data quality dashboard link
|
||||
const dashboardLinkItem = find(solutionAppLinks, { id: SecurityPageName.dashboards });
|
||||
if (dashboardLinkItem && dashboardLinkItem.links) {
|
||||
remove(dashboardLinkItem.links, { id: SecurityPageName.dataQuality });
|
||||
}
|
||||
|
||||
// Remove manage link
|
||||
const [manageLinkItem] = remove(solutionAppLinks, { id: SecurityPageName.administration });
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import type { TelemetryEventTypes } from '../../constants';
|
|||
export type ReportDataQualityIndexCheckedParams = ReportDataQualityCheckAllCompletedParams & {
|
||||
errorCount?: number;
|
||||
ilmPhase?: string;
|
||||
indexId?: string;
|
||||
indexId?: string | null;
|
||||
indexName: string;
|
||||
sameFamilyFields?: string[];
|
||||
unallowedMappingFields?: string[];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue