Skip to content

Commit 8589217

Browse files
Kerry350weltenwortelasticmachine
committed
[Logs UI] Add category anomalies to anomalies page (#70982)
* Add category anomalies to anomalies page Co-authored-by: Felix Stürmer <weltenwort@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent e2d7e2c commit 8589217

34 files changed

Lines changed: 1764 additions & 892 deletions

x-pack/plugins/infra/common/http_api/log_analysis/results/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export * from './log_entry_categories';
88
export * from './log_entry_category_datasets';
99
export * from './log_entry_category_examples';
1010
export * from './log_entry_rate';
11-
export * from './log_entry_rate_examples';
11+
export * from './log_entry_examples';
12+
export * from './log_entry_anomalies';
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import * as rt from 'io-ts';
8+
9+
import { timeRangeRT, routeTimingMetadataRT } from '../../shared';
10+
11+
export const LOG_ANALYSIS_GET_LOG_ENTRY_ANOMALIES_PATH =
12+
'/api/infra/log_analysis/results/log_entry_anomalies';
13+
14+
// [Sort field value, tiebreaker value]
15+
const paginationCursorRT = rt.tuple([
16+
rt.union([rt.string, rt.number]),
17+
rt.union([rt.string, rt.number]),
18+
]);
19+
20+
export type PaginationCursor = rt.TypeOf<typeof paginationCursorRT>;
21+
22+
export const anomalyTypeRT = rt.keyof({
23+
logRate: null,
24+
logCategory: null,
25+
});
26+
27+
export type AnomalyType = rt.TypeOf<typeof anomalyTypeRT>;
28+
29+
const logEntryAnomalyCommonFieldsRT = rt.type({
30+
id: rt.string,
31+
anomalyScore: rt.number,
32+
dataset: rt.string,
33+
typical: rt.number,
34+
actual: rt.number,
35+
type: anomalyTypeRT,
36+
duration: rt.number,
37+
startTime: rt.number,
38+
jobId: rt.string,
39+
});
40+
const logEntrylogRateAnomalyRT = logEntryAnomalyCommonFieldsRT;
41+
const logEntrylogCategoryAnomalyRT = rt.partial({
42+
categoryId: rt.string,
43+
});
44+
const logEntryAnomalyRT = rt.intersection([
45+
logEntryAnomalyCommonFieldsRT,
46+
logEntrylogRateAnomalyRT,
47+
logEntrylogCategoryAnomalyRT,
48+
]);
49+
50+
export type LogEntryAnomaly = rt.TypeOf<typeof logEntryAnomalyRT>;
51+
52+
export const getLogEntryAnomaliesSuccessReponsePayloadRT = rt.intersection([
53+
rt.type({
54+
data: rt.intersection([
55+
rt.type({
56+
anomalies: rt.array(logEntryAnomalyRT),
57+
// Signifies there are more entries backwards or forwards. If this was a request
58+
// for a previous page, there are more previous pages, if this was a request for a next page,
59+
// there are more next pages.
60+
hasMoreEntries: rt.boolean,
61+
}),
62+
rt.partial({
63+
paginationCursors: rt.type({
64+
// The cursor to use to fetch the previous page
65+
previousPageCursor: paginationCursorRT,
66+
// The cursor to use to fetch the next page
67+
nextPageCursor: paginationCursorRT,
68+
}),
69+
}),
70+
]),
71+
}),
72+
rt.partial({
73+
timing: routeTimingMetadataRT,
74+
}),
75+
]);
76+
77+
export type GetLogEntryAnomaliesSuccessResponsePayload = rt.TypeOf<
78+
typeof getLogEntryAnomaliesSuccessReponsePayloadRT
79+
>;
80+
81+
const sortOptionsRT = rt.keyof({
82+
anomalyScore: null,
83+
dataset: null,
84+
startTime: null,
85+
});
86+
87+
const sortDirectionsRT = rt.keyof({
88+
asc: null,
89+
desc: null,
90+
});
91+
92+
const paginationPreviousPageCursorRT = rt.type({
93+
searchBefore: paginationCursorRT,
94+
});
95+
96+
const paginationNextPageCursorRT = rt.type({
97+
searchAfter: paginationCursorRT,
98+
});
99+
100+
const paginationRT = rt.intersection([
101+
rt.type({
102+
pageSize: rt.number,
103+
}),
104+
rt.partial({
105+
cursor: rt.union([paginationPreviousPageCursorRT, paginationNextPageCursorRT]),
106+
}),
107+
]);
108+
109+
export type Pagination = rt.TypeOf<typeof paginationRT>;
110+
111+
const sortRT = rt.type({
112+
field: sortOptionsRT,
113+
direction: sortDirectionsRT,
114+
});
115+
116+
export type Sort = rt.TypeOf<typeof sortRT>;
117+
118+
export const getLogEntryAnomaliesRequestPayloadRT = rt.type({
119+
data: rt.intersection([
120+
rt.type({
121+
// the ID of the source configuration
122+
sourceId: rt.string,
123+
// the time range to fetch the log entry anomalies from
124+
timeRange: timeRangeRT,
125+
}),
126+
rt.partial({
127+
// Pagination properties
128+
pagination: paginationRT,
129+
// Sort properties
130+
sort: sortRT,
131+
}),
132+
]),
133+
});
134+
135+
export type GetLogEntryAnomaliesRequestPayload = rt.TypeOf<
136+
typeof getLogEntryAnomaliesRequestPayloadRT
137+
>;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import * as rt from 'io-ts';
8+
9+
import {
10+
badRequestErrorRT,
11+
forbiddenErrorRT,
12+
timeRangeRT,
13+
routeTimingMetadataRT,
14+
} from '../../shared';
15+
16+
export const LOG_ANALYSIS_GET_LOG_ENTRY_RATE_EXAMPLES_PATH =
17+
'/api/infra/log_analysis/results/log_entry_examples';
18+
19+
/**
20+
* request
21+
*/
22+
23+
export const getLogEntryExamplesRequestPayloadRT = rt.type({
24+
data: rt.intersection([
25+
rt.type({
26+
// the dataset to fetch the log rate examples from
27+
dataset: rt.string,
28+
// the number of examples to fetch
29+
exampleCount: rt.number,
30+
// the id of the source configuration
31+
sourceId: rt.string,
32+
// the time range to fetch the log rate examples from
33+
timeRange: timeRangeRT,
34+
}),
35+
rt.partial({
36+
categoryId: rt.string,
37+
}),
38+
]),
39+
});
40+
41+
export type GetLogEntryExamplesRequestPayload = rt.TypeOf<
42+
typeof getLogEntryExamplesRequestPayloadRT
43+
>;
44+
45+
/**
46+
* response
47+
*/
48+
49+
const logEntryExampleRT = rt.type({
50+
id: rt.string,
51+
dataset: rt.string,
52+
message: rt.string,
53+
timestamp: rt.number,
54+
tiebreaker: rt.number,
55+
});
56+
57+
export type LogEntryExample = rt.TypeOf<typeof logEntryExampleRT>;
58+
59+
export const getLogEntryExamplesSuccessReponsePayloadRT = rt.intersection([
60+
rt.type({
61+
data: rt.type({
62+
examples: rt.array(logEntryExampleRT),
63+
}),
64+
}),
65+
rt.partial({
66+
timing: routeTimingMetadataRT,
67+
}),
68+
]);
69+
70+
export type GetLogEntryExamplesSuccessReponsePayload = rt.TypeOf<
71+
typeof getLogEntryExamplesSuccessReponsePayloadRT
72+
>;
73+
74+
export const getLogEntryExamplesResponsePayloadRT = rt.union([
75+
getLogEntryExamplesSuccessReponsePayloadRT,
76+
badRequestErrorRT,
77+
forbiddenErrorRT,
78+
]);
79+
80+
export type GetLogEntryExamplesResponsePayload = rt.TypeOf<
81+
typeof getLogEntryExamplesResponsePayloadRT
82+
>;

x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_rate_examples.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.

x-pack/plugins/infra/common/log_analysis/log_analysis_results.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export const formatAnomalyScore = (score: number) => {
4141
return Math.round(score);
4242
};
4343

44+
export const formatOneDecimalPlace = (number: number) => {
45+
return Math.round(number * 10) / 10;
46+
};
47+
4448
export const getFriendlyNameForPartitionId = (partitionId: string) => {
4549
return partitionId !== '' ? partitionId : 'unknown';
4650
};

0 commit comments

Comments
 (0)