Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions packages/fiori-mcp-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ export class FioriFunctionalityServer {
* Sets up telemetry.
*/
private async setupTelemetry(): Promise<void> {
await TelemetryHelper.initTelemetrySettings();
TelemetryHelper.initTelemetrySettings().catch((error) => {
console.error('Error initializing telemetry settings:', error);
});
}

/**
Expand All @@ -79,14 +81,11 @@ export class FioriFunctionalityServer {

this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params as { name: string; arguments: ToolArgs };
const telemetryData: TelemetryData = { tool: name, functionalityId: (args as any)?.functionalityId };

try {
let result;
TelemetryHelper.markToolStartTime();
const telemetryProperties: TelemetryData = {
tool: name,
functionalityId: (args as any)?.functionalityId
};

switch (name) {
case 'list-fiori-apps':
Expand All @@ -102,14 +101,21 @@ export class FioriFunctionalityServer {
result = await executeFunctionality(args as ExecuteFunctionalityInput);
break;
default:
await TelemetryHelper.sendTelemetry(unknownTool, telemetryProperties, (args as any)?.appPath);
TelemetryHelper.sendTelemetry(unknownTool, telemetryData, (args as any)?.appPath).catch(() => {
/* ignore telemetry errors */
});
throw new Error(
`Unknown tool: ${name}. Try one of: list-fiori-apps, list-functionality, get-functionality-details, execute-functionality.`
);
}
await TelemetryHelper.sendTelemetry(name, telemetryProperties, (args as any)?.appPath);
TelemetryHelper.sendTelemetry(name, telemetryData, (args as any)?.appPath).catch(() => {
/* ignore telemetry errors */
});
return this.convertResultToCallToolResult(result);
} catch (error) {
TelemetryHelper.sendTelemetry(name, { ...telemetryData }, (args as any)?.appPath, error).catch(() => {
/* ignore telemetry errors */
});
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return {
content: [
Expand Down
41 changes: 34 additions & 7 deletions packages/fiori-mcp-server/src/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { isAppStudio } from '@sap-ux/btp-utils';
import osName from 'os-name';
import i18next from 'i18next';
import { version } from '../../package.json';
import z from 'zod';

export const mcpServerName = '@sap-ux/fiori-mcp-server';
export const unknownTool = 'unknown-tool';
Expand Down Expand Up @@ -155,19 +156,45 @@ export abstract class TelemetryHelper {
* @param telemetryEventName - the event name to be reported
* @param telemetryData - the telemetry data
* @param appPath - the path of the application
* @param error - an optional error to be included in the telemetry data
* @returns - a promise that resolves when the event is sent
*/
public static async sendTelemetry(
telemetryEventName: string,
telemetryData: TelemetryData,
appPath?: string
appPath?: string,
error?: Error
): Promise<void> {
const telemetryEvent = this.prepareTelemetryEvent(telemetryEventName, telemetryData);
await ClientFactory.getTelemetryClient().reportEvent(
telemetryEvent,
SampleRate.NoSampling,
appPath ? { appPath } : undefined
);
try {
const client = ClientFactory.getTelemetryClient();
if (!client) {
console.error('Telemetry client is not initialized.');
return;
}
if (error) {
this.addTelemetryError(telemetryData, error);
}
const telemetryEvent = this.prepareTelemetryEvent(telemetryEventName, telemetryData);
await client.reportEvent(telemetryEvent, SampleRate.NoSampling, appPath ? { appPath } : undefined);
} catch (err) {
console.error('Error sending telemetry event:', err);
}
}

/**
* Adds error information to the telemetry data.
*
* @param telemetryData - the telemetry data
* @param error - the error to be added
*/
public static addTelemetryError(telemetryData: TelemetryData, error: Error): void {
if (error instanceof z.ZodError) {
telemetryData.error = 'zod';
} else if (error instanceof Error) {
telemetryData.error = 'error';
} else {
telemetryData.error = 'unknown';
}
}

/**
Expand Down
Loading