diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index 9b7773f1795d5..58e8b3a100ab0 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -25,7 +25,7 @@ import { finished } from 'stream/promises'; import { PassThrough } from 'stream'; import { SecurityConnectorFeatureId } from '../../common'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; -import { getErrorSource } from '@kbn/task-manager-plugin/server/task_running'; +import { createTaskRunError, getErrorSource } from '@kbn/task-manager-plugin/server/task_running'; const actionExecutor = new ActionExecutor({ isESOCanEncrypt: true }); const services = actionsMock.createServices(); @@ -1199,6 +1199,35 @@ describe('Action Executor', () => { }); }); + test(`${label} logs warning captures source when executor throws error with error source`, async () => { + const err = createTaskRunError( + new Error('this action execution is intended to fail'), + TaskErrorSource.USER + ); + err.stack = 'foo error\n stack 1\n stack 2\n stack 3'; + connectorType.executor.mockRejectedValueOnce(err); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( + connectorSavedObject + ); + connectorTypeRegistry.get.mockReturnValueOnce(connectorType); + + let executorResult; + if (executeUnsecure) { + executorResult = await actionExecutor.executeUnsecured(executeUnsecuredParams); + } else { + executorResult = await actionExecutor.execute(executeParams); + } + + expect(executorResult?.errorSource).toBe(TaskErrorSource.USER); + expect(loggerMock.warn).toBeCalledWith( + 'action execution failure: test:1: 1: an error occurred while running the action: this action execution is intended to fail; retry: true' + ); + expect(loggerMock.error).toBeCalledWith(err, { + error: { stack_trace: 'foo error\n stack 1\n stack 2\n stack 3' }, + tags: ['test', '1', 'action-run-failed'], + }); + }); + test(`${label} logs warning when executor returns invalid status`, async () => { connectorType.executor.mockResolvedValueOnce({ actionId: '1', diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index a15bd8b4c7c04..2db78f0d5058e 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -15,6 +15,7 @@ import { SpacesServiceStart } from '@kbn/spaces-plugin/server'; import { IEventLogger, SAVED_OBJECT_REL_PRIMARY } from '@kbn/event-log-plugin/server'; import { AuthenticatedUser, SecurityPluginStart } from '@kbn/security-plugin/server'; import { createTaskRunError, TaskErrorSource } from '@kbn/task-manager-plugin/server'; +import { getErrorSource } from '@kbn/task-manager-plugin/server/task_running'; import { getGenAiTokenTracking, shouldTrackGenAiToken } from './gen_ai_token_tracking'; import { validateConfig, @@ -507,6 +508,7 @@ export class ActionExecutor { rawResult.errorSource = TaskErrorSource.USER; } } catch (err) { + const errorSource = getErrorSource(err) || TaskErrorSource.FRAMEWORK; if (err.reason === ActionExecutionErrorReason.Authorization) { rawResult = err.result; } else { @@ -517,7 +519,7 @@ export class ActionExecutor { serviceMessage: err.message, error: err, retry: true, - errorSource: TaskErrorSource.FRAMEWORK, + errorSource, }; } }