Skip to content

Commit

Permalink
Add an additional function override to measure any action
Browse files Browse the repository at this point in the history
  • Loading branch information
TungstnBallon committed Feb 21, 2025
1 parent 79efb82 commit 4370349
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 72 deletions.
98 changes: 46 additions & 52 deletions libs/execution/src/lib/blocks/block-execution-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,69 +98,63 @@ export async function executeBlock(
name: block.name,
type: blockType,
});
const { result, durationMs: totalDurMs } = await measure(
location,
async () => {
assert(location.block !== undefined);

const { durationMs: preDurMs } = await measure(
location.withBlockInternalLocation('preBlockHooks'),
() => executionContext.executeHooks(inputValue),
);
executionContext.logger.logDebug(
`Pre-block hooks took ${Math.round(preDurMs)} ms`,
);
const { result, durationMs: totalDurMs } = await measure(async () => {
assert(location.block !== undefined);

if (inputValue == null) {
executionContext.logger.logInfoDiagnostic(
`Skipped execution because parent block emitted no value.`,
{ node: block, property: 'name' },
);
const result = R.ok(null);
const { durationMs: postDurMs } = await measure(
location.withBlockInternalLocation('postBlockHooks'),
() => executionContext.executeHooks(inputValue, result),
);
executionContext.logger.logDebug(
`Post-block hooks took ${Math.round(postDurMs)} ms`,
);
return result;
}
const { durationMs: preDurMs } = await measure(
() => executionContext.executeHooks(inputValue),
location.withBlockInternalLocation('preBlockHooks'),
);
executionContext.logger.logDebug(
`Pre-block hooks took ${Math.round(preDurMs)} ms`,
);

const { result, durationMs: blockDurMs } = await measure(
location.withBlockInternalLocation('blockExecution'),
async () => {
let result: R.Result<IOTypeImplementation | null>;
try {
result = await blockExecutor.execute(inputValue, executionContext);
} catch (unexpectedError) {
result = R.err({
message: `An unknown error occurred: ${
unexpectedError instanceof Error
? unexpectedError.stack ?? unexpectedError.message
: JSON.stringify(unexpectedError)
}`,
diagnostic: { node: block, property: 'name' },
});
}
return result;
},
);
executionContext.logger.logDebug(
`Block execution itself took ${Math.round(blockDurMs)} ms`,
if (inputValue == null) {
executionContext.logger.logInfoDiagnostic(
`Skipped execution because parent block emitted no value.`,
{ node: block, property: 'name' },
);

const result = R.ok(null);
const { durationMs: postDurMs } = await measure(
location.withBlockInternalLocation('postBlockHooks'),
() => executionContext.executeHooks(inputValue, result),
location.withBlockInternalLocation('postBlockHooks'),
);
executionContext.logger.logDebug(
`Post-block hooks took ${Math.round(postDurMs)} ms`,
);
return result;
}

const { result, durationMs: blockDurMs } = await measure(async () => {
let result: R.Result<IOTypeImplementation | null>;
try {
result = await blockExecutor.execute(inputValue, executionContext);
} catch (unexpectedError) {
result = R.err({
message: `An unknown error occurred: ${
unexpectedError instanceof Error
? unexpectedError.stack ?? unexpectedError.message
: JSON.stringify(unexpectedError)
}`,
diagnostic: { node: block, property: 'name' },
});
}
return result;
},
);
}, location.withBlockInternalLocation('blockExecution'));
executionContext.logger.logDebug(
`Block execution itself took ${Math.round(blockDurMs)} ms`,
);

const { durationMs: postDurMs } = await measure(
() => executionContext.executeHooks(inputValue, result),
location.withBlockInternalLocation('postBlockHooks'),
);
executionContext.logger.logDebug(
`Post-block hooks took ${Math.round(postDurMs)} ms`,
);

return result;
}, location);
executionContext.logger.logDebug(
`${block.name} took ${Math.round(totalDurMs)} ms`,
);
Expand Down
32 changes: 29 additions & 3 deletions libs/execution/src/lib/perf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,39 @@ export class MeasureLocation {
}
}

/**
* Measure the duration of any action.
* @param id The action's name/identifier
* @param action The action to measure
* @returns The action's result and the actions duration in milliseconds
*/
export async function measure<R>(
action: () => Promise<R>,
id: string,
detail?: unknown,
): Promise<{ result: R; durationMs: number }>;
/**
* Measure the duration of a pipeline, block or block-internal.
* @param location The measure's location
* @param action The action to measure
* @returns The action's result and the actions duration in milliseconds
*/
export async function measure<R>(
action: () => Promise<R>,
location: MeasureLocation,
): Promise<{ result: R; durationMs: number }>;
export async function measure<R>(
action: () => Promise<R>,
location: MeasureLocation | string,
detail?: unknown,
): Promise<{ result: R; durationMs: number }> {
const name = location.name;
const start = name + '::start';
const end = name + '::end';
const id = typeof location === 'string' ? location : location.id;
if (typeof location !== 'string') {
assert(detail === undefined);
detail = location;
}
const start = id + '::start';
const end = id + '::end';

performance.mark(start);
const result = await action();
Expand Down
31 changes: 14 additions & 17 deletions libs/interpreter-lib/src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,23 +318,20 @@ export class DefaultJayveeInterpreter implements JayveeInterpreter {
this.services.WrapperFactories,
);

const { result, durationMs } = await measure(
new MeasureLocation(pipeline.name),
async () => {
const executionResult = await executeBlocks(executionContext, pipeline);

if (isErr(executionResult)) {
const diagnosticError = executionResult.left;
executionContext.logger.logErrDiagnostic(
diagnosticError.message,
diagnosticError.diagnostic,
);
return ExitCode.FAILURE;
}

return ExitCode.SUCCESS;
},
);
const { result, durationMs } = await measure(async () => {
const executionResult = await executeBlocks(executionContext, pipeline);

if (isErr(executionResult)) {
const diagnosticError = executionResult.left;
executionContext.logger.logErrDiagnostic(
diagnosticError.message,
diagnosticError.diagnostic,
);
return ExitCode.FAILURE;
}

return ExitCode.SUCCESS;
}, new MeasureLocation(pipeline.name));
executionContext.logger.logDebug(
`${pipeline.name} took ${Math.round(durationMs)} ms`,
);
Expand Down

0 comments on commit 4370349

Please sign in to comment.