diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 49adce3ae69..0aa00f21bcf 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -1814,8 +1814,8 @@ export class Repository { } } - getStatus(opts?: { limit?: number, ignoreSubmodules?: boolean }): Promise<{ status: IFileStatus[]; didHitLimit: boolean; }> { - return new Promise<{ status: IFileStatus[]; didHitLimit: boolean; }>((c, e) => { + getStatus(opts?: { limit?: number, ignoreSubmodules?: boolean }): Promise<{ status: IFileStatus[]; statusLength: number; didHitLimit: boolean; }> { + return new Promise<{ status: IFileStatus[]; statusLength: number; didHitLimit: boolean; }>((c, e) => { const parser = new GitStatusParser(); const env = { GIT_OPTIONAL_LOCKS: '0' }; const args = ['status', '-z', '-u']; @@ -1839,7 +1839,7 @@ export class Repository { })); } - c({ status: parser.status, didHitLimit: false }); + c({ status: parser.status, statusLength: parser.status.length, didHitLimit: false }); }; const limit = opts?.limit ?? 10000; @@ -1851,7 +1851,7 @@ export class Repository { child.stdout!.removeListener('data', onStdoutData); child.kill(); - c({ status: parser.status.slice(0, limit), didHitLimit: true }); + c({ status: parser.status.slice(0, limit), statusLength: parser.status.length, didHitLimit: true }); } }; diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index 7d40b7ee265..0742550848d 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -73,7 +73,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann version: info.version, env: environment, }); - const model = new Model(git, askpass, context.globalState, outputChannel); + const model = new Model(git, askpass, context.globalState, outputChannel, telemetryReporter); disposables.push(model); const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`); diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index a9a7b0e5f31..ba965e323d0 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel, commands } from 'vscode'; +import TelemetryReporter from 'vscode-extension-telemetry'; import { Repository, RepositoryState } from './repository'; import { memoize, sequentialize, debounce } from './decorators'; import { dispose, anyEvent, filterEvent, isDescendant, pathEquals, toDisposable, eventToPromise, logTimestamp } from './util'; @@ -108,7 +109,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR private disposables: Disposable[] = []; - constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel) { + constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel, private telemetryReporter: TelemetryReporter) { workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables); window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables); workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables); @@ -331,7 +332,7 @@ export class Model implements IRemoteSourcePublisherRegistry, IPushErrorHandlerR } const dotGit = await this.git.getRepositoryDotGit(repositoryRoot); - const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel); + const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel, this.telemetryReporter); this.open(repository); repository.status(); // do not await this, we want SCM to know about the repo asap diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 09c64ec1750..08426577718 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -6,6 +6,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands } from 'vscode'; +import TelemetryReporter from 'vscode-extension-telemetry'; import * as nls from 'vscode-nls'; import { Branch, Change, ForcePushMode, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status, CommitOptions, BranchQuery, FetchOptions } from './api/git'; import { AutoFetcher } from './autofetch'; @@ -853,7 +854,8 @@ export class Repository implements Disposable { private pushErrorHandlerRegistry: IPushErrorHandlerRegistry, remoteSourcePublisherRegistry: IRemoteSourcePublisherRegistry, globalState: Memento, - outputChannel: OutputChannel + outputChannel: OutputChannel, + private telemetryReporter: TelemetryReporter ) { const workspaceWatcher = workspace.createFileSystemWatcher('**'); this.disposables.push(workspaceWatcher); @@ -1802,7 +1804,18 @@ export class Repository implements Disposable { const limit = scopedConfig.get('statusLimit', 10000); - const { status, didHitLimit } = await this.repository.getStatus({ limit, ignoreSubmodules }); + const { status, statusLength, didHitLimit } = await this.repository.getStatus({ limit, ignoreSubmodules }); + + if (didHitLimit) { + /* __GDPR__ + "statusLimit" : { + "ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "limit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, + "statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ + this.telemetryReporter.sendTelemetryEvent('statusLimit', { ignoreSubmodules: String(ignoreSubmodules) }, { limit, statusLength }); + } const config = workspace.getConfiguration('git'); const shouldIgnore = config.get('ignoreLimitWarning') === true;