Skip to content

Commit

Permalink
Improve Task Manager instrumentation (elastic#99160)
Browse files Browse the repository at this point in the history
* Instrument task manager

* Don't refresh after SO updates

* Update snapshot test, remove beforeRun instrumentation

* Revert "Don't refresh after SO updates"

This reverts commit 54f848d.

* Fix task_store unit test

* Adding tests and updating ConcreteTaskInstance interface with traceparent

* Reverting unnecessary changes

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Ying Mao <ying.mao@elastic.co>
  • Loading branch information
3 people committed Jun 4, 2021
1 parent 183a55f commit dda5f01
Show file tree
Hide file tree
Showing 11 changed files with 406 additions and 147 deletions.
14 changes: 10 additions & 4 deletions packages/kbn-apm-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface SpanOptions {
labels?: Record<string, string>;
}

type Span = Exclude<typeof agent.currentSpan, undefined | null>;

export function parseSpanOptions(optionsOrName: SpanOptions | string) {
const options = typeof optionsOrName === 'string' ? { name: optionsOrName } : optionsOrName;

Expand All @@ -30,7 +32,7 @@ const runInNewContext = <T extends (...args: any[]) => any>(cb: T): ReturnType<T

export async function withSpan<T>(
optionsOrName: SpanOptions | string,
cb: () => Promise<T>
cb: (span?: Span) => Promise<T>
): Promise<T> {
const options = parseSpanOptions(optionsOrName);

Expand Down Expand Up @@ -71,13 +73,17 @@ export async function withSpan<T>(
span.addLabels(labels);
}

return cb()
return cb(span)
.then((res) => {
span.outcome = 'success';
if (!span.outcome || span.outcome === 'unknown') {
span.outcome = 'success';
}
return res;
})
.catch((err) => {
span.outcome = 'failure';
if (!span.outcome || span.outcome === 'unknown') {
span.outcome = 'failure';
}
throw err;
})
.finally(() => {
Expand Down
223 changes: 123 additions & 100 deletions x-pack/plugins/actions/server/lib/action_executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import type { PublicMethodsOf } from '@kbn/utility-types';
import { Logger, KibanaRequest } from 'src/core/server';
import { withSpan } from '@kbn/apm-utils';
import { validateParams, validateConfig, validateSecrets } from './validate_with_schema';
import {
ActionTypeExecutorResult,
Expand Down Expand Up @@ -78,113 +79,135 @@ export class ActionExecutor {
);
}

const {
logger,
spaces,
getServices,
encryptedSavedObjectsClient,
actionTypeRegistry,
eventLogger,
preconfiguredActions,
getActionsClientWithRequest,
} = this.actionExecutorContext!;

const services = getServices(request);
const spaceId = spaces && spaces.getSpaceId(request);
const namespace = spaceId && spaceId !== 'default' ? { namespace: spaceId } : {};

const { actionTypeId, name, config, secrets } = await getActionInfo(
await getActionsClientWithRequest(request, source),
encryptedSavedObjectsClient,
preconfiguredActions,
actionId,
namespace.namespace
);
return withSpan(
{
name: `execute_action`,
type: 'actions',
labels: {
actionId,
},
},
async (span) => {
const {
logger,
spaces,
getServices,
encryptedSavedObjectsClient,
actionTypeRegistry,
eventLogger,
preconfiguredActions,
getActionsClientWithRequest,
} = this.actionExecutorContext!;

if (!actionTypeRegistry.isActionExecutable(actionId, actionTypeId, { notifyUsage: true })) {
actionTypeRegistry.ensureActionTypeEnabled(actionTypeId);
}
const actionType = actionTypeRegistry.get(actionTypeId);

let validatedParams: Record<string, unknown>;
let validatedConfig: Record<string, unknown>;
let validatedSecrets: Record<string, unknown>;

try {
validatedParams = validateParams(actionType, params);
validatedConfig = validateConfig(actionType, config);
validatedSecrets = validateSecrets(actionType, secrets);
} catch (err) {
return { status: 'error', actionId, message: err.message, retry: false };
}
const services = getServices(request);
const spaceId = spaces && spaces.getSpaceId(request);
const namespace = spaceId && spaceId !== 'default' ? { namespace: spaceId } : {};

const { actionTypeId, name, config, secrets } = await getActionInfo(
await getActionsClientWithRequest(request, source),
encryptedSavedObjectsClient,
preconfiguredActions,
actionId,
namespace.namespace
);

if (span) {
span.name = `execute_action ${actionTypeId}`;
span.addLabels({
actionTypeId,
});
}

if (!actionTypeRegistry.isActionExecutable(actionId, actionTypeId, { notifyUsage: true })) {
actionTypeRegistry.ensureActionTypeEnabled(actionTypeId);
}
const actionType = actionTypeRegistry.get(actionTypeId);

let validatedParams: Record<string, unknown>;
let validatedConfig: Record<string, unknown>;
let validatedSecrets: Record<string, unknown>;

try {
validatedParams = validateParams(actionType, params);
validatedConfig = validateConfig(actionType, config);
validatedSecrets = validateSecrets(actionType, secrets);
} catch (err) {
span?.setOutcome('failure');
return { status: 'error', actionId, message: err.message, retry: false };
}

const actionLabel = `${actionTypeId}:${actionId}: ${name}`;
logger.debug(`executing action ${actionLabel}`);

const event: IEvent = {
event: { action: EVENT_LOG_ACTIONS.execute },
kibana: {
saved_objects: [
{
rel: SAVED_OBJECT_REL_PRIMARY,
type: 'action',
id: actionId,
...namespace,
const actionLabel = `${actionTypeId}:${actionId}: ${name}`;
logger.debug(`executing action ${actionLabel}`);

const event: IEvent = {
event: { action: EVENT_LOG_ACTIONS.execute },
kibana: {
saved_objects: [
{
rel: SAVED_OBJECT_REL_PRIMARY,
type: 'action',
id: actionId,
...namespace,
},
],
},
],
},
};
};

eventLogger.startTiming(event);
let rawResult: ActionTypeExecutorResult<unknown>;
try {
rawResult = await actionType.executor({
actionId,
services,
params: validatedParams,
config: validatedConfig,
secrets: validatedSecrets,
});
} catch (err) {
rawResult = {
actionId,
status: 'error',
message: 'an error occurred while running the action executor',
serviceMessage: err.message,
retry: false,
};
}
eventLogger.stopTiming(event);
eventLogger.startTiming(event);
let rawResult: ActionTypeExecutorResult<unknown>;
try {
rawResult = await actionType.executor({
actionId,
services,
params: validatedParams,
config: validatedConfig,
secrets: validatedSecrets,
});
} catch (err) {
rawResult = {
actionId,
status: 'error',
message: 'an error occurred while running the action executor',
serviceMessage: err.message,
retry: false,
};
}
eventLogger.stopTiming(event);

// allow null-ish return to indicate success
const result = rawResult || {
actionId,
status: 'ok',
};
// allow null-ish return to indicate success
const result = rawResult || {
actionId,
status: 'ok',
};

event.event = event.event || {};

if (result.status === 'ok') {
event.event.outcome = 'success';
event.message = `action executed: ${actionLabel}`;
} else if (result.status === 'error') {
event.event.outcome = 'failure';
event.message = `action execution failure: ${actionLabel}`;
event.error = event.error || {};
event.error.message = actionErrorToMessage(result);
logger.warn(`action execution failure: ${actionLabel}: ${event.error.message}`);
} else {
event.event.outcome = 'failure';
event.message = `action execution returned unexpected result: ${actionLabel}: "${result.status}"`;
event.error = event.error || {};
event.error.message = 'action execution returned unexpected result';
logger.warn(
`action execution failure: ${actionLabel}: returned unexpected result "${result.status}"`
);
}
event.event = event.event || {};

eventLogger.logEvent(event);
return result;
if (result.status === 'ok') {
span?.setOutcome('success');
event.event.outcome = 'success';
event.message = `action executed: ${actionLabel}`;
} else if (result.status === 'error') {
span?.setOutcome('failure');
event.event.outcome = 'failure';
event.message = `action execution failure: ${actionLabel}`;
event.error = event.error || {};
event.error.message = actionErrorToMessage(result);
logger.warn(`action execution failure: ${actionLabel}: ${event.error.message}`);
} else {
span?.setOutcome('failure');
event.event.outcome = 'failure';
event.message = `action execution returned unexpected result: ${actionLabel}: "${result.status}"`;
event.error = event.error || {};
event.error.message = 'action execution returned unexpected result';
logger.warn(
`action execution failure: ${actionLabel}: returned unexpected result "${result.status}"`
);
}

eventLogger.logEvent(event);
return result;
}
);
}
}

Expand Down
Loading

0 comments on commit dda5f01

Please sign in to comment.