Tool execution metrics (#21587)
<!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21587?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+2
-1
@@ -4,8 +4,8 @@ import {
|
||||
MCP_PROGRESS_NOTIFICATION_METHOD,
|
||||
TOOL_CALL_PROGRESS_TOKEN_PREFIX,
|
||||
} from 'src/engine/api/mcp/constants/mcp-progress-notification.const';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { McpToolExecutorService } from 'src/engine/api/mcp/services/mcp-tool-executor.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
|
||||
describe('McpToolExecutorService', () => {
|
||||
let service: McpToolExecutorService;
|
||||
@@ -13,6 +13,7 @@ describe('McpToolExecutorService', () => {
|
||||
beforeEach(() => {
|
||||
const metricsService = {
|
||||
incrementCounterBy: jest.fn().mockResolvedValue(undefined),
|
||||
recordHistogram: jest.fn(),
|
||||
} as unknown as MetricsService;
|
||||
|
||||
service = new McpToolExecutorService(metricsService);
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { type ToolSet } from 'ai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
import { estimateToolOutputTokens } from 'src/engine/core-modules/tool-provider/utils/estimate-tool-output-tokens.util';
|
||||
import { getToolMetricName } from 'src/engine/core-modules/tool-provider/utils/get-tool-metric-name.util';
|
||||
import { isToolOutputSuccessful } from 'src/engine/core-modules/tool-provider/utils/is-tool-output-successful.util';
|
||||
import { resolveToolName } from 'src/engine/core-modules/tool-provider/utils/resolve-tool-name.util';
|
||||
|
||||
import { JSON_RPC_ERROR_CODE } from 'src/engine/api/mcp/constants/json-rpc-error-code.const';
|
||||
import {
|
||||
@@ -33,14 +38,23 @@ export class McpToolExecutorService {
|
||||
params: Record<string, unknown>,
|
||||
sseWriter?: (data: Record<string, unknown>) => void,
|
||||
) {
|
||||
const toolName = params.name as keyof typeof toolSet;
|
||||
if (!isNonEmptyString(params.name)) {
|
||||
return wrapJsonRpcResponse(id, {
|
||||
error: {
|
||||
code: JSON_RPC_ERROR_CODE.INVALID_PARAMS,
|
||||
message: 'Tool name is required',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const toolName = params.name;
|
||||
const tool = toolSet[toolName];
|
||||
|
||||
if (!isDefined(tool) || !isDefined(tool.execute)) {
|
||||
return wrapJsonRpcResponse(id, {
|
||||
error: {
|
||||
code: JSON_RPC_ERROR_CODE.INVALID_PARAMS,
|
||||
message: `Unknown tool: ${String(params.name)}`,
|
||||
message: `Unknown tool: ${toolName}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -57,15 +71,34 @@ export class McpToolExecutorService {
|
||||
});
|
||||
}
|
||||
|
||||
const metricToolName = getToolMetricName(
|
||||
resolveToolName({
|
||||
toolName,
|
||||
input: params.arguments,
|
||||
}),
|
||||
);
|
||||
|
||||
try {
|
||||
const result = await tool.execute(params.arguments, {
|
||||
toolCallId: '1',
|
||||
messages: [],
|
||||
});
|
||||
|
||||
void this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.McpToolExecutionSucceeded,
|
||||
const succeeded = isToolOutputSuccessful(result);
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: succeeded
|
||||
? MetricsKeys.McpToolExecutionSucceeded
|
||||
: MetricsKeys.McpToolExecutionFailed,
|
||||
amount: 1,
|
||||
attributes: { tool: metricToolName },
|
||||
});
|
||||
|
||||
this.metricsService.recordHistogram({
|
||||
key: MetricsKeys.McpToolOutputTokens,
|
||||
value: estimateToolOutputTokens(result),
|
||||
unit: 'token',
|
||||
attributes: { tool: metricToolName },
|
||||
});
|
||||
|
||||
return wrapJsonRpcResponse(id, {
|
||||
@@ -75,9 +108,10 @@ export class McpToolExecutorService {
|
||||
},
|
||||
});
|
||||
} catch (executionError) {
|
||||
void this.metricsService.incrementCounterBy({
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.McpToolExecutionFailed,
|
||||
amount: 1,
|
||||
attributes: { tool: metricToolName },
|
||||
});
|
||||
|
||||
return wrapJsonRpcResponse(id, {
|
||||
|
||||
Reference in New Issue
Block a user