@@ -13,17 +13,25 @@ import * as cp from 'child_process';
1313import { getWorkspaceFolderPath } from './util' ;
1414import { toolExecutionEnvironment } from './goEnv' ;
1515
16- // Name of the prompt telemetry command. This is also used to determine if the gopls instance supports telemetry.
17- // Exported for testing.
16+ /**
17+ * Name of the prompt telemetry command. This is also used to determine if the
18+ * gopls instance supports telemetry.
19+ * Exported for testing.
20+ */
1821export const GOPLS_MAYBE_PROMPT_FOR_TELEMETRY = 'gopls.maybe_prompt_for_telemetry' ;
1922
20- // Key for the global state that holds the very first time the telemetry-enabled gopls was observed.
21- // Exported for testing.
23+ /**
24+ * Key for the global state that holds the very first time the telemetry-enabled
25+ * gopls was observed.
26+ * Exported for testing.
27+ */
2228export const TELEMETRY_START_TIME_KEY = 'telemetryStartTime' ;
2329
24- // Run our encode/decode function for the Date object, to be defensive
25- // from vscode Memento API behavior change.
26- // Exported for testing.
30+ /**
31+ * Run our encode/decode function for the Date object, to be defensive from
32+ * vscode Memento API behavior change.
33+ * Exported for testing.
34+ */
2735export function recordTelemetryStartTime ( storage : vscode . Memento , date : Date ) {
2836 storage . update ( TELEMETRY_START_TIME_KEY , date . toJSON ( ) ) ;
2937}
@@ -43,32 +51,57 @@ function readTelemetryStartTime(storage: vscode.Memento): Date | null {
4351enum ReporterState {
4452 NOT_INITIALIZED ,
4553 IDLE ,
46- STARTING ,
4754 RUNNING
4855}
4956
50- // exported for testing.
57+ /**
58+ * Manages Go telemetry data and persists them to disk using a storage tool.
59+ *
60+ * **Usage:**
61+ * 1. Call `setTool(tool)` once, before any other methods.
62+ * 2. Call `add(key, value)` to add values associated with keys.
63+ * 3. Data is automatically flushed to disk periodically.
64+ * 4. To force an immediate flush, call `flush(true)`.
65+ *
66+ * **Example:**
67+ * ```typescript
68+ * const r = new TelemetryReporter();
69+ * r.setTool(vscgo);
70+ * r.add("count", 10);
71+ * r.add("count", 5);
72+ * r.flush(true); // Force a flush
73+ * ```
74+ *
75+ * Exported for testing.
76+ */
5177export class TelemetryReporter implements vscode . Disposable {
5278 private _state = ReporterState . NOT_INITIALIZED ;
5379 private _counters : { [ key : string ] : number } = { } ;
5480 private _flushTimer : NodeJS . Timeout | undefined ;
5581 private _tool = '' ;
5682 constructor ( flushIntervalMs = 60_000 , private counterFile : string = '' ) {
5783 if ( flushIntervalMs > 0 ) {
58- // periodically call flush.
84+ // Periodically call flush.
5985 this . _flushTimer = setInterval ( this . flush . bind ( this ) , flushIntervalMs ) ;
6086 }
6187 }
6288
89+ /**
90+ * Initializes the tool.
91+ * This method should be called once. Subsequent calls have no effect.
92+ */
6393 public setTool ( tool : string ) {
64- // allow only once.
94+ // Allow only once.
6595 if ( tool === '' || this . _state !== ReporterState . NOT_INITIALIZED ) {
6696 return ;
6797 }
6898 this . _state = ReporterState . IDLE ;
6999 this . _tool = tool ;
70100 }
71101
102+ /**
103+ * Adds a numeric value to a counter associated with the given key.
104+ */
72105 public add ( key : string , value : number ) {
73106 if ( value <= 0 ) {
74107 return ;
@@ -77,16 +110,20 @@ export class TelemetryReporter implements vscode.Disposable {
77110 this . _counters [ key ] = ( this . _counters [ key ] || 0 ) + value ;
78111 }
79112
80- // flush is called periodically (by the callback set up in the constructor)
81- // or when the extension is deactivated (with force=true).
113+ /**
114+ * Flushes Go telemetry data.
115+ * * When `force` is true, telemetry is flushed immediately, bypassing the
116+ * IDLE state check.
117+ * * When `force` is false, telemetry is flushed only if the reporter is IDLE.
118+ */
82119 public async flush ( force = false ) {
83120 // If flush runs with force=true, ignore the state and skip state update.
84121 if ( ! force && this . _state !== ReporterState . IDLE ) {
85122 // vscgo is not installed yet or is running. flush next time.
86123 return 0 ;
87124 }
88125 if ( ! force ) {
89- this . _state = ReporterState . STARTING ;
126+ this . _state = ReporterState . RUNNING ;
90127 }
91128 try {
92129 await this . writeGoTelemetry ( ) ;
@@ -142,11 +179,13 @@ export class TelemetryReporter implements vscode.Disposable {
142179 clearInterval ( this . _flushTimer ) ;
143180 }
144181 this . _flushTimer = undefined ;
145- await this . flush ( true ) ; // flush any remaining data in buffer.
182+ await this . flush ( true ) ; // Flush any remaining data in buffer.
146183 }
147184}
148185
149- // global telemetryReporter instance.
186+ /**
187+ * Global telemetryReporter instance.
188+ */
150189export const telemetryReporter = new TelemetryReporter ( ) ;
151190
152191// TODO(hyangah): consolidate the list of all the telemetries and bucketting functions.
@@ -155,8 +194,10 @@ export function addTelemetryEvent(name: string, count: number) {
155194 telemetryReporter . add ( name , count ) ;
156195}
157196
158- // Go extension delegates most of the telemetry logic to gopls.
159- // TelemetryService provides API to interact with gopls's telemetry.
197+ /**
198+ * Go extension delegates most of the telemetry logic to gopls.
199+ * TelemetryService provides API to interact with gopls's telemetry.
200+ */
160201export class TelemetryService {
161202 private active = false ;
162203 constructor (
@@ -219,8 +260,10 @@ export class TelemetryService {
219260 }
220261}
221262
222- // Set telemetry env vars for gopls. See gopls/internal/server/prompt.go
223- // TODO(hyangah): add an integration testing after gopls v0.17 becomes available.
263+ /**
264+ * Set telemetry env vars for gopls. See gopls/internal/server/prompt.go
265+ * TODO(hyangah): add an integration testing after gopls v0.17 becomes available.
266+ */
224267export function setTelemetryEnvVars ( globalState : vscode . Memento , env : NodeJS . ProcessEnv ) {
225268 if ( ! env [ 'GOTELEMETRY_GOPLS_CLIENT_TOKEN' ] ) {
226269 env [ 'GOTELEMETRY_GOPLS_CLIENT_TOKEN' ] = `${ hashMachineID ( ) + 1 } ` ; // [1, 1000]
@@ -234,7 +277,9 @@ export function setTelemetryEnvVars(globalState: vscode.Memento, env: NodeJS.Pro
234277 }
235278}
236279
237- // Map vscode.env.machineId to an integer in [0, 1000).
280+ /**
281+ * Map vscode.env.machineId to an integer in [0, 1000).
282+ */
238283function hashMachineID ( salt ?: string ) : number {
239284 const hash = createHash ( 'md5' ) . update ( `${ vscode . env . machineId } ${ salt } ` ) . digest ( 'hex' ) ;
240285 return parseInt ( hash . substring ( 0 , 8 ) , 16 ) % 1000 ;
0 commit comments