diff --git a/src/vs/base/node/stats.ts b/src/vs/base/node/stats.ts index ae76a9de2182ff08d51ae75cfaba3690661b25bd..aedbd13349e7dc989eb8e7eafd2481911f5666f7 100644 --- a/src/vs/base/node/stats.ts +++ b/src/vs/base/node/stats.ts @@ -17,6 +17,7 @@ export interface WorkspaceStats { configFiles: WorkspaceStatItem[]; fileCount: number; maxFilesReached: boolean; + launchConfigFiles: WorkspaceStatItem[]; } function asSortedItems(map: Map): WorkspaceStatItem[] { @@ -66,7 +67,7 @@ export function collectLaunchConfigs(folder: string): Promise { +export async function collectWorkspaceStats(folder: string, filter: string[]): Promise { const configFilePatterns = [ { 'tag': 'grunt.js', 'pattern': /^gruntfile\.js$/i }, { 'tag': 'gulp.js', 'pattern': /^gulpfile\.js$/i }, @@ -182,15 +183,17 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Promise let token: { count: number, maxReached: boolean } = { count: 0, maxReached: false }; return new Promise((resolve, reject) => { - walk(folder, filter, token, (files) => { + walk(folder, filter, token, async (files) => { files.forEach(acceptFile); + let launchConfigs = await collectLaunchConfigs(folder); + resolve({ configFiles: asSortedItems(configFiles), fileTypes: asSortedItems(fileTypes), fileCount: token.count, - maxFilesReached: token.maxReached - + maxFilesReached: token.maxReached, + launchConfigFiles: launchConfigs }); }); }); diff --git a/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts b/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts index 94cba280d743c2fefbdc54cf175b148fe01bd8a9..9e60ec11d55b6fca551d743d4c895e435f7d265e 100644 --- a/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts +++ b/src/vs/platform/diagnostics/electron-main/diagnosticsService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { WorkspaceStats, collectWorkspaceStats, collectLaunchConfigs, WorkspaceStatItem } from 'vs/base/node/stats'; +import { WorkspaceStats, collectWorkspaceStats, WorkspaceStatItem } from 'vs/base/node/stats'; import { IMainProcessInfo } from 'vs/platform/launch/electron-main/launchService'; import { ProcessItem, listProcesses } from 'vs/base/node/ps'; import product from 'vs/platform/node/product'; @@ -110,9 +110,8 @@ export class DiagnosticsService implements IDiagnosticsService { workspaceInfoMessages.push(`| Folder (${basename(folder)}): ${countMessage}`); workspaceInfoMessages.push(this.formatWorkspaceStats(stats)); - const launchConfigs = await collectLaunchConfigs(folder); - if (launchConfigs.length > 0) { - workspaceInfoMessages.push(this.formatLaunchConfigs(launchConfigs)); + if (stats.launchConfigFiles.length > 0) { + workspaceInfoMessages.push(this.formatLaunchConfigs(stats.launchConfigFiles)); } })); } else { @@ -196,11 +195,9 @@ export class DiagnosticsService implements IDiagnosticsService { console.log(`| Folder (${basename(folder)}): ${countMessage}`); console.log(this.formatWorkspaceStats(stats)); - await collectLaunchConfigs(folder).then(launchConfigs => { - if (launchConfigs.length > 0) { - console.log(this.formatLaunchConfigs(launchConfigs)); - } - }); + if (stats.launchConfigFiles.length > 0) { + console.log(this.formatLaunchConfigs(stats.launchConfigFiles)); + } }).catch(error => { console.log(`| Error: Unable to collect workspace stats for folder ${folder} (${error.toString()})`); })); diff --git a/src/vs/workbench/parts/stats/node/workspaceStats.ts b/src/vs/workbench/parts/stats/node/workspaceStats.ts index bed2040b45630c7b888422b516348f5c4a040c82..633ba9c3df914442ecbcb51b593d684ab5e4b8a0 100644 --- a/src/vs/workbench/parts/stats/node/workspaceStats.ts +++ b/src/vs/workbench/parts/stats/node/workspaceStats.ts @@ -20,6 +20,7 @@ import { extname, join } from 'path'; import { WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { collectWorkspaceStats, WorkspaceStats as WorkspaceStatsType } from 'vs/base/node/stats'; const SshProtocolMatcher = /^([^@:]+@)?([^:]+):/; const SshUrlMatcher = /^([^@:]+@)?([^:]+):(.+)$/; @@ -225,10 +226,15 @@ export class WorkspaceStats implements IWorkbenchContribution { private report(): void { - // Workspace Stats + // Workspace Tags this.resolveWorkspaceTags(this.windowService.getConfiguration(), rootFiles => this.handleWorkspaceFiles(rootFiles)) .then(tags => this.reportWorkspaceTags(tags), error => onUnexpectedError(error)); + // Workspace file types, config files, and launch configs + this.getWorkspaceMetadata().then(stats => { + this.reportWorkspaceMetadata(stats); + }); + // Cloud Stats this.reportCloudStats(); @@ -731,4 +737,39 @@ export class WorkspaceStats implements IWorkbenchContribution { this.telemetryService.publicLog('resolveProxy.stats', { type }); }).then(undefined, onUnexpectedError); } + + /* __GDPR__ + "workspace.metadata" : { + "fileTypes" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "configTypes" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "launchConfigs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ + private reportWorkspaceMetadata(stats: WorkspaceStatsType[]): void { + for (let stat of stats) { // one event for each root folder in the workspace + this.telemetryService.publicLog('workspce.metadata', { + 'fileTypes': stat.fileTypes, + 'configTypes': stat.configFiles, + 'launchConfigs': stat.launchConfigFiles + }); + } + } + + private getWorkspaceMetadata(): Promise { + const workspaceStatPromises: Promise[] = []; + const workspace = this.contextService.getWorkspace(); + workspace.folders.forEach(folder => { + const folderUri = URI.revive(folder.uri); + if (folderUri.scheme === 'file') { + const folder = folderUri.fsPath; + workspaceStatPromises.push(collectWorkspaceStats(folder, ['node_modules', '.git']).then(async stats => { + return stats; + })); + } + }); + + return Promise.all(workspaceStatPromises).then((stats) => { + return stats; + }); + } }