Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
480a53b
[RCA] AI-assisted root cause analysis
dgieselaar Oct 22, 2024
7c4d7e0
Add log pattern table
dgieselaar Oct 22, 2024
d5a55e8
Change points
dgieselaar Oct 22, 2024
64d6557
Simplify SLO client
dgieselaar Oct 22, 2024
1158a39
[CI] Auto-commit changed files from 'node scripts/build_plugin_list_d…
kibanamachine Oct 22, 2024
113776f
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Oct 22, 2024
9db7634
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Oct 22, 2024
b34e36e
Merge branch 'llm-rca-kubecon' of github.com:dgieselaar/kibana into l…
dgieselaar Oct 23, 2024
35438eb
Fix quick checks
dgieselaar Oct 23, 2024
8b26417
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Oct 23, 2024
9ba32f4
Include alerts without grouping fields
dgieselaar Oct 23, 2024
04e2e96
Fix test config
maryam-saeidi Oct 24, 2024
f06779c
Merge branch 'main' into llm-rca-kubecon
maryam-saeidi Oct 25, 2024
ed0a10f
Fix test config
maryam-saeidi Oct 25, 2024
888a8e4
lock timerange to be investigation time range
benakansara Oct 25, 2024
fd6d246
Improve process
dgieselaar Oct 27, 2024
ff93d69
Merge branch 'llm-rca-kubecon' of github.com:dgieselaar/kibana into l…
dgieselaar Oct 27, 2024
44bc6d5
v2.1
dgieselaar Oct 31, 2024
924d2c3
Remove console.logging
dgieselaar Oct 31, 2024
f147223
Make sure to log all events after finishing
dgieselaar Oct 31, 2024
e07334b
Partition related entity extraction
dgieselaar Oct 31, 2024
96d938a
Order by score asc (lower is better)
dgieselaar Oct 31, 2024
f680c97
Include documents from knowledge base
dgieselaar Nov 1, 2024
65ec3bd
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Nov 2, 2024
a9df5d7
Move to separate package
dgieselaar Nov 2, 2024
a6ea3a3
Title for observations & some UI cleanup
dgieselaar Nov 2, 2024
64ab54d
Update CODEOWNERS
dgieselaar Nov 2, 2024
d58a50d
Fix references
dgieselaar Nov 2, 2024
69f75a3
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 3, 2024
88c36cf
Fix lint errors
dgieselaar Nov 3, 2024
515bf33
Fix type errors
dgieselaar Nov 3, 2024
d5641b2
Merge branch 'llm-rca-kubecon' of github.com:dgieselaar/kibana into l…
dgieselaar Nov 3, 2024
4269121
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Nov 3, 2024
029453a
Remove unused var, replace scan() with toArray()/map()
dgieselaar Nov 3, 2024
d2c7efc
Merge branch 'llm-rca-kubecon' of github.com:dgieselaar/kibana into l…
dgieselaar Nov 3, 2024
286e54c
Complete in background
dgieselaar Nov 5, 2024
325fc42
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Nov 5, 2024
43d7d43
Fix conflicts
dgieselaar Nov 8, 2024
c3b37e3
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Nov 8, 2024
a9eeaf7
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Nov 27, 2024
4372088
Type checks
dgieselaar Nov 27, 2024
cc7254a
Tests for observable_into_event_source_stream
dgieselaar Nov 27, 2024
6c99e3d
Update tests
dgieselaar Nov 27, 2024
609cf95
[CI] Auto-commit changed files from 'node scripts/capture_oas_snapsho…
kibanamachine Nov 28, 2024
5d9b9c0
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Dec 9, 2024
8fac3c2
Remove unused translations
dgieselaar Dec 9, 2024
d0c5f6e
Merge branch 'llm-rca-kubecon' of github.com:dgieselaar/kibana into l…
dgieselaar Dec 9, 2024
ed0518e
Clean up route handler
dgieselaar Dec 9, 2024
b76a428
Remove unused file
dgieselaar Dec 9, 2024
68343a9
Use random_sampler
dgieselaar Dec 9, 2024
9bd05c2
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Dec 9, 2024
5c91822
Fix references
dgieselaar Dec 9, 2024
1f7a705
Merge branch 'llm-rca-kubecon' of github.com:dgieselaar/kibana into l…
dgieselaar Dec 9, 2024
7bbfd78
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Dec 10, 2024
f3c9af2
Import categorizationAnalyzer directly
dgieselaar Dec 10, 2024
5dfa41f
Don't export categorizationAnalyzer
dgieselaar Dec 10, 2024
68cb38d
Add llmTasks to dependencies
dgieselaar Dec 10, 2024
b953c20
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Dec 10, 2024
3f751ea
Fix tests
dgieselaar Dec 10, 2024
cbdb129
Reset limits for aiops
dgieselaar Dec 10, 2024
bd80cd3
Merge branch 'main' of github.com:elastic/kibana into llm-rca-kubecon
dgieselaar Dec 10, 2024
ba5d761
Delete unused files
dgieselaar Dec 10, 2024
b06d3f5
Re-skip tests in Obs AI Assistant
dgieselaar Dec 10, 2024
62252d0
Add tests for retry.onValidationError
dgieselaar Dec 11, 2024
75068c9
Clarify complexity
dgieselaar Dec 11, 2024
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
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,7 @@ module.exports = {
'x-pack/plugins/observability_solution/exploratory_view/**/*.{js,mjs,ts,tsx}',
'x-pack/plugins/observability_solution/ux/**/*.{js,mjs,ts,tsx}',
'x-pack/plugins/observability_solution/slo/**/*.{js,mjs,ts,tsx}',
'x-pack/packages/observability/**/*.{js,mjs,ts,tsx}',
],
rules: {
'no-console': ['warn', { allow: ['error'] }],
Expand All @@ -938,6 +939,7 @@ module.exports = {
'x-pack/plugins/observability_solution/observability/**/*.stories.*',
'x-pack/plugins/observability_solution/exploratory_view/**/*.stories.*',
'x-pack/plugins/observability_solution/slo/**/*.stories.*',
'x-pack/packages/observability/**/*.{js,mjs,ts,tsx}',
],
rules: {
'react/function-component-definition': [
Expand Down
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,8 @@ x-pack/packages/observability/alerting_rule_utils @elastic/obs-ux-management-tea
x-pack/packages/observability/alerting_test_data @elastic/obs-ux-management-team
x-pack/packages/observability/get_padded_alert_time_range_util @elastic/obs-ux-management-team
x-pack/packages/observability/logs_overview @elastic/obs-ux-logs-team
x-pack/packages/observability/observability_ai/observability_ai_common @elastic/obs-ai-assistant
x-pack/packages/observability/observability_ai/observability_ai_server @elastic/obs-ai-assistant
x-pack/packages/observability/observability_utils/observability_utils_browser @elastic/observability-ui
x-pack/packages/observability/observability_utils/observability_utils_common @elastic/observability-ui
x-pack/packages/observability/observability_utils/observability_utils_server @elastic/observability-ui
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,8 @@
"@kbn/observability-ai-assistant-app-plugin": "link:x-pack/plugins/observability_solution/observability_ai_assistant_app",
"@kbn/observability-ai-assistant-management-plugin": "link:x-pack/plugins/observability_solution/observability_ai_assistant_management",
"@kbn/observability-ai-assistant-plugin": "link:x-pack/plugins/observability_solution/observability_ai_assistant",
"@kbn/observability-ai-common": "link:x-pack/packages/observability/observability_ai/observability_ai_common",
"@kbn/observability-ai-server": "link:x-pack/packages/observability/observability_ai/observability_ai_server",
"@kbn/observability-alert-details": "link:x-pack/packages/observability/alert_details",
"@kbn/observability-alerting-rule-utils": "link:x-pack/packages/observability/alerting_rule_utils",
"@kbn/observability-alerting-test-data": "link:x-pack/packages/observability/alerting_test_data",
Expand Down Expand Up @@ -1145,6 +1147,7 @@
"fnv-plus": "^1.3.1",
"formik": "^2.4.6",
"fp-ts": "^2.3.1",
"fuse.js": "^7.0.0",
"get-port": "^5.0.0",
"getopts": "^2.2.5",
"getos": "^3.1.0",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-es-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type {
SearchHit,
ESSearchResponse,
ESSearchRequest,
ESSearchRequestWithoutBody,
ESSourceOptions,
InferSearchResponseOf,
AggregationResultOf,
Expand Down
2 changes: 2 additions & 0 deletions packages/kbn-es-types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import * as estypesWithoutBody from '@elastic/elasticsearch/lib/api/types';
import type {
Field,
QueryDslFieldAndFormat,
Expand All @@ -26,6 +27,7 @@ import {

export type ESFilter = estypes.QueryDslQueryContainer;
export type ESSearchRequest = estypes.SearchRequest;
export type ESSearchRequestWithoutBody = estypesWithoutBody.SearchRequest;
Comment on lines 29 to +30
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: I'd love it if we could start highlighting that body is deprecated:

Suggested change
export type ESSearchRequest = estypes.SearchRequest;
export type ESSearchRequestWithoutBody = estypesWithoutBody.SearchRequest;
/** @deprecated Use ESSearchRequestWithoutBody instead */
export type ESSearchRequest = estypes.SearchRequest;
export type ESSearchRequestWithoutBody = estypesWithoutBody.SearchRequest;

In any case, I think this is a good change... as we'll be able to progressively migrate consumers of each type.

export type AggregationOptionsByType = Required<estypes.AggregationsAggregationContainer>;

// Typings for Elasticsearch queries and aggregations. These are intended to be
Expand Down
21 changes: 8 additions & 13 deletions packages/kbn-es-types/src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,15 @@ type InvalidAggregationRequest = unknown;
// Union keys are not included in keyof, but extends iterates over the types in a union.
type ValidAggregationKeysOf<T extends Record<string, any>> = T extends T ? keyof T : never;

type KeyOfSource<T> = Record<
keyof T,
(T extends Record<string, { terms: { missing_bucket: true } }> ? null : never) | string | number
>;
type KeyOfSource<T> = {
[key in keyof T]:
| (T[key] extends Record<string, { terms: { missing_bucket: true } }> ? null : never)
| string
| number;
};

type KeysOfSources<T extends any[]> = T extends [any]
? KeyOfSource<T[0]>
: T extends [any, any]
? KeyOfSource<T[0]> & KeyOfSource<T[1]>
: T extends [any, any, any]
? KeyOfSource<T[0]> & KeyOfSource<T[1]> & KeyOfSource<T[2]>
: T extends [any, any, any, any]
? KeyOfSource<T[0]> & KeyOfSource<T[1]> & KeyOfSource<T[2]> & KeyOfSource<T[3]>
: Record<string, null | string | number>;
// convert to intersection to be able to get all the keys
type KeysOfSources<T extends any[]> = UnionToIntersection<KeyOfSource<ValuesType<Pick<T, number>>>>;

type CompositeKeysOf<TAggregationContainer extends AggregationsAggregationContainer> =
TAggregationContainer extends {
Expand Down
3 changes: 3 additions & 0 deletions packages/kbn-investigation-shared/src/rest_specs/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const updateInvestigationParamsSchema = z.object({
}),
tags: z.array(z.string()),
externalIncidentUrl: z.string().nullable(),
rootCauseAnalysis: z.object({
events: z.array(z.any()),
}),
})
.partial(),
});
Expand Down
5 changes: 5 additions & 0 deletions packages/kbn-investigation-shared/src/schema/investigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ const investigationSchema = z.object({
notes: z.array(investigationNoteSchema),
items: z.array(investigationItemSchema),
externalIncidentUrl: z.string().nullable(),
rootCauseAnalysis: z
.object({
events: z.array(z.any()),
})
.optional(),
});

type Status = z.infer<typeof statusSchema>;
Expand Down
9 changes: 8 additions & 1 deletion packages/kbn-server-route-repository/src/register_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,15 @@ export function registerRoutes<TDependencies extends Record<string, any>>({
if (isKibanaResponse(result)) {
return result;
} else if (isObservable(result)) {
const controller = new AbortController();
request.events.aborted$.subscribe(() => {
controller.abort();
});
return response.ok({
body: observableIntoEventSourceStream(result as Observable<ServerSentEvent>),
body: observableIntoEventSourceStream(result as Observable<ServerSentEvent>, {
logger,
signal: controller.signal,
}),
});
} else {
const body = result || {};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { Logger } from '@kbn/logging';
import { observableIntoEventSourceStream } from './observable_into_event_source_stream';
import { PassThrough } from 'node:stream';
import { Subject } from 'rxjs';
import { ServerSentEvent, ServerSentEventType } from '@kbn/sse-utils/src/events';
import {
ServerSentEventErrorCode,
createSSEInternalError,
createSSERequestError,
} from '@kbn/sse-utils/src/errors';

describe('observableIntoEventSourceStream', () => {
let logger: jest.Mocked<Logger>;

let controller: AbortController;

let stream: PassThrough;
let source$: Subject<ServerSentEvent>;

let data: string[];

beforeEach(() => {
jest.useFakeTimers();
logger = {
debug: jest.fn(),
error: jest.fn(),
} as unknown as jest.Mocked<Logger>;

controller = new AbortController();
source$ = new Subject();
data = [];

stream = observableIntoEventSourceStream(source$, { logger, signal: controller.signal });
stream.on('data', (chunk) => {
data.push(chunk.toString());
});
});

afterEach(() => {
jest.clearAllTimers();
});

it('writes events into the stream in SSE format', () => {
source$.next({ type: ServerSentEventType.data, data: { foo: 'bar' } });
source$.complete();

jest.runAllTimers();

expect(data).toEqual(['event: data\ndata: {"data":{"foo":"bar"}}\n\n']);
});

it('handles SSE errors', () => {
const sseError = createSSEInternalError('Invalid input');

source$.error(sseError);

jest.runAllTimers();

expect(logger.error).toHaveBeenCalledWith(sseError);
expect(logger.debug).toHaveBeenCalled();
const debugFn = logger.debug.mock.calls[0][0] as () => string;
const loggedError = JSON.parse(debugFn());
expect(loggedError).toEqual({
type: 'error',
error: {
code: ServerSentEventErrorCode.internalError,
message: 'Invalid input',
meta: {},
},
});

expect(data).toEqual([
`event: error\ndata: ${JSON.stringify({
error: {
code: ServerSentEventErrorCode.internalError,
message: 'Invalid input',
meta: {},
},
})}\n\n`,
]);
});

it('handles SSE errors with metadata', () => {
const sseError = createSSERequestError('Invalid request', 400);

source$.error(sseError);

jest.runAllTimers();

expect(logger.error).toHaveBeenCalledWith(sseError);
expect(logger.debug).toHaveBeenCalled();
const debugFn = logger.debug.mock.calls[0][0] as () => string;
const loggedError = JSON.parse(debugFn());
expect(loggedError).toEqual({
type: 'error',
error: {
code: ServerSentEventErrorCode.requestError,
message: 'Invalid request',
meta: {
status: 400,
},
},
});

expect(data).toEqual([
`event: error\ndata: ${JSON.stringify({
error: {
code: ServerSentEventErrorCode.requestError,
message: 'Invalid request',
meta: {
status: 400,
},
},
})}\n\n`,
]);
});

it('handles non-SSE errors', () => {
const error = new Error('Non-SSE Error');

source$.error(error);

jest.runAllTimers();

expect(logger.error).toHaveBeenCalledWith(error);
expect(data).toEqual([
`event: error\ndata: ${JSON.stringify({
error: {
code: ServerSentEventErrorCode.internalError,
message: 'Non-SSE Error',
},
})}\n\n`,
]);
});

it('should send keep-alive comments every 10 seconds', () => {
jest.advanceTimersByTime(10000);
expect(data).toContain(': keep-alive');

jest.advanceTimersByTime(10000);
expect(data.filter((d) => d === ': keep-alive')).toHaveLength(2);
});

describe('without fake timers', () => {
beforeEach(() => {
jest.useFakeTimers({ doNotFake: ['nextTick'] });
});

it('should end the stream when the observable completes', async () => {
jest.useFakeTimers({ doNotFake: ['nextTick'] });

const endSpy = jest.fn();
stream.on('end', endSpy);

source$.complete();

await new Promise((resolve) => process.nextTick(resolve));

expect(endSpy).toHaveBeenCalled();
});

it('should end stream when signal is aborted', async () => {
const endSpy = jest.fn();
stream.on('end', endSpy);

// Emit some data
source$.next({ type: ServerSentEventType.data, data: { initial: 'data' } });

// Abort the signal
controller.abort();

// Emit more data after abort
source$.next({ type: ServerSentEventType.data, data: { after: 'abort' } });

await new Promise((resolve) => process.nextTick(resolve));

expect(endSpy).toHaveBeenCalled();

// Data after abort should not be received
expect(data).toEqual([
`event: data\ndata: ${JSON.stringify({ data: { initial: 'data' } })}\n\n`,
]);
});

afterEach(() => {
jest.useFakeTimers();
});
});
});
Loading