From a137a1b92e470f97f83bbcc06afbb3be9cd9ea3f Mon Sep 17 00:00:00 2001 From: Bianca Lisle Date: Thu, 24 Apr 2025 14:31:38 +0100 Subject: [PATCH 1/4] chore: add server events --- src/server.ts | 39 ++++++++++++++++++++++++++++++++++++++ src/telemetry/telemetry.ts | 2 +- src/telemetry/types.ts | 12 ++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/server.ts b/src/server.ts index fd16c75d..95bc2465 100644 --- a/src/server.ts +++ b/src/server.ts @@ -8,6 +8,8 @@ import { mongoLogId } from "mongodb-log-writer"; import { ObjectId } from "mongodb"; import { Telemetry } from "./telemetry/telemetry.js"; import { UserConfig } from "./config.js"; +import { type ServerEvent } from "./telemetry/types.js"; +import { type ServerCommand } from "./telemetry/types.js"; export interface ServerOptions { session: Session; @@ -20,8 +22,10 @@ export class Server { private readonly mcpServer: McpServer; private readonly telemetry: Telemetry; private readonly userConfig: UserConfig; + private readonly startTime: number; constructor({ session, mcpServer, userConfig }: ServerOptions) { + this.startTime = Date.now(); this.session = session; this.telemetry = new Telemetry(session); this.mcpServer = mcpServer; @@ -46,12 +50,47 @@ export class Server { "server", `Server started with transport ${transport.constructor.name} and agent runner ${this.session.agentRunner?.name}` ); + + this.emitServerEvent("start", Date.now() - this.startTime); }; } async close(): Promise { + const closeTime = Date.now(); await this.session.close(); await this.mcpServer.close(); + + this.emitServerEvent("stop", Date.now() - closeTime); + } + + + /** + * Emits a server event + * @param command - The server command (e.g., "start", "stop", "register", "deregister") + * @param additionalProperties - Additional properties specific to the event + */ + async emitServerEvent(command: ServerCommand, commandDuration: number): Promise { + const event: ServerEvent = { + timestamp: new Date().toISOString(), + source: "mdbmcp", + properties: { + ...this.telemetry.getCommonProperties(), + result: "success", + duration_ms: commandDuration, + component: "server", + category: "other", + command: command, + }, + }; + + if (command === "start") { + event.properties.startup_time_ms = commandDuration; + } + if (command === "stop") { + event.properties.runtime_duration_ms = Date.now() - this.startTime; + } + + await this.telemetry.emitEvents([event]); } private registerTools() { diff --git a/src/telemetry/telemetry.ts b/src/telemetry/telemetry.ts index a43b11c9..2e440571 100644 --- a/src/telemetry/telemetry.ts +++ b/src/telemetry/telemetry.ts @@ -1,5 +1,5 @@ import { Session } from "../session.js"; -import { BaseEvent } from "./types.js"; +import { BaseEvent, ServerEvent } from "./types.js"; import { config } from "../config.js"; import logger from "../logger.js"; import { mongoLogId } from "mongodb-log-writer"; diff --git a/src/telemetry/types.ts b/src/telemetry/types.ts index 4f24e545..57601d45 100644 --- a/src/telemetry/types.ts +++ b/src/telemetry/types.ts @@ -2,6 +2,7 @@ * Result type constants for telemetry events */ export type TelemetryResult = "success" | "failure"; +export type ServerCommand = "start" | "stop" | "register" | "deregister"; /** * Base interface for all events @@ -45,3 +46,14 @@ export interface ToolEvent extends BaseEvent { is_atlas?: boolean; } & BaseEvent["properties"]; } + +/** + * Interface for server events + */ +export interface ServerEvent extends BaseEvent { + properties: { + command: ServerCommand; + startup_time_ms?: number; + runtime_duration_ms?: number; + } & BaseEvent["properties"]; +} From 521aa847e5f38a2266a72f1404370c1be59af5f1 Mon Sep 17 00:00:00 2001 From: Bianca Lisle Date: Thu, 24 Apr 2025 14:54:40 +0100 Subject: [PATCH 2/4] update --- src/server.ts | 22 ++++++++++++++++------ src/telemetry/telemetry.ts | 2 +- src/telemetry/types.ts | 5 +++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/server.ts b/src/server.ts index 95bc2465..f0644d9c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -53,23 +53,29 @@ export class Server { this.emitServerEvent("start", Date.now() - this.startTime); }; + + this.mcpServer.server.onclose = () => { + const closeTime = Date.now(); + this.emitServerEvent("stop", Date.now() - closeTime); + }; + + this.mcpServer.server.onerror = (error: Error) => { + const closeTime = Date.now(); + this.emitServerEvent("stop", Date.now() - closeTime, error); + }; } async close(): Promise { - const closeTime = Date.now(); await this.session.close(); await this.mcpServer.close(); - - this.emitServerEvent("stop", Date.now() - closeTime); } - /** * Emits a server event * @param command - The server command (e.g., "start", "stop", "register", "deregister") * @param additionalProperties - Additional properties specific to the event */ - async emitServerEvent(command: ServerCommand, commandDuration: number): Promise { + emitServerEvent(command: ServerCommand, commandDuration: number, error?: Error) { const event: ServerEvent = { timestamp: new Date().toISOString(), source: "mdbmcp", @@ -88,9 +94,13 @@ export class Server { } if (command === "stop") { event.properties.runtime_duration_ms = Date.now() - this.startTime; + if (error) { + event.properties.result = "failure"; + event.properties.reason = error.message; + } } - await this.telemetry.emitEvents([event]); + this.telemetry.emitEvents([event]).catch(() => {}); } private registerTools() { diff --git a/src/telemetry/telemetry.ts b/src/telemetry/telemetry.ts index 2e440571..a43b11c9 100644 --- a/src/telemetry/telemetry.ts +++ b/src/telemetry/telemetry.ts @@ -1,5 +1,5 @@ import { Session } from "../session.js"; -import { BaseEvent, ServerEvent } from "./types.js"; +import { BaseEvent } from "./types.js"; import { config } from "../config.js"; import logger from "../logger.js"; import { mongoLogId } from "mongodb-log-writer"; diff --git a/src/telemetry/types.ts b/src/telemetry/types.ts index 57601d45..08bfb817 100644 --- a/src/telemetry/types.ts +++ b/src/telemetry/types.ts @@ -2,7 +2,7 @@ * Result type constants for telemetry events */ export type TelemetryResult = "success" | "failure"; -export type ServerCommand = "start" | "stop" | "register" | "deregister"; +export type ServerCommand = "start" | "stop" | "register" | "deregister"; /** * Base interface for all events @@ -53,7 +53,8 @@ export interface ToolEvent extends BaseEvent { export interface ServerEvent extends BaseEvent { properties: { command: ServerCommand; + reason?: string; startup_time_ms?: number; runtime_duration_ms?: number; - } & BaseEvent["properties"]; + } & BaseEvent["properties"]; } From 16eabd6561fb0f03eb9640bababba4388a62a3b7 Mon Sep 17 00:00:00 2001 From: Bianca Lisle Date: Thu, 24 Apr 2025 14:55:25 +0100 Subject: [PATCH 3/4] updatE --- src/telemetry/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/telemetry/types.ts b/src/telemetry/types.ts index 08bfb817..c44127d6 100644 --- a/src/telemetry/types.ts +++ b/src/telemetry/types.ts @@ -2,7 +2,7 @@ * Result type constants for telemetry events */ export type TelemetryResult = "success" | "failure"; -export type ServerCommand = "start" | "stop" | "register" | "deregister"; +export type ServerCommand = "start" | "stop"; /** * Base interface for all events From 1bb08eacc5b6c2651d2bbf0ace0099d0cc05f443 Mon Sep 17 00:00:00 2001 From: Bianca Lisle Date: Thu, 24 Apr 2025 16:40:34 +0100 Subject: [PATCH 4/4] update --- src/telemetry/telemetry.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/telemetry/telemetry.ts b/src/telemetry/telemetry.ts index a43b11c9..2b5ed7df 100644 --- a/src/telemetry/telemetry.ts +++ b/src/telemetry/telemetry.ts @@ -69,7 +69,6 @@ export class Telemetry { public async emitEvents(events: BaseEvent[]): Promise { try { if (!Telemetry.isTelemetryEnabled()) { - logger.debug(mongoLogId(1_000_000), "telemetry", "Telemetry is disabled, skipping events."); return; }