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

[8.16] [Security assistant] Fix `invoke_assistant_*` telemetry (#198594) #198626

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ describe('chatCompleteRoute', () => {
actionTypeId: '.gen-ai',
model: 'gpt-4',
assistantStreamingEnabled: false,
isEnabledKnowledgeBase: false,
});
}),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import { buildResponse } from '../../lib/build_response';
import {
appendAssistantMessageToConversation,
createConversationWithUserInput,
DEFAULT_PLUGIN_NAME,
getIsKnowledgeBaseInstalled,
getPluginNameFromRequest,
langChainExecute,
performChecks,
} from '../helpers';
Expand Down Expand Up @@ -63,9 +66,9 @@ export const chatCompleteRoute = (
const assistantResponse = buildResponse(response);
let telemetry;
let actionTypeId;
const ctx = await context.resolve(['core', 'elasticAssistant', 'licensing']);
const logger: Logger = ctx.elasticAssistant.logger;
try {
const ctx = await context.resolve(['core', 'elasticAssistant', 'licensing']);
const logger: Logger = ctx.elasticAssistant.logger;
telemetry = ctx.elasticAssistant.telemetry;
const inference = ctx.elasticAssistant.inference;

Expand Down Expand Up @@ -219,13 +222,27 @@ export const chatCompleteRoute = (
});
} catch (err) {
const error = transformError(err as Error);
const pluginName = getPluginNameFromRequest({
request,
defaultPluginName: DEFAULT_PLUGIN_NAME,
logger,
});
const v2KnowledgeBaseEnabled =
ctx.elasticAssistant.getRegisteredFeatures(pluginName).assistantKnowledgeBaseByDefault;
const kbDataClient =
(await ctx.elasticAssistant.getAIAssistantKnowledgeBaseDataClient({
v2KnowledgeBaseEnabled,
})) ?? undefined;
const isKnowledgeBaseInstalled = await getIsKnowledgeBaseInstalled(kbDataClient);

telemetry?.reportEvent(INVOKE_ASSISTANT_ERROR_EVENT.eventType, {
actionTypeId: actionTypeId ?? '',
model: request.body.model,
errorMessage: error.message,
// TODO rm actionTypeId check when llmClass for bedrock streaming is implemented
// tracked here: https://github.com/elastic/security-team/issues/7363
assistantStreamingEnabled: request.body.isStream ?? false,
isEnabledKnowledgeBase: isKnowledgeBaseInstalled,
});
return assistantResponse.error({
body: error.message,
Expand Down
30 changes: 11 additions & 19 deletions x-pack/plugins/elastic_assistant/server/routes/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { FindResponse } from '../ai_assistant_data_clients/find';
import { EsPromptsSchema } from '../ai_assistant_data_clients/prompts/types';
import { AIAssistantDataClient } from '../ai_assistant_data_clients';
import { MINIMUM_AI_ASSISTANT_LICENSE } from '../../common/constants';
import { ESQL_DOCS_LOADED_QUERY } from './knowledge_base/constants';
import { SECURITY_LABS_RESOURCE, SECURITY_LABS_LOADED_QUERY } from './knowledge_base/constants';
import { buildResponse, getLlmType } from './utils';
import {
AgentExecutorParams,
Expand Down Expand Up @@ -436,15 +436,13 @@ export const langChainExecute = async ({
executorParams
);

const { esqlExists, isModelDeployed } = await getIsKnowledgeBaseEnabled(kbDataClient);
const isKnowledgeBaseInstalled = await getIsKnowledgeBaseInstalled(kbDataClient);

telemetry.reportEvent(INVOKE_ASSISTANT_SUCCESS_EVENT.eventType, {
actionTypeId,
model: request.body.model,
// TODO rm actionTypeId check when llmClass for bedrock streaming is implemented
// tracked here: https://github.com/elastic/security-team/issues/7363
assistantStreamingEnabled: isStream && actionTypeId === '.gen-ai',
isEnabledKnowledgeBase: isModelDeployed && esqlExists,
assistantStreamingEnabled: isStream,
isEnabledKnowledgeBase: isKnowledgeBaseInstalled,
});
return response.ok<StreamResponseWithHeaders['body'] | StaticReturnType['body']>(result);
};
Expand Down Expand Up @@ -671,23 +669,20 @@ export const isV2KnowledgeBaseEnabled = ({
* Telemetry function to determine whether knowledge base has been installed
* @param kbDataClient
*/
export const getIsKnowledgeBaseEnabled = async (
export const getIsKnowledgeBaseInstalled = async (
kbDataClient?: AIAssistantKnowledgeBaseDataClient | null
): Promise<{
esqlExists: boolean;
isModelDeployed: boolean;
}> => {
let esqlExists = false;
): Promise<boolean> => {
let securityLabsDocsExist = false;
let isModelDeployed = false;
if (kbDataClient != null) {
try {
isModelDeployed = await kbDataClient.isModelDeployed();
if (isModelDeployed) {
esqlExists =
securityLabsDocsExist =
(
await kbDataClient.getKnowledgeBaseDocumentEntries({
query: ESQL_DOCS_LOADED_QUERY,
required: true,
kbResource: SECURITY_LABS_RESOURCE,
query: SECURITY_LABS_LOADED_QUERY,
})
).length > 0;
}
Expand All @@ -696,8 +691,5 @@ export const getIsKnowledgeBaseEnabled = async (
}
}

return {
esqlExists,
isModelDeployed,
};
return isModelDeployed && securityLabsDocsExist;
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const ESQL_DOCS_LOADED_QUERY =
'You can chain processing commands, separated by a pipe character: `|`.';
export const SECURITY_LABS_RESOURCE = 'security_labs';
export const USER_RESOURCE = 'user';
// Query for determining if Security Labs docs have been loaded. Intended for use with Telemetry
export const SECURITY_LABS_LOADED_QUERY = 'What is Elastic Security Labs';
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jest.mock('./helpers', () => {

return {
...original,
getIsKnowledgeBaseEnabled: jest.fn(),
getIsKnowledgeBaseInstalled: jest.fn(),
appendAssistantMessageToConversation: jest.fn(),
langChainExecute: jest.fn(),
getPluginNameFromRequest: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { ElasticAssistantRequestHandlerContext, GetElser } from '../types';
import {
appendAssistantMessageToConversation,
DEFAULT_PLUGIN_NAME,
getIsKnowledgeBaseEnabled,
getIsKnowledgeBaseInstalled,
getPluginNameFromRequest,
getSystemPromptFromUserConversation,
langChainExecute,
Expand Down Expand Up @@ -170,14 +170,13 @@ export const postActionsConnectorExecuteRoute = (
(await assistantContext.getAIAssistantKnowledgeBaseDataClient({
v2KnowledgeBaseEnabled,
})) ?? undefined;
const isEnabledKnowledgeBase = await getIsKnowledgeBaseEnabled(kbDataClient);

const isKnowledgeBaseInstalled = await getIsKnowledgeBaseInstalled(kbDataClient);
telemetry.reportEvent(INVOKE_ASSISTANT_ERROR_EVENT.eventType, {
actionTypeId: request.body.actionTypeId,
model: request.body.model,
errorMessage: error.message,
assistantStreamingEnabled: request.body.subAction !== 'invokeAI',
isEnabledKnowledgeBase,
isEnabledKnowledgeBase: isKnowledgeBaseInstalled,
});

return resp.error({
Expand Down