Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[infra] Shorten IDs for ML jobs #168234

Merged
merged 34 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9714423
[infra] Shorten IDs for ML jobs (#47477)
miltonhultgren Oct 6, 2023
46b2593
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 9, 2023
5deea41
Use uuid.v5 instead of crypto, update description of created jobs
miltonhultgren Oct 9, 2023
f50f6d0
Merge branch 'main' of github.com:elastic/kibana into 47477-shorten-m…
miltonhultgren Oct 9, 2023
a4caae4
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 9, 2023
000750c
Add basic tests and test helpers
miltonhultgren Oct 11, 2023
b91a791
Merge branch 'main' of github.com:elastic/kibana into 47477-shorten-m…
miltonhultgren Oct 11, 2023
dd029b6
Add more tests
miltonhultgren Oct 12, 2023
1ae59e0
Merge branch 'main' of github.com:elastic/kibana into 47477-shorten-m…
miltonhultgren Oct 12, 2023
ae4de5a
Add more tests
miltonhultgren Oct 12, 2023
5e9bacc
Merge branch 'main' of github.com:elastic/kibana into 47477-shorten-m…
miltonhultgren Oct 12, 2023
b646a4d
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 13, 2023
9c5000e
Add comment about removing dashes from UUID
miltonhultgren Oct 13, 2023
341de2a
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 13, 2023
fb4b244
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 13, 2023
0e38a69
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 14, 2023
7955b11
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 16, 2023
6814fb7
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 18, 2023
c40e2d3
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Oct 19, 2023
bf2e37d
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 9, 2023
35a3a2e
Merge branch 'main' of github.com:elastic/kibana into 47477-shorten-m…
miltonhultgren Nov 13, 2023
afad134
Change import to refernece http_api/latest
miltonhultgren Nov 13, 2023
0b4e168
Remove unnecessary useMemo calls, use previous value in state update …
miltonhultgren Nov 13, 2023
a6baa5a
Shuffle around null checks
miltonhultgren Nov 13, 2023
4c02374
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 13, 2023
1e57ce5
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 13, 2023
f0f964f
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 14, 2023
6dff85c
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 14, 2023
359a5f0
Merge branch 'main' of github.com:elastic/kibana into 47477-shorten-m…
miltonhultgren Nov 15, 2023
0d2fb43
Move tests to new location
miltonhultgren Nov 15, 2023
73e6c31
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 15, 2023
cb25844
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 15, 2023
dc5ebb6
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 15, 2023
7b8ba6b
Merge branch 'main' into 47477-shorten-ml-job-ids
miltonhultgren Nov 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions x-pack/plugins/infra/common/http_api/latest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './log_alerts/v1';
export * from './log_analysis/results/v1';
export * from './log_analysis/validation/v1';
export * from './metrics_explorer_views/v1';
export * from './log_analysis/id_formats/v1/id_formats';
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import * as rt from 'io-ts';
import { logEntryRateJobTypeRT, logEntryCategoriesJobTypeRT } from '../../../../log_analysis';

export const idFormatRT = rt.union([rt.literal('legacy'), rt.literal('hashed')]);
export type IdFormat = rt.TypeOf<typeof idFormatRT>;

const jobTypeRT = rt.union([logEntryRateJobTypeRT, logEntryCategoriesJobTypeRT]);
export type JobType = rt.TypeOf<typeof jobTypeRT>;

export const idFormatByJobTypeRT = rt.record(jobTypeRT, idFormatRT);
export type IdFormatByJobType = rt.TypeOf<typeof idFormatByJobTypeRT>;

export const LOG_ANALYSIS_GET_ID_FORMATS = '/api/infra/log_analysis/id_formats';

export const getLogAnalysisIdFormatsRequestPayloadRT = rt.type({
data: rt.type({
logViewId: rt.string,
spaceId: rt.string,
}),
});

export type GetLogAnalysisIdFormatsRequestPayload = rt.TypeOf<
typeof getLogAnalysisIdFormatsRequestPayloadRT
>;

export const getLogAnalysisIdFormatsSuccessResponsePayloadRT = rt.type({
data: rt.record(rt.union([logEntryRateJobTypeRT, logEntryCategoriesJobTypeRT]), idFormatRT),
});

export type GetLogAnalysisIdFormatsSuccessResponsePayload = rt.TypeOf<
typeof getLogAnalysisIdFormatsSuccessResponsePayloadRT
>;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import * as rt from 'io-ts';

import { persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common';
import { idFormatByJobTypeRT } from '../../id_formats/v1/id_formats';
import { timeRangeRT, routeTimingMetadataRT } from '../../../shared';
import {
logEntryAnomalyRT,
Expand Down Expand Up @@ -54,6 +55,7 @@ export const getLogEntryAnomaliesRequestPayloadRT = rt.type({
rt.type({
// log view
logView: persistedLogViewReferenceRT,
idFormats: idFormatByJobTypeRT,
// the time range to fetch the log entry anomalies from
timeRange: timeRangeRT,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
timeRangeRT,
routeTimingMetadataRT,
} from '../../../shared';
import { idFormatByJobTypeRT } from '../../id_formats/v1/id_formats';

export const LOG_ANALYSIS_GET_LOG_ENTRY_ANOMALIES_DATASETS_PATH =
'/api/infra/log_analysis/results/log_entry_anomalies_datasets';
Expand All @@ -26,6 +27,7 @@ export const getLogEntryAnomaliesDatasetsRequestPayloadRT = rt.type({
data: rt.type({
// log view
logView: persistedLogViewReferenceRT,
idFormats: idFormatByJobTypeRT,
// the time range to fetch the anomalies datasets from
timeRange: timeRangeRT,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import * as rt from 'io-ts';

import { persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common';
import { idFormatRT } from '../../id_formats/v1/id_formats';
import {
badRequestErrorRT,
forbiddenErrorRT,
Expand Down Expand Up @@ -41,6 +42,7 @@ export const getLogEntryCategoriesRequestPayloadRT = rt.type({
categoryCount: rt.number,
// log view
logView: persistedLogViewReferenceRT,
idFormat: idFormatRT,
// the time range to fetch the categories from
timeRange: timeRangeRT,
// a list of histograms to create
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import * as rt from 'io-ts';

import { persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common';
import { idFormatRT } from '../../id_formats/v1/id_formats';
import {
badRequestErrorRT,
forbiddenErrorRT,
Expand All @@ -25,6 +26,7 @@ export const getLogEntryCategoryDatasetsRequestPayloadRT = rt.type({
data: rt.type({
// log view
logView: persistedLogViewReferenceRT,
idFormat: idFormatRT,
// the time range to fetch the category datasets from
timeRange: timeRangeRT,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { logEntryContextRT, persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common';
import * as rt from 'io-ts';
import { idFormatRT } from '../../id_formats/v1/id_formats';
import {
badRequestErrorRT,
forbiddenErrorRT,
Expand All @@ -29,6 +30,7 @@ export const getLogEntryCategoryExamplesRequestPayloadRT = rt.type({
exampleCount: rt.number,
// log view
logView: persistedLogViewReferenceRT,
idFormat: idFormatRT,
// the time range to fetch the category examples from
timeRange: timeRangeRT,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import * as rt from 'io-ts';
import { persistedLogViewReferenceRT } from '@kbn/logs-shared-plugin/common';
import { idFormatRT } from '../../id_formats/v1/id_formats';
import { logEntryExampleRT } from '../../../../log_analysis';
import {
badRequestErrorRT,
Expand All @@ -31,6 +32,7 @@ export const getLogEntryExamplesRequestPayloadRT = rt.type({
exampleCount: rt.number,
// logView
logView: persistedLogViewReferenceRT,
idFormat: idFormatRT,
// the time range to fetch the log rate examples from
timeRange: timeRangeRT,
}),
Expand Down
32 changes: 26 additions & 6 deletions x-pack/plugins/infra/common/log_analysis/job_parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,41 @@
*/

import * as rt from 'io-ts';
import { v5 } from 'uuid';
import { IdFormat, JobType } from '../http_api/latest';

export const bucketSpan = 900000;

export const categoriesMessageField = 'message';

export const partitionField = 'event.dataset';

export const getJobIdPrefix = (spaceId: string, sourceId: string) =>
`kibana-logs-ui-${spaceId}-${sourceId}-`;
const ID_NAMESPACE = 'f91b78c0-fdd3-425d-a4ba-4c028fe57e0f';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Hardcoded IDs in the codebase are a bit of a code smell in the long run, can we just comment on what it represents and why can we keep it hardcoded? Future ourselves will thank us for this 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto merge went through but to address your concern, I feel the variable name and it's usage is clear enough?

We need to generate a unique ID for each job so we use uuid.v5 which accepts a UUID to use as the namespace for the hashing and a name unique in that namespace.


export const getJobId = (spaceId: string, logViewId: string, jobType: string) =>
`${getJobIdPrefix(spaceId, logViewId)}${jobType}`;
export const getJobIdPrefix = (spaceId: string, sourceId: string, idFormat: IdFormat) => {
if (idFormat === 'legacy') {
return `kibana-logs-ui-${spaceId}-${sourceId}-`;
} else {
// A UUID is 36 characters but based on the ML job names for logs, our limit is 32 characters
// Thus we remove the 4 dashes
const uuid = v5(`${spaceId}-${sourceId}`, ID_NAMESPACE).replaceAll('-', '');
miltonhultgren marked this conversation as resolved.
Show resolved Hide resolved
return `logs-${uuid}-`;
}
};

export const getDatafeedId = (spaceId: string, logViewId: string, jobType: string) =>
`datafeed-${getJobId(spaceId, logViewId, jobType)}`;
export const getJobId = (
spaceId: string,
logViewId: string,
idFormat: IdFormat,
jobType: JobType
) => `${getJobIdPrefix(spaceId, logViewId, idFormat)}${jobType}`;

export const getDatafeedId = (
spaceId: string,
logViewId: string,
idFormat: IdFormat,
jobType: JobType
) => `datafeed-${getJobId(spaceId, logViewId, idFormat, jobType)}`;

export const datasetFilterRT = rt.union([
rt.strict({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
import * as rt from 'io-ts';
import { sortRT } from './log_analysis_results';

export const logEntryCategoriesJobTypeRT = rt.keyof({
'log-entry-categories-count': null,
});
export const logEntryCategoriesJobTypeRT = rt.literal('log-entry-categories-count');

export type LogEntryCategoriesJobType = rt.TypeOf<typeof logEntryCategoriesJobTypeRT>;

export const logEntryCategoriesJobTypes: LogEntryCategoriesJobType[] = [
'log-entry-categories-count',
];

export const logEntryCategoriesJobType: LogEntryCategoriesJobType = 'log-entry-categories-count';

export const logEntryCategoryDatasetRT = rt.type({
name: rt.string,
maximumAnomalyScore: rt.number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@

import * as rt from 'io-ts';

export const logEntryRateJobTypeRT = rt.keyof({
'log-entry-rate': null,
});
export const logEntryRateJobTypeRT = rt.literal('log-entry-rate');

export type LogEntryRateJobType = rt.TypeOf<typeof logEntryRateJobTypeRT>;

export const logEntryRateJobTypes: LogEntryRateJobType[] = ['log-entry-rate'];
export const logEntryRateJobType: LogEntryRateJobType = 'log-entry-rate';
export const logEntryRateJobTypes: LogEntryRateJobType[] = [logEntryRateJobType];
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useCallback } from 'react';
import { logEntryCategoriesJobType, logEntryRateJobType } from '../../../../../common/log_analysis';
import { useLogAnalysisCapabilitiesContext } from '../../../../containers/logs/log_analysis';
import {
logEntryCategoriesModule,
Expand Down Expand Up @@ -40,7 +41,7 @@ export const LogAnalysisModuleList: React.FC<{
<EuiFlexGroup>
<EuiFlexItem>
<LogAnalysisModuleListCard
jobId={logEntryRateJobIds['log-entry-rate']}
jobId={logEntryRateJobIds[logEntryRateJobType]}
hasSetupCapabilities={hasLogAnalysisSetupCapabilities}
moduleDescription={logEntryRateModule.moduleDescription}
moduleName={logEntryRateModule.moduleName}
Expand All @@ -50,7 +51,7 @@ export const LogAnalysisModuleList: React.FC<{
</EuiFlexItem>
<EuiFlexItem>
<LogAnalysisModuleListCard
jobId={logEntryCategoriesJobIds['log-entry-categories-count']}
jobId={logEntryCategoriesJobIds[logEntryCategoriesJobType]}
hasSetupCapabilities={hasLogAnalysisSetupCapabilities}
moduleDescription={logEntryCategoriesModule.moduleDescription}
moduleName={logEntryCategoriesModule.moduleName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ export const LogAnalysisSetupFlyout: React.FC<{
}

return (
<EuiFlyout aria-labelledby={FLYOUT_HEADING_ID} maxWidth={800} onClose={closeFlyout}>
<EuiFlyout
aria-labelledby={FLYOUT_HEADING_ID}
maxWidth={800}
onClose={closeFlyout}
data-test-subj="infraLogAnalysisSetupFlyout"
>
<EuiFlyoutHeader hasBorder>
<EuiTitle>
<h2 id={FLYOUT_HEADING_ID}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,30 @@
import * as rt from 'io-ts';
import type { HttpHandler } from '@kbn/core/public';

import { IdFormat, JobType } from '../../../../../common/http_api/latest';
import { getDatafeedId, getJobId } from '../../../../../common/log_analysis';
import { decodeOrThrow } from '../../../../../common/runtime_types';

interface DeleteJobsRequestArgs<JobType extends string> {
interface DeleteJobsRequestArgs<T extends JobType> {
spaceId: string;
logViewId: string;
jobTypes: JobType[];
idFormat: IdFormat;
jobTypes: T[];
}

export const callDeleteJobs = async <JobType extends string>(
requestArgs: DeleteJobsRequestArgs<JobType>,
export const callDeleteJobs = async <T extends JobType>(
requestArgs: DeleteJobsRequestArgs<T>,
fetch: HttpHandler
) => {
const { spaceId, logViewId, jobTypes } = requestArgs;
const { spaceId, logViewId, idFormat, jobTypes } = requestArgs;

// NOTE: Deleting the jobs via this API will delete the datafeeds at the same time
const deleteJobsResponse = await fetch('/internal/ml/jobs/delete_jobs', {
method: 'POST',
version: '1',
body: JSON.stringify(
deleteJobsRequestPayloadRT.encode({
jobIds: jobTypes.map((jobType) => getJobId(spaceId, logViewId, jobType)),
jobIds: jobTypes.map((jobType) => getJobId(spaceId, logViewId, idFormat, jobType)),
})
),
});
Expand All @@ -45,25 +47,28 @@ export const callGetJobDeletionTasks = async (fetch: HttpHandler) => {
return decodeOrThrow(getJobDeletionTasksResponsePayloadRT)(jobDeletionTasksResponse);
};

interface StopDatafeedsRequestArgs<JobType extends string> {
interface StopDatafeedsRequestArgs<T extends JobType> {
spaceId: string;
logViewId: string;
jobTypes: JobType[];
idFormat: IdFormat;
jobTypes: T[];
}

export const callStopDatafeeds = async <JobType extends string>(
requestArgs: StopDatafeedsRequestArgs<JobType>,
export const callStopDatafeeds = async <T extends JobType>(
requestArgs: StopDatafeedsRequestArgs<T>,
fetch: HttpHandler
) => {
const { spaceId, logViewId, jobTypes } = requestArgs;
const { spaceId, logViewId, idFormat, jobTypes } = requestArgs;

// Stop datafeed due to https://github.com/elastic/kibana/issues/44652
const stopDatafeedResponse = await fetch('/internal/ml/jobs/stop_datafeeds', {
method: 'POST',
version: '1',
body: JSON.stringify(
stopDatafeedsRequestPayloadRT.encode({
datafeedIds: jobTypes.map((jobType) => getDatafeedId(spaceId, logViewId, jobType)),
datafeedIds: jobTypes.map((jobType) =>
getDatafeedId(spaceId, logViewId, idFormat, jobType)
),
})
),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,28 @@
import * as rt from 'io-ts';
import type { HttpHandler } from '@kbn/core/public';

import { IdFormat, JobType } from '../../../../../common/http_api/latest';
import { getJobId, jobCustomSettingsRT } from '../../../../../common/log_analysis';
import { decodeOrThrow } from '../../../../../common/runtime_types';

interface RequestArgs<JobType extends string> {
interface RequestArgs<T extends JobType> {
spaceId: string;
logViewId: string;
jobTypes: JobType[];
idFormat: IdFormat;
jobTypes: T[];
}

export const callJobsSummaryAPI = async <JobType extends string>(
requestArgs: RequestArgs<JobType>,
export const callJobsSummaryAPI = async <T extends JobType>(
requestArgs: RequestArgs<T>,
fetch: HttpHandler
) => {
const { spaceId, logViewId, jobTypes } = requestArgs;
const { spaceId, logViewId, idFormat, jobTypes } = requestArgs;
const response = await fetch('/internal/ml/jobs/jobs_summary', {
method: 'POST',
version: '1',
body: JSON.stringify(
fetchJobStatusRequestPayloadRT.encode({
jobIds: jobTypes.map((jobType) => getJobId(spaceId, logViewId, jobType)),
jobIds: jobTypes.map((jobType) => getJobId(spaceId, logViewId, idFormat, jobType)),
})
),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const callSetupMlModuleAPI = async (requestArgs: RequestArgs, fetch: Http
start,
end,
indexPatternName: indexPattern,
prefix: getJobIdPrefix(spaceId, sourceId),
prefix: getJobIdPrefix(spaceId, sourceId, 'hashed'),
startDatafeed: true,
jobOverrides,
datafeedOverrides,
Expand Down
Loading
Loading