Skip to content

Commit 101cdda

Browse files
authored
[o11y AI] Refactor tools (elastic#247070)
Refactors the o11y tools to a consistent separation between tool definition and handling logic. Previously, tools mixed these and used inconsistent naming conventions, making it harder to navigate (both for humans and LLMs) New folder structure - `tool.ts`: Contains the tool schema, metadata and registration - `handler.ts`: Encapsulates the business logic (mostly data retrieval and data formatting) **Advantages** - This improves maintainability and readability. - This will enable us to consume tools from AI insight routes by calling the tool handler directly (bypassing the tool wrapper)
1 parent b1230f0 commit 101cdda

File tree

27 files changed

+1037
-684
lines changed

27 files changed

+1037
-684
lines changed

x-pack/solutions/observability/plugins/observability_agent_builder/server/data_registry/data_registry_types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ interface ServiceSummary {
3838
deployments: Array<{ '@timestamp': string }>;
3939
}
4040

41-
interface APMDownstreamDependency {
41+
export interface APMDownstreamDependency {
4242
'service.name'?: string | undefined;
4343
'span.destination.service.resource': string;
4444
'span.type'?: string | undefined;
@@ -86,7 +86,7 @@ interface APMTransaction {
8686
};
8787
}
8888

89-
interface ServicesItemsItem {
89+
export interface ServicesItemsItem {
9090
serviceName: string;
9191
transactionType?: string;
9292
environments?: string[];
@@ -129,7 +129,7 @@ interface InfraEntityMetadata {
129129
value: string | number | null;
130130
}
131131

132-
interface InfraEntityMetricsItem {
132+
export interface InfraEntityMetricsItem {
133133
name: string;
134134
metrics: InfraEntityMetrics[];
135135
metadata: InfraEntityMetadata[];

x-pack/solutions/observability/plugins/observability_agent_builder/server/routes/ai_insights/apm_error/fetch_apm_error_context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type {
1616
ObservabilityAgentBuilderPluginStart,
1717
ObservabilityAgentBuilderPluginStartDependencies,
1818
} from '../../../types';
19-
import { getFilteredLogCategories } from '../../../tools/get_log_categories/get_log_categories';
19+
import { getFilteredLogCategories } from '../../../tools/get_log_categories/handler';
2020
import { getLogsIndices } from '../../../utils/get_logs_indices';
2121
import { getApmIndices } from '../../../utils/get_apm_indices';
2222
import { parseDatemath } from '../../../utils/time';
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { omit } from 'lodash';
9+
import type { CoreSetup, KibanaRequest, Logger } from '@kbn/core/server';
10+
import {
11+
ALERT_STATUS,
12+
ALERT_STATUS_ACTIVE,
13+
AlertConsumers,
14+
} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names';
15+
import { OBSERVABILITY_RULE_TYPE_IDS_WITH_SUPPORTED_STACK_RULE_TYPES } from '@kbn/observability-shared-plugin/common';
16+
import type {
17+
ObservabilityAgentBuilderPluginStart,
18+
ObservabilityAgentBuilderPluginStartDependencies,
19+
} from '../../types';
20+
import { getRelevantAlertFields } from './get_relevant_alert_fields';
21+
import { getHitsTotal } from '../../utils/get_hits_total';
22+
import { kqlFilter as buildKqlFilter } from '../../utils/dsl_filters';
23+
import { getDefaultConnectorId } from '../../utils/get_default_connector_id';
24+
25+
const OMITTED_ALERT_FIELDS = [
26+
'event.action',
27+
'event.kind',
28+
'kibana.alert.rule.execution.uuid',
29+
'kibana.alert.rule.revision',
30+
'kibana.alert.rule.tags',
31+
'kibana.alert.rule.uuid',
32+
'kibana.alert.workflow_status',
33+
'kibana.space_ids',
34+
'kibana.alert.time_range',
35+
'kibana.version',
36+
] as const;
37+
38+
export async function getToolHandler({
39+
core,
40+
request,
41+
logger,
42+
start,
43+
end,
44+
query,
45+
kqlFilter,
46+
includeRecovered,
47+
}: {
48+
core: CoreSetup<
49+
ObservabilityAgentBuilderPluginStartDependencies,
50+
ObservabilityAgentBuilderPluginStart
51+
>;
52+
request: KibanaRequest;
53+
logger: Logger;
54+
start: string;
55+
end: string;
56+
query: string;
57+
kqlFilter?: string;
58+
includeRecovered?: boolean;
59+
}) {
60+
const [coreStart, pluginStart] = await core.getStartServices();
61+
const { inference, ruleRegistry } = pluginStart;
62+
63+
const alertsClient = await ruleRegistry.getRacClientWithRequest(request);
64+
const connectorId = await getDefaultConnectorId({
65+
coreStart,
66+
inference,
67+
request,
68+
logger,
69+
});
70+
71+
const boundInferenceClient = inference.getClient({
72+
request,
73+
bindTo: { connectorId },
74+
});
75+
76+
const selectedFields = await getRelevantAlertFields({
77+
coreStart,
78+
pluginStart,
79+
request,
80+
inferenceClient: boundInferenceClient,
81+
logger,
82+
query,
83+
});
84+
85+
const response = await alertsClient.find({
86+
ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS_WITH_SUPPORTED_STACK_RULE_TYPES,
87+
consumers: [
88+
AlertConsumers.APM,
89+
AlertConsumers.INFRASTRUCTURE,
90+
AlertConsumers.LOGS,
91+
AlertConsumers.UPTIME,
92+
AlertConsumers.SLO,
93+
AlertConsumers.OBSERVABILITY,
94+
AlertConsumers.ALERTS,
95+
],
96+
query: {
97+
bool: {
98+
filter: [
99+
{
100+
range: {
101+
'kibana.alert.start': {
102+
gte: start,
103+
lte: end,
104+
},
105+
},
106+
},
107+
...buildKqlFilter(kqlFilter),
108+
...(includeRecovered ? [] : [{ term: { [ALERT_STATUS]: ALERT_STATUS_ACTIVE } }]),
109+
],
110+
},
111+
},
112+
size: 10,
113+
});
114+
115+
const total = getHitsTotal(response);
116+
const alerts = response.hits.hits.map((hit) => omit(hit._source ?? {}, ...OMITTED_ALERT_FIELDS));
117+
118+
return { alerts, selectedFields, total };
119+
}

x-pack/solutions/observability/plugins/observability_agent_builder/server/tools/get_alerts/get_alerts.ts renamed to x-pack/solutions/observability/plugins/observability_agent_builder/server/tools/get_alerts/tool.ts

Lines changed: 7 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,17 @@
66
*/
77

88
import { z } from '@kbn/zod';
9-
import { omit } from 'lodash';
109
import { ToolType } from '@kbn/onechat-common';
1110
import { ToolResultType } from '@kbn/onechat-common/tools/tool_result';
1211
import type { BuiltinToolDefinition, StaticToolRegistration } from '@kbn/onechat-server';
1312
import type { CoreSetup, Logger } from '@kbn/core/server';
14-
import {
15-
ALERT_STATUS,
16-
ALERT_STATUS_ACTIVE,
17-
AlertConsumers,
18-
} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names';
19-
import { OBSERVABILITY_RULE_TYPE_IDS_WITH_SUPPORTED_STACK_RULE_TYPES } from '@kbn/observability-shared-plugin/common';
2013
import type {
2114
ObservabilityAgentBuilderPluginStart,
2215
ObservabilityAgentBuilderPluginStartDependencies,
2316
} from '../../types';
24-
import { getRelevantAlertFields } from './get_relevant_alert_fields';
25-
import { getHitsTotal } from '../../utils/get_hits_total';
26-
import { kqlFilter as buildKqlFilter } from '../../utils/dsl_filters';
2717
import { getAgentBuilderResourceAvailability } from '../../utils/get_agent_builder_resource_availability';
2818
import { timeRangeSchemaOptional } from '../../utils/tool_schemas';
29-
import { getDefaultConnectorId } from '../../utils/get_default_connector_id';
19+
import { getToolHandler } from './handler';
3020

3121
export const OBSERVABILITY_GET_ALERTS_TOOL_ID = 'observability.get_alerts';
3222

@@ -62,19 +52,6 @@ export const defaultFields = [
6252
'transaction.name',
6353
];
6454

65-
const OMITTED_ALERT_FIELDS = [
66-
'event.action',
67-
'event.kind',
68-
'kibana.alert.rule.execution.uuid',
69-
'kibana.alert.rule.revision',
70-
'kibana.alert.rule.tags',
71-
'kibana.alert.rule.uuid',
72-
'kibana.alert.workflow_status',
73-
'kibana.space_ids',
74-
'kibana.alert.time_range',
75-
'kibana.version',
76-
] as const;
77-
7855
const getAlertsSchema = z.object({
7956
...timeRangeSchemaOptional(DEFAULT_TIME_RANGE),
8057
query: z.string().min(1).describe('Natural language query to guide relevant field selection.'),
@@ -120,68 +97,17 @@ export function createGetAlertsTool({
12097
{ request }
12198
) => {
12299
try {
123-
const [coreStart, pluginStart] = await core.getStartServices();
124-
const { inference, ruleRegistry } = pluginStart;
125-
126-
const alertsClient = await ruleRegistry.getRacClientWithRequest(request);
127-
128-
const connectorId = await getDefaultConnectorId({
129-
coreStart,
130-
inference,
131-
request,
132-
logger,
133-
});
134-
135-
const boundInferenceClient = inference.getClient({
100+
const { alerts, selectedFields, total } = await getToolHandler({
101+
core,
136102
request,
137-
bindTo: { connectorId },
138-
});
139-
140-
const selectedFields = await getRelevantAlertFields({
141-
coreStart,
142-
pluginStart,
143-
request,
144-
inferenceClient: boundInferenceClient,
145103
logger,
104+
start,
105+
end,
146106
query,
107+
kqlFilter,
108+
includeRecovered,
147109
});
148110

149-
const response = await alertsClient.find({
150-
ruleTypeIds: OBSERVABILITY_RULE_TYPE_IDS_WITH_SUPPORTED_STACK_RULE_TYPES,
151-
consumers: [
152-
AlertConsumers.APM,
153-
AlertConsumers.INFRASTRUCTURE,
154-
AlertConsumers.LOGS,
155-
AlertConsumers.UPTIME,
156-
AlertConsumers.SLO,
157-
AlertConsumers.OBSERVABILITY,
158-
AlertConsumers.ALERTS,
159-
],
160-
query: {
161-
bool: {
162-
filter: [
163-
{
164-
range: {
165-
'kibana.alert.start': {
166-
gte: start,
167-
lte: end,
168-
},
169-
},
170-
},
171-
...buildKqlFilter(kqlFilter),
172-
...(includeRecovered ? [] : [{ term: { [ALERT_STATUS]: ALERT_STATUS_ACTIVE } }]),
173-
],
174-
},
175-
},
176-
size: 10,
177-
});
178-
179-
const total = getHitsTotal(response);
180-
181-
const alerts = response.hits.hits.map((hit) =>
182-
omit(hit._source ?? {}, ...OMITTED_ALERT_FIELDS)
183-
);
184-
185111
return {
186112
results: [
187113
{

0 commit comments

Comments
 (0)