@@ -6,6 +6,11 @@ import logger from '../logger.js';
66import { mongoLogId } from 'mongodb-log-writer' ;
77import { ApiClient } from '../common/atlas/apiClient.js' ;
88import { ApiClientError } from '../common/atlas/apiClientError.js' ;
9+ import fs from 'fs/promises' ;
10+ import path from 'path' ;
11+
12+ const isTelemetryEnabled = config . telemetry === 'enabled' ;
13+ const CACHE_FILE = path . join ( process . cwd ( ) , '.telemetry-cache.json' ) ;
914
1015export class Telemetry {
1116 constructor ( private readonly session : Session ) { }
@@ -23,10 +28,8 @@ export class Telemetry {
2328 os_version : config . os_version ,
2429 } ;
2530
26- private readonly isTelemetryEnabled = config . telemetry === 'enabled' ;
27-
2831 async emitToolEvent ( command : string , category : string , startTime : number , result : 'success' | 'failure' , error ?: Error ) : Promise < void > {
29- if ( ! this . isTelemetryEnabled ) {
32+ if ( ! isTelemetryEnabled ) {
3033 logger . debug ( mongoLogId ( 1_000_000 ) , "telemetry" , `Telemetry is disabled, skipping event.` ) ;
3134 return ;
3235 }
@@ -50,26 +53,72 @@ export class Telemetry {
5053 event . properties . error_code = error ?. message ;
5154 }
5255
53- await this . emit ( event ) ;
56+ await this . emit ( [ event ] ) ;
5457 }
5558
56- private async emit ( event : BaseEvent ) : Promise < void > {
59+ private async emit ( events : BaseEvent [ ] ) : Promise < void > {
60+ // First try to read any cached events
61+ const cachedEvents = await this . readCache ( ) ;
62+ const allEvents = [ ...cachedEvents , ...events ] ;
63+
64+ logger . debug ( mongoLogId ( 1_000_000 ) , "telemetry" , `Attempting to send ${ allEvents . length } events (${ cachedEvents . length } cached)` ) ;
65+
5766 try {
5867 if ( this . session . apiClient ) {
59- await this . session . apiClient . sendEvents ( [ event ] ) ;
68+ await this . session . apiClient . sendEvents ( allEvents ) ;
69+ // If successful, clear the cache
70+ await this . clearCache ( ) ;
71+ return ;
6072 }
6173 } catch ( error ) {
6274 logger . warning ( mongoLogId ( 1_000_000 ) , "telemetry" , `Error sending event to authenticated client: ${ error } ` ) ;
75+ // Cache the events that failed to send
76+ await this . cacheEvents ( allEvents ) ;
6377 }
6478
65- // if it is unauthenticated, send to temp client
79+ // Try unauthenticated client as fallback
6680 try {
6781 const tempApiClient = new ApiClient ( {
6882 baseUrl : config . apiBaseUrl ,
6983 } ) ;
70- await tempApiClient . sendEvents ( [ event ] ) ;
84+ await tempApiClient . sendEvents ( allEvents ) ;
85+ // If successful, clear the cache
86+ await this . clearCache ( ) ;
7187 } catch ( error ) {
7288 logger . warning ( mongoLogId ( 1_000_000 ) , "telemetry" , `Error sending event to unauthenticated client: ${ error } ` ) ;
89+ // Cache the events that failed to send
90+ await this . cacheEvents ( allEvents ) ;
91+ }
92+ }
93+
94+ private async readCache ( ) : Promise < BaseEvent [ ] > {
95+ try {
96+ const data = await fs . readFile ( CACHE_FILE , 'utf-8' ) ;
97+ return JSON . parse ( data ) ;
98+ } catch ( error ) {
99+ if ( ( error as NodeJS . ErrnoException ) . code !== 'ENOENT' ) {
100+ logger . warning ( mongoLogId ( 1_000_000 ) , "telemetry" , `Error reading telemetry cache: ${ error } ` ) ;
101+ }
102+ return [ ] ;
103+ }
104+ }
105+
106+ private async cacheEvents ( events : BaseEvent [ ] ) : Promise < void > {
107+ try {
108+ await fs . writeFile ( CACHE_FILE , JSON . stringify ( events , null , 2 ) ) ;
109+ logger . debug ( mongoLogId ( 1_000_000 ) , "telemetry" , `Cached ${ events . length } events for later sending` ) ;
110+ } catch ( error ) {
111+ logger . warning ( mongoLogId ( 1_000_000 ) , "telemetry" , `Failed to cache telemetry events: ${ error } ` ) ;
112+ }
113+ }
114+
115+ private async clearCache ( ) : Promise < void > {
116+ try {
117+ await fs . unlink ( CACHE_FILE ) ;
118+ } catch ( error ) {
119+ if ( ( error as NodeJS . ErrnoException ) . code !== 'ENOENT' ) {
120+ logger . warning ( mongoLogId ( 1_000_000 ) , "telemetry" , `Error clearing telemetry cache: ${ error } ` ) ;
121+ }
73122 }
74123 }
75124}
0 commit comments