Skip to content

Commit 240c207

Browse files
author
Rachel Macfarlane
committed
Add workspace.id property to stats telemetry
1 parent 5ea298a commit 240c207

File tree

4 files changed

+55
-28
lines changed

4 files changed

+55
-28
lines changed

src/vs/platform/diagnostics/common/diagnosticsService.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ export interface PerformanceInfo {
6363
workspaceInfo?: string;
6464
}
6565

66+
export interface IWorkspaceInformation extends IWorkspace {
67+
telemetryId: string | undefined;
68+
}
69+
6670
export const ID = 'diagnosticsService';
6771
export const IDiagnosticsService = createDecorator<IDiagnosticsService>(ID);
6872

@@ -72,9 +76,9 @@ export interface IDiagnosticsService {
7276
getPerformanceInfo(mainProcessInfo: IMainProcessInfo, remoteInfo: (IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]): Promise<PerformanceInfo>;
7377
getSystemInfo(mainProcessInfo: IMainProcessInfo, remoteInfo: (IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]): Promise<SystemInfo>;
7478
getDiagnostics(mainProcessInfo: IMainProcessInfo, remoteInfo: (IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]): Promise<string>;
75-
reportWorkspaceStats(workspace: IWorkspace): Promise<void>;
79+
reportWorkspaceStats(workspace: IWorkspaceInformation): Promise<void>;
7680
}
7781

7882
export function isRemoteDiagnosticError(x: any): x is IRemoteDiagnosticError {
7983
return !!x.hostName && !!x.errorMessage;
80-
}
84+
}

src/vs/platform/diagnostics/node/diagnosticsService.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55
import * as osLib from 'os';
66
import { virtualMachineHint } from 'vs/base/node/id';
7-
import { IMachineInfo, WorkspaceStats, WorkspaceStatItem, IDiagnosticsService, PerformanceInfo, SystemInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnosticsService';
7+
import { IMachineInfo, WorkspaceStats, WorkspaceStatItem, IDiagnosticsService, PerformanceInfo, SystemInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError, isRemoteDiagnosticError, IWorkspaceInformation } from 'vs/platform/diagnostics/common/diagnosticsService';
88
import { readdir, stat, exists, readFile } from 'fs';
99
import { join, basename } from 'vs/base/common/path';
1010
import { parse, ParseError } from 'vs/base/common/json';
@@ -16,7 +16,6 @@ import { isWindows } from 'vs/base/common/platform';
1616
import { URI } from 'vs/base/common/uri';
1717
import { ProcessItem } from 'vs/base/common/processes';
1818
import { IMainProcessInfo } from 'vs/platform/launch/common/launchService';
19-
import { IWorkspace } from 'vs/platform/workspace/common/workspace';
2019
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2120

2221
export interface VersionInfo {
@@ -514,7 +513,7 @@ export class DiagnosticsService implements IDiagnosticsService {
514513
}
515514
}
516515

517-
public async reportWorkspaceStats(workspace: IWorkspace): Promise<void> {
516+
public async reportWorkspaceStats(workspace: IWorkspaceInformation): Promise<void> {
518517
workspace.folders.forEach(folder => {
519518
const folderUri = URI.revive(folder.uri);
520519
if (folderUri.scheme === 'file') {
@@ -525,16 +524,19 @@ export class DiagnosticsService implements IDiagnosticsService {
525524
count: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
526525
};
527526
type WorkspaceStatsClassification = {
527+
'workspace.id': { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
528528
fileTypes: WorkspaceStatItemClassification;
529529
configTypes: WorkspaceStatItemClassification;
530530
launchConfigs: WorkspaceStatItemClassification;
531531
};
532532
type WorkspaceStatsEvent = {
533+
'workspace.id': string | undefined;
533534
fileTypes: WorkspaceStatItem[];
534535
configTypes: WorkspaceStatItem[];
535536
launchConfigs: WorkspaceStatItem[];
536537
};
537538
this.telemetryService.publicLog2<WorkspaceStatsEvent, WorkspaceStatsClassification>('workspace.stats', {
539+
'workspace.id': workspace.telemetryId,
538540
fileTypes: stats.fileTypes,
539541
configTypes: stats.configFiles,
540542
launchConfigs: stats.launchConfigFiles
@@ -545,4 +547,4 @@ export class DiagnosticsService implements IDiagnosticsService {
545547
}
546548
});
547549
}
548-
}
550+
}

src/vs/workbench/contrib/stats/electron-browser/workspaceStats.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { endsWith } from 'vs/base/common/strings';
1515
import { ITextFileService, } from 'vs/workbench/services/textfile/common/textfiles';
1616
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
1717
import { IWorkspaceStatsService, Tags } from 'vs/workbench/contrib/stats/electron-browser/workspaceStatsService';
18+
import { IWorkspaceInformation } from 'vs/platform/diagnostics/common/diagnosticsService';
1819

1920
const SshProtocolMatcher = /^([^@:]+@)?([^:]+):/;
2021
const SshUrlMatcher = /^([^@:]+@)?([^:]+):(.+)$/;
@@ -175,10 +176,20 @@ export class WorkspaceStats implements IWorkbenchContribution {
175176
this.reportProxyStats();
176177

177178
const diagnosticsChannel = this.sharedProcessService.getChannel('diagnostics');
178-
diagnosticsChannel.call('reportWorkspaceStats', this.contextService.getWorkspace());
179+
diagnosticsChannel.call('reportWorkspaceStats', this.getWorkspaceInformation());
179180
}
180181

181-
182+
private getWorkspaceInformation(): IWorkspaceInformation {
183+
const workspace = this.contextService.getWorkspace();
184+
const state = this.contextService.getWorkbenchState();
185+
const id = this.workspaceStatsService.getTelemetryWorkspaceId(workspace, state);
186+
return {
187+
id: workspace.id,
188+
telemetryId: id,
189+
folders: workspace.folders,
190+
configuration: workspace.configuration
191+
};
192+
}
182193

183194
private reportWorkspaceTags(tags: Tags): void {
184195
/* __GDPR__

src/vs/workbench/contrib/stats/electron-browser/workspaceStatsService.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import * as crypto from 'crypto';
77
import { IFileService, IResolveFileResult, IFileStat } from 'vs/platform/files/common/files';
8-
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
8+
import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platform/workspace/common/workspace';
99
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
1010
import { IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
1111
import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification';
@@ -98,6 +98,12 @@ export const IWorkspaceStatsService = createDecorator<IWorkspaceStatsService>('w
9898
export interface IWorkspaceStatsService {
9999
_serviceBrand: any;
100100
getTags(): Promise<Tags>;
101+
102+
/**
103+
* Returns an id for the workspace, different from the id returned by the context service. A hash based
104+
* on the folder uri or workspace configuration, not time-based, and undefined for empty workspaces.
105+
*/
106+
getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): string | undefined;
101107
}
102108

103109

@@ -124,6 +130,28 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
124130
return this._tags;
125131
}
126132

133+
public getTelemetryWorkspaceId(workspace: IWorkspace, state: WorkbenchState): string | undefined {
134+
function createHash(uri: URI): string {
135+
return crypto.createHash('sha1').update(uri.scheme === Schemas.file ? uri.fsPath : uri.toString()).digest('hex');
136+
}
137+
138+
let workspaceId: string | undefined;
139+
switch (state) {
140+
case WorkbenchState.EMPTY:
141+
workspaceId = undefined;
142+
break;
143+
case WorkbenchState.FOLDER:
144+
workspaceId = createHash(workspace.folders[0].uri);
145+
break;
146+
case WorkbenchState.WORKSPACE:
147+
if (workspace.configuration) {
148+
workspaceId = createHash(workspace.configuration);
149+
}
150+
}
151+
152+
return workspaceId;
153+
}
154+
127155
/* __GDPR__FRAGMENT__
128156
"WorkspaceTags" : {
129157
"workbench.filesToOpenOrCreate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
@@ -226,25 +254,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
226254
const state = this.contextService.getWorkbenchState();
227255
const workspace = this.contextService.getWorkspace();
228256

229-
function createHash(uri: URI): string {
230-
return crypto.createHash('sha1').update(uri.scheme === Schemas.file ? uri.fsPath : uri.toString()).digest('hex');
231-
}
232-
233-
let workspaceId: string | undefined;
234-
switch (state) {
235-
case WorkbenchState.EMPTY:
236-
workspaceId = undefined;
237-
break;
238-
case WorkbenchState.FOLDER:
239-
workspaceId = createHash(workspace.folders[0].uri);
240-
break;
241-
case WorkbenchState.WORKSPACE:
242-
if (workspace.configuration) {
243-
workspaceId = createHash(workspace.configuration);
244-
}
245-
}
246-
247-
tags['workspace.id'] = workspaceId;
257+
tags['workspace.id'] = this.getTelemetryWorkspaceId(workspace, state);
248258

249259
const { filesToOpenOrCreate, filesToDiff } = configuration;
250260
tags['workbench.filesToOpenOrCreate'] = filesToOpenOrCreate && filesToOpenOrCreate.length || 0;

0 commit comments

Comments
 (0)