Skip to content

Commit

Permalink
[Logs UI] Display category in anomalies table (#88677)
Browse files Browse the repository at this point in the history
* Add category pattern to anomalies table
  • Loading branch information
Kerry350 authored Jan 27, 2021
1 parent da9ad2a commit 42a9490
Show file tree
Hide file tree
Showing 62 changed files with 394 additions and 313 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,17 @@
import * as rt from 'io-ts';

import { timeRangeRT, routeTimingMetadataRT } from '../../shared';
import {
logEntryAnomalyRT,
logEntryAnomalyDatasetsRT,
anomaliesSortRT,
paginationRT,
paginationCursorRT,
} from '../../../log_analysis';

export const LOG_ANALYSIS_GET_LOG_ENTRY_ANOMALIES_PATH =
'/api/infra/log_analysis/results/log_entry_anomalies';

// [Sort field value, tiebreaker value]
const paginationCursorRT = rt.tuple([
rt.union([rt.string, rt.number]),
rt.union([rt.string, rt.number]),
]);

export type PaginationCursor = rt.TypeOf<typeof paginationCursorRT>;

export const anomalyTypeRT = rt.keyof({
logRate: null,
logCategory: null,
});

export type AnomalyType = rt.TypeOf<typeof anomalyTypeRT>;

const logEntryAnomalyCommonFieldsRT = rt.type({
id: rt.string,
anomalyScore: rt.number,
dataset: rt.string,
typical: rt.number,
actual: rt.number,
type: anomalyTypeRT,
duration: rt.number,
startTime: rt.number,
jobId: rt.string,
});
const logEntrylogRateAnomalyRT = logEntryAnomalyCommonFieldsRT;
const logEntrylogCategoryAnomalyRT = rt.partial({
categoryId: rt.string,
});
const logEntryAnomalyRT = rt.intersection([
logEntryAnomalyCommonFieldsRT,
logEntrylogRateAnomalyRT,
logEntrylogCategoryAnomalyRT,
]);

export type LogEntryAnomaly = rt.TypeOf<typeof logEntryAnomalyRT>;

export const getLogEntryAnomaliesSuccessReponsePayloadRT = rt.intersection([
rt.type({
data: rt.intersection([
Expand Down Expand Up @@ -78,43 +47,6 @@ export type GetLogEntryAnomaliesSuccessResponsePayload = rt.TypeOf<
typeof getLogEntryAnomaliesSuccessReponsePayloadRT
>;

const sortOptionsRT = rt.keyof({
anomalyScore: null,
dataset: null,
startTime: null,
});

const sortDirectionsRT = rt.keyof({
asc: null,
desc: null,
});

const paginationPreviousPageCursorRT = rt.type({
searchBefore: paginationCursorRT,
});

const paginationNextPageCursorRT = rt.type({
searchAfter: paginationCursorRT,
});

const paginationRT = rt.intersection([
rt.type({
pageSize: rt.number,
}),
rt.partial({
cursor: rt.union([paginationPreviousPageCursorRT, paginationNextPageCursorRT]),
}),
]);

export type Pagination = rt.TypeOf<typeof paginationRT>;

const sortRT = rt.type({
field: sortOptionsRT,
direction: sortDirectionsRT,
});

export type Sort = rt.TypeOf<typeof sortRT>;

export const getLogEntryAnomaliesRequestPayloadRT = rt.type({
data: rt.intersection([
rt.type({
Expand All @@ -127,9 +59,9 @@ export const getLogEntryAnomaliesRequestPayloadRT = rt.type({
// Pagination properties
pagination: paginationRT,
// Sort properties
sort: sortRT,
sort: anomaliesSortRT,
// Dataset filters
datasets: rt.array(rt.string),
datasets: logEntryAnomalyDatasetsRT,
}),
]),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
routeTimingMetadataRT,
} from '../../shared';

import { logEntryCategoryRT, categoriesSortRT } from '../../../log_analysis';

export const LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH =
'/api/infra/log_analysis/results/log_entry_categories';

Expand All @@ -30,23 +32,6 @@ export type LogEntryCategoriesHistogramParameters = rt.TypeOf<
typeof logEntryCategoriesHistogramParametersRT
>;

const sortOptionsRT = rt.keyof({
maximumAnomalyScore: null,
logEntryCount: null,
});

const sortDirectionsRT = rt.keyof({
asc: null,
desc: null,
});

const categorySortRT = rt.type({
field: sortOptionsRT,
direction: sortDirectionsRT,
});

export type CategorySort = rt.TypeOf<typeof categorySortRT>;

export const getLogEntryCategoriesRequestPayloadRT = rt.type({
data: rt.intersection([
rt.type({
Expand All @@ -59,7 +44,7 @@ export const getLogEntryCategoriesRequestPayloadRT = rt.type({
// a list of histograms to create
histograms: rt.array(logEntryCategoriesHistogramParametersRT),
// the criteria to the categories by
sort: categorySortRT,
sort: categoriesSortRT,
}),
rt.partial({
// the datasets to filter for (optional, unfiltered if not present)
Expand All @@ -76,39 +61,6 @@ export type GetLogEntryCategoriesRequestPayload = rt.TypeOf<
* response
*/

export const logEntryCategoryHistogramBucketRT = rt.type({
startTime: rt.number,
bucketDuration: rt.number,
logEntryCount: rt.number,
});

export type LogEntryCategoryHistogramBucket = rt.TypeOf<typeof logEntryCategoryHistogramBucketRT>;

export const logEntryCategoryHistogramRT = rt.type({
histogramId: rt.string,
buckets: rt.array(logEntryCategoryHistogramBucketRT),
});

export type LogEntryCategoryHistogram = rt.TypeOf<typeof logEntryCategoryHistogramRT>;

export const logEntryCategoryDatasetRT = rt.type({
name: rt.string,
maximumAnomalyScore: rt.number,
});

export type LogEntryCategoryDataset = rt.TypeOf<typeof logEntryCategoryDatasetRT>;

export const logEntryCategoryRT = rt.type({
categoryId: rt.number,
datasets: rt.array(logEntryCategoryDatasetRT),
histograms: rt.array(logEntryCategoryHistogramRT),
logEntryCount: rt.number,
maximumAnomalyScore: rt.number,
regularExpression: rt.string,
});

export type LogEntryCategory = rt.TypeOf<typeof logEntryCategoryRT>;

export const getLogEntryCategoriesSuccessReponsePayloadRT = rt.intersection([
rt.type({
data: rt.type({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
timeRangeRT,
routeTimingMetadataRT,
} from '../../shared';
import { logEntryContextRT } from '../../log_entries';
import { logEntryContextRT } from '../../../log_entry';

export const LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORY_EXAMPLES_PATH =
'/api/infra/log_analysis/results/log_entry_category_examples';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import * as rt from 'io-ts';

import { logEntryExampleRT } from '../../../log_analysis';
import {
badRequestErrorRT,
forbiddenErrorRT,
Expand Down Expand Up @@ -46,16 +46,6 @@ export type GetLogEntryExamplesRequestPayload = rt.TypeOf<
* response
*/

const logEntryExampleRT = rt.type({
id: rt.string,
dataset: rt.string,
message: rt.string,
timestamp: rt.number,
tiebreaker: rt.number,
});

export type LogEntryExample = rt.TypeOf<typeof logEntryExampleRT>;

export const getLogEntryExamplesSuccessReponsePayloadRT = rt.intersection([
rt.type({
data: rt.type({
Expand Down
51 changes: 1 addition & 50 deletions x-pack/plugins/infra/common/http_api/log_entries/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
*/

import * as rt from 'io-ts';
import { logEntryCursorRT } from '../../log_entry';
import { jsonArrayRT } from '../../typed_json';
import { logEntryCursorRT, logEntryRT } from '../../log_entry';
import { logSourceColumnConfigurationRT } from '../log_sources';

export const LOG_ENTRIES_PATH = '/api/log_entries/entries';
Expand Down Expand Up @@ -52,54 +51,6 @@ export type LogEntriesAfterRequest = rt.TypeOf<typeof logEntriesAfterRequestRT>;
export type LogEntriesCenteredRequest = rt.TypeOf<typeof logEntriesCenteredRequestRT>;
export type LogEntriesRequest = rt.TypeOf<typeof logEntriesRequestRT>;

export const logMessageConstantPartRT = rt.type({
constant: rt.string,
});
export const logMessageFieldPartRT = rt.type({
field: rt.string,
value: jsonArrayRT,
highlights: rt.array(rt.string),
});

export const logMessagePartRT = rt.union([logMessageConstantPartRT, logMessageFieldPartRT]);

export const logTimestampColumnRT = rt.type({ columnId: rt.string, timestamp: rt.number });
export const logFieldColumnRT = rt.type({
columnId: rt.string,
field: rt.string,
value: jsonArrayRT,
highlights: rt.array(rt.string),
});
export const logMessageColumnRT = rt.type({
columnId: rt.string,
message: rt.array(logMessagePartRT),
});

export const logColumnRT = rt.union([logTimestampColumnRT, logFieldColumnRT, logMessageColumnRT]);

export const logEntryContextRT = rt.union([
rt.type({}),
rt.type({ 'container.id': rt.string }),
rt.type({ 'host.name': rt.string, 'log.file.path': rt.string }),
]);

export const logEntryRT = rt.type({
id: rt.string,
cursor: logEntryCursorRT,
columns: rt.array(logColumnRT),
context: logEntryContextRT,
});

export type LogMessageConstantPart = rt.TypeOf<typeof logMessageConstantPartRT>;
export type LogMessageFieldPart = rt.TypeOf<typeof logMessageFieldPartRT>;
export type LogMessagePart = rt.TypeOf<typeof logMessagePartRT>;
export type LogTimestampColumn = rt.TypeOf<typeof logTimestampColumnRT>;
export type LogFieldColumn = rt.TypeOf<typeof logFieldColumnRT>;
export type LogMessageColumn = rt.TypeOf<typeof logMessageColumnRT>;
export type LogColumn = rt.TypeOf<typeof logColumnRT>;
export type LogEntryContext = rt.TypeOf<typeof logEntryContextRT>;
export type LogEntry = rt.TypeOf<typeof logEntryRT>;

export const logEntriesResponseRT = rt.type({
data: rt.intersection([
rt.type({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
*/

import * as rt from 'io-ts';
import { logEntryCursorRT } from '../../log_entry';
import { logEntryCursorRT, logEntryRT } from '../../log_entry';
import {
logEntriesBaseRequestRT,
logEntriesBeforeRequestRT,
logEntriesAfterRequestRT,
logEntriesCenteredRequestRT,
logEntryRT,
} from './entries';

export const LOG_ENTRIES_HIGHLIGHTS_PATH = '/api/log_entries/highlights';
Expand Down
9 changes: 1 addition & 8 deletions x-pack/plugins/infra/common/http_api/shared/time_range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';

export const timeRangeRT = rt.type({
startTime: rt.number,
endTime: rt.number,
});

export type TimeRange = rt.TypeOf<typeof timeRangeRT>;
export * from '../../time/time_range';
2 changes: 2 additions & 0 deletions x-pack/plugins/infra/common/log_analysis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export * from './log_analysis_results';
export * from './log_entry_rate_analysis';
export * from './log_entry_categories_analysis';
export * from './job_parameters';
export * from './log_entry_anomalies';
export * from './log_entry_examples';
43 changes: 43 additions & 0 deletions x-pack/plugins/infra/common/log_analysis/log_analysis_results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';

export const ML_SEVERITY_SCORES = {
warning: 3,
minor: 25,
Expand Down Expand Up @@ -55,3 +57,44 @@ export const compareDatasetsByMaximumAnomalyScore = <
firstDataset: Dataset,
secondDataset: Dataset
) => firstDataset.maximumAnomalyScore - secondDataset.maximumAnomalyScore;

// Generic Sort

const sortDirectionsRT = rt.keyof({
asc: null,
desc: null,
});

export const sortRT = <Fields extends rt.Mixed>(fields: Fields) =>
rt.type({
field: fields,
direction: sortDirectionsRT,
});

// Pagination
// [Sort field value, tiebreaker value]
export const paginationCursorRT = rt.tuple([
rt.union([rt.string, rt.number]),
rt.union([rt.string, rt.number]),
]);

export type PaginationCursor = rt.TypeOf<typeof paginationCursorRT>;

const paginationPreviousPageCursorRT = rt.type({
searchBefore: paginationCursorRT,
});

const paginationNextPageCursorRT = rt.type({
searchAfter: paginationCursorRT,
});

export const paginationRT = rt.intersection([
rt.type({
pageSize: rt.number,
}),
rt.partial({
cursor: rt.union([paginationPreviousPageCursorRT, paginationNextPageCursorRT]),
}),
]);

export type Pagination = rt.TypeOf<typeof paginationRT>;
Loading

0 comments on commit 42a9490

Please sign in to comment.