提交 2c185a4f 编写于 作者: C Christof Marti

Add telemetry for clone action (fixes #20570)

上级 154df1b4
......@@ -9,6 +9,7 @@ import { IEventEmitter, EventEmitter } from 'vs/base/common/eventEmitter';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as Events from 'vs/base/common/events';
import Event, { Emitter } from 'vs/base/common/event';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export interface IAction extends IDisposable {
id: string;
......@@ -202,7 +203,7 @@ export class Action implements IAction {
this._order = value;
}
public run(event?: any): TPromise<any> {
public run(event?: any, data?: ITelemetryData): TPromise<any> {
if (this._actionCallback !== void 0) {
return this._actionCallback(event);
}
......
......@@ -15,6 +15,11 @@ export interface ITelemetryInfo {
instanceId: string;
}
export interface ITelemetryData {
from?: string;
[key: string]: any;
}
export interface ITelemetryExperiments {
showNewUserWatermark: boolean;
openUntitledFile: boolean;
......@@ -30,7 +35,7 @@ export interface ITelemetryService {
* Sends a telemetry event that has been privacy approved.
* Do not call this unless you have been given approval.
*/
publicLog(eventName: string, data?: any): TPromise<void>;
publicLog(eventName: string, data?: ITelemetryData): TPromise<void>;
getTelemetryInfo(): TPromise<ITelemetryInfo>;
......
......@@ -7,7 +7,7 @@
import { localize } from 'vs/nls';
import { escapeRegExpCharacters } from 'vs/base/common/strings';
import { ITelemetryService, ITelemetryInfo, ITelemetryExperiments } from 'vs/platform/telemetry/common/telemetry';
import { ITelemetryService, ITelemetryInfo, ITelemetryExperiments, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { ITelemetryAppender, defaultExperiments } from 'vs/platform/telemetry/common/telemetryUtils';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
......@@ -100,7 +100,7 @@ export class TelemetryService implements ITelemetryService {
this._disposables = dispose(this._disposables);
}
publicLog(eventName: string, data?: any): TPromise<any> {
publicLog(eventName: string, data?: ITelemetryData): TPromise<any> {
// don't send events when the user is optout
if (!this._userOptIn) {
return TPromise.as(undefined);
......
......@@ -14,7 +14,7 @@ import { IKeybindingService, KeybindingSource } from 'vs/platform/keybinding/com
import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ITelemetryService, ITelemetryExperiments, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { ITelemetryService, ITelemetryExperiments, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { StorageService } from 'vs/platform/storage/common/storageService';
import * as objects from 'vs/base/common/objects';
......@@ -28,7 +28,7 @@ export const defaultExperiments: ITelemetryExperiments = {
export const NullTelemetryService = {
_serviceBrand: undefined,
_experiments: defaultExperiments,
publicLog(eventName: string, data?: any) {
publicLog(eventName: string, data?: ITelemetryData) {
return TPromise.as<void>(null);
},
isOptedIn: true,
......
......@@ -168,14 +168,15 @@ export function triggerAndDisposeAction(instantitationService: IInstantiationSer
return undefined;
}
const from = args && args.from || 'keybinding';
if (telemetryService) {
telemetryService.publicLog('workbenchActionExecuted', { id: actionInstance.id, from: args && args.from || 'keybinding' });
telemetryService.publicLog('workbenchActionExecuted', { id: actionInstance.id, from });
}
// run action when workbench is created
return partService.joinCreation().then(() => {
try {
return TPromise.as(actionInstance.run()).then(() => {
return TPromise.as(actionInstance.run(undefined, { from })).then(() => {
actionInstance.dispose();
}, (err) => {
actionInstance.dispose();
......
......@@ -16,6 +16,8 @@ import { IGitService } from 'vs/workbench/parts/git/common/git';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import * as url from 'url';
import { remote } from 'electron';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { isPromiseCanceledError } from 'vs/base/common/errors';
const dialog = remote.dialog;
......@@ -29,12 +31,13 @@ export class CloneAction extends Action {
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IMessageService private messageService: IMessageService,
@IWindowsService private windowsService: IWindowsService,
@ITelemetryService private telemetryService: ITelemetryService,
@IWorkspaceContextService private workspaceService: IWorkspaceContextService
) {
super(id, label);
}
run(): TPromise<void> {
run(event?: any, data?: ITelemetryData): TPromise<void> {
return this.quickOpenService.input({
prompt: localize('valid', "Provide a valid git repository URL"),
placeHolder: localize('url', "Repository URL"),
......@@ -50,6 +53,7 @@ export class CloneAction extends Action {
})
.then(url => {
if (!url) {
this.telemetryService.publicLog('gitClone', { ...data, outcome: 'no_URL' });
return TPromise.as(null);
}
......@@ -59,6 +63,7 @@ export class CloneAction extends Action {
});
if (!result || result.length === 0) {
this.telemetryService.publicLog('gitClone', { ...data, outcome: 'no_directory' });
return TPromise.as(null);
}
......@@ -69,14 +74,17 @@ export class CloneAction extends Action {
const clone = always(this.gitService.clone(url, result[0]), () => promise.cancel());
return clone.then(path => {
this.telemetryService.publicLog('gitClone', { ...data, outcome: 'success' });
const forceNewWindow = this.workspaceService.hasWorkspace();
return this.windowsService.openWindow([path], { forceNewWindow, forceReuseWindow: !forceNewWindow });
}).then<void>(null, e => {
if (/already exists and is not an empty directory/.test(e.stderr || '')) {
this.telemetryService.publicLog('gitClone', { ...data, outcome: 'directory_not_empty' });
return TPromise.wrapError(localize('already exists', "Destination repository already exists, please pick another directory to clone to."));
}
this.telemetryService.publicLog('gitClone', { ...data, outcome: isPromiseCanceledError(e) ? 'canceled' : 'error' });
return TPromise.wrapError(e);
});
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册