Skip to content

Commit 89a28f5

Browse files
committed
Refactor: Consolidate MCP event tracking functions
1 parent 95e5536 commit 89a28f5

File tree

8 files changed

+50
-92
lines changed

8 files changed

+50
-92
lines changed

src/lib/instrumentation.ts

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ interface MCPEventPayload {
1515
};
1616
}
1717

18-
export function trackMCPEvent(
18+
export function trackMCP(
1919
toolName: string,
2020
clientInfo: { name?: string; version?: string },
21+
error?: unknown
2122
): void {
2223
const instrumentationEndpoint = "https://api.browserstack.com/sdk/v1/event";
23-
24+
const isSuccess = !error;
2425
const mcpClient = clientInfo?.name || "unknown";
26+
27+
// Log client information
2528
if (clientInfo?.name) {
2629
logger.info(
2730
`Client connected: ${clientInfo.name} (version: ${clientInfo.version})`,
@@ -36,60 +39,15 @@ export function trackMCPEvent(
3639
mcp_version: packageJson.version,
3740
tool_name: toolName,
3841
mcp_client: mcpClient,
39-
success: true,
42+
success: isSuccess,
4043
},
4144
};
4245

43-
axios
44-
.post(instrumentationEndpoint, event, {
45-
headers: {
46-
"Content-Type": "application/json",
47-
Authorization: `Basic ${Buffer.from(
48-
`${config.browserstackUsername}:${config.browserstackAccessKey}`,
49-
).toString("base64")}`,
50-
},
51-
timeout: 2000,
52-
})
53-
.then((response) => {
54-
logger.info("MCP event tracked successfully", {
55-
toolName,
56-
response,
57-
});
58-
})
59-
.catch((error: unknown) => {
60-
logger.warn(
61-
`Failed to track MCP event: ${error instanceof Error ? error.message : String(error)}`,
62-
{
63-
toolName,
64-
},
65-
);
66-
});
67-
}
68-
69-
export function trackMCPFailure(
70-
toolName: string,
71-
error: unknown,
72-
clientInfo: { name?: string; version?: string },
73-
): void {
74-
const instrumentationEndpoint = "https://api.browserstack.com/sdk/v1/event";
75-
76-
const mcpClient = clientInfo?.name || "unknown";
77-
const errorMessage = error instanceof Error ? error.message : String(error);
78-
const errorType = error instanceof Error ? error.constructor.name : "Unknown";
79-
80-
logger.error(`Tool failure: ${toolName} - ${errorMessage}`, { errorType });
81-
82-
const event: MCPEventPayload = {
83-
event_type: "MCPInstrumentation",
84-
event_properties: {
85-
mcp_version: packageJson.version,
86-
tool_name: toolName,
87-
mcp_client: mcpClient,
88-
success: false,
89-
error_message: errorMessage,
90-
error_type: errorType,
91-
},
92-
};
46+
// Add error details if applicable
47+
if (error) {
48+
event.event_properties.error_message = error instanceof Error ? error.message : String(error);
49+
event.event_properties.error_type = error instanceof Error ? error.constructor.name : "Unknown";
50+
}
9351

9452
axios
9553
.post(instrumentationEndpoint, event, {
@@ -102,17 +60,17 @@ export function trackMCPFailure(
10260
timeout: 2000,
10361
})
10462
.then((response) => {
105-
logger.info("MCP failure event tracked successfully", {
63+
logger.info(`MCP ${isSuccess ? 'event' : 'failure event'} tracked successfully`, {
10664
toolName,
10765
response,
10866
});
10967
})
11068
.catch((error: unknown) => {
11169
logger.warn(
112-
`Failed to track MCP failure event: ${error instanceof Error ? error.message : String(error)}`,
70+
`Failed to track MCP ${isSuccess ? 'event' : 'failure event'}: ${error instanceof Error ? error.message : String(error)}`,
11371
{
11472
toolName,
11573
},
11674
);
11775
});
118-
}
76+
}

src/tools/accessibility.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
startAccessibilityScan,
66
AccessibilityScanResponse,
77
} from "./accessiblity-utils/accessibility";
8-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
8+
import { trackMCP } from "../lib/instrumentation";
99

1010
async function runAccessibilityScan(
1111
name: string,
@@ -44,16 +44,16 @@ export default function addAccessibilityTools(server: McpServer) {
4444
},
4545
async (args) => {
4646
try {
47-
trackMCPEvent(
47+
trackMCP(
4848
"startAccessibilityScan",
49-
server.server.getClientVersion()!,
49+
server.server.getClientVersion()!
5050
);
5151
return await runAccessibilityScan(args.name, args.pageURL);
5252
} catch (error) {
53-
trackMCPFailure(
53+
trackMCP(
5454
"startAccessibilityScan",
55-
error,
5655
server.server.getClientVersion()!,
56+
error
5757
);
5858
return {
5959
content: [

src/tools/applive.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
44
import fs from "fs";
55
import { startSession } from "./applive-utils/start-session";
66
import logger from "../logger";
7-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
7+
import { trackMCP } from "../lib/instrumentation";
88

99
/**
1010
* Launches an App Live Session on BrowserStack.
@@ -91,14 +91,14 @@ export default function addAppLiveTools(server: McpServer) {
9191
},
9292
async (args) => {
9393
try {
94-
trackMCPEvent("runAppLiveSession", server.server.getClientVersion()!);
94+
trackMCP("runAppLiveSession", server.server.getClientVersion()!);
9595
return await startAppLiveSession(args);
9696
} catch (error) {
9797
logger.error("App live session failed: %s", error);
98-
trackMCPFailure(
98+
trackMCP(
9999
"runAppLiveSession",
100-
error,
101100
server.server.getClientVersion()!,
101+
error
102102
);
103103
return {
104104
content: [

src/tools/automate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { z } from "zod";
33
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
44
import logger from "../logger";
55
import { retrieveNetworkFailures } from "../lib/api";
6-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
6+
import { trackMCP } from "../lib/instrumentation";
77

88
/**
99
* Fetches failed network requests from a BrowserStack Automate session.
@@ -48,17 +48,17 @@ export default function addAutomateTools(server: McpServer) {
4848
},
4949
async (args) => {
5050
try {
51-
trackMCPEvent("getNetworkFailures", server.server.getClientVersion()!);
51+
trackMCP("getNetworkFailures", server.server.getClientVersion()!);
5252
return await getNetworkFailures(args);
5353
} catch (error) {
5454
const errorMessage =
5555
error instanceof Error ? error.message : String(error);
5656
logger.error("Failed to fetch network logs: %s", errorMessage);
5757

58-
trackMCPFailure(
58+
trackMCP(
5959
"getNetworkFailures",
60-
error,
6160
server.server.getClientVersion()!,
61+
error
6262
);
6363

6464
return {

src/tools/bstack-sdk.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
generateBrowserStackYMLInstructions,
1111
getInstructionsForProjectConfiguration,
1212
} from "./sdk-utils/instructions";
13-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
13+
import { trackMCP } from "../lib/instrumentation";
1414

1515
/**
1616
* BrowserStack SDK hooks into your test framework to seamlessly run tests on BrowserStack.
@@ -74,9 +74,9 @@ export default function addSDKTools(server: McpServer) {
7474
},
7575
async (args) => {
7676
try {
77-
trackMCPEvent(
77+
trackMCP(
7878
"runTestsOnBrowserStack",
79-
server.server.getClientVersion()!,
79+
server.server.getClientVersion()!
8080
);
8181

8282
return await bootstrapProjectWithSDK({
@@ -88,10 +88,10 @@ export default function addSDKTools(server: McpServer) {
8888
desiredPlatforms: args.desiredPlatforms,
8989
});
9090
} catch (error) {
91-
trackMCPFailure(
91+
trackMCP(
9292
"runTestsOnBrowserStack",
93-
error,
9493
server.server.getClientVersion()!,
94+
error
9595
);
9696
return {
9797
content: [

src/tools/live.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { z } from "zod";
44
import logger from "../logger";
55
import { startBrowserSession } from "./live-utils/start-session";
66
import { PlatformType } from "./live-utils/types";
7-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
7+
import { trackMCP } from "../lib/instrumentation";
88

99
// Define the schema shape
1010
const LiveArgsShape = {
@@ -105,17 +105,17 @@ export default function addBrowserLiveTools(server: McpServer) {
105105
LiveArgsShape,
106106
async (args) => {
107107
try {
108-
trackMCPEvent(
108+
trackMCP(
109109
"runBrowserLiveSession",
110-
server.server.getClientVersion()!,
110+
server.server.getClientVersion()!
111111
);
112112
return await runBrowserSession(args);
113113
} catch (error) {
114114
logger.error("Live session failed: %s", error);
115-
trackMCPFailure(
115+
trackMCP(
116116
"runBrowserLiveSession",
117-
error,
118117
server.server.getClientVersion()!,
118+
error
119119
);
120120
return {
121121
content: [

src/tools/observability.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
import { z } from "zod";
33
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
44
import { getLatestO11YBuildInfo } from "../lib/api";
5-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
5+
import { trackMCP } from "../lib/instrumentation";
66
import logger from "../logger";
77

88
export async function getFailuresInLastRun(
@@ -59,17 +59,17 @@ export default function addObservabilityTools(server: McpServer) {
5959
},
6060
async (args) => {
6161
try {
62-
trackMCPEvent(
62+
trackMCP(
6363
"getFailuresInLastRun",
64-
server.server.getClientVersion()!,
64+
server.server.getClientVersion()!
6565
);
6666
return await getFailuresInLastRun(args.buildName, args.projectName);
6767
} catch (error) {
6868
logger.error("Failed to get failures in the last run: %s", error);
69-
trackMCPFailure(
69+
trackMCP(
7070
"getFailuresInLastRun",
71-
error,
7271
server.server.getClientVersion()!,
72+
error
7373
);
7474
return {
7575
content: [

src/tools/testmanagement.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
import { z } from "zod";
33
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4-
import { trackMCPEvent, trackMCPFailure } from "../lib/instrumentation";
4+
import { trackMCP } from "../lib/instrumentation";
55
import logger from "../logger";
66
import {
77
createProjectOrFolder,
@@ -23,17 +23,17 @@ export async function createProjectOrFolderTool(
2323
args: z.infer<typeof CreateProjFoldSchema>,
2424
): Promise<CallToolResult> {
2525
try {
26-
trackMCPEvent(
26+
trackMCP(
2727
"createProjectOrFolder",
28-
serverInstance.server.getClientVersion()!,
28+
serverInstance.server.getClientVersion()!
2929
);
3030
return await createProjectOrFolder(args);
3131
} catch (err) {
3232
logger.error("Failed to create project/folder: %s", err);
33-
trackMCPFailure(
33+
trackMCP(
3434
"createProjectOrFolder",
35-
err,
3635
serverInstance.server.getClientVersion()!,
36+
err
3737
);
3838
return {
3939
content: [
@@ -59,14 +59,14 @@ export async function createTestCaseTool(
5959
// Sanitize input arguments
6060
const cleanedArgs = sanitizeArgs(args);
6161
try {
62-
trackMCPEvent("createTestCase", serverInstance.server.getClientVersion()!);
62+
trackMCP("createTestCase", serverInstance.server.getClientVersion()!);
6363
return await createTestCaseAPI(cleanedArgs);
6464
} catch (err) {
6565
logger.error("Failed to create test case: %s", err);
66-
trackMCPFailure(
66+
trackMCP(
6767
"createTestCase",
68-
err,
6968
serverInstance.server.getClientVersion()!,
69+
err
7070
);
7171
return {
7272
content: [

0 commit comments

Comments
 (0)