소스 검색

Adds basic telemetry

main
Eric Amodio 7 년 전
부모
커밋
4e67a84531
6개의 변경된 파일176개의 추가작업 그리고 7개의 파일을 삭제
  1. +3
    -0
      src/commands/commands.ts
  2. +4
    -1
      src/constants.ts
  3. +17
    -6
      src/extension.ts
  4. +3
    -0
      src/logger.ts
  5. +44
    -0
      src/system/object.ts
  6. +105
    -0
      src/telemetry.ts

+ 3
- 0
src/commands/commands.ts 파일 보기

@ -1,6 +1,7 @@
'use strict';
import { commands, Disposable, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode';
import { BuiltInCommands } from '../constants';
import { Telemetry } from '../telemetry';
export type Commands = 'gitlens.closeUnchangedFiles' | 'gitlens.copyMessageToClipboard' | 'gitlens.copyShaToClipboard' |
'gitlens.diffDirectory' | 'gitlens.diffWithBranch' | 'gitlens.diffWithNext' | 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' |
@ -54,6 +55,7 @@ export abstract class Command extends Disposable {
}
protected _execute(...args: any[]): any {
Telemetry.trackEvent(this.command);
return this.execute(...args);
}
@ -74,6 +76,7 @@ export abstract class EditorCommand extends Disposable {
}
private _execute(editor: TextEditor, edit: TextEditorEdit, ...args: any[]): any {
Telemetry.trackEvent(this.command);
return this.execute(editor, edit, ...args);
}

+ 4
- 1
src/constants.ts 파일 보기

@ -31,4 +31,7 @@ export const WorkspaceState = {
GitLensVersion: 'gitlensVersion' as WorkspaceState,
RepoPath: 'repoPath' as WorkspaceState,
SuppressGitVersionWarning: 'suppressGitVersionWarning' as WorkspaceState
};
};
export const ExtensionId = 'eamodio.gitlens';
export const ApplicationInsightsKey = 'a9c302f8-6483-4d01-b92c-c159c799c679';

+ 17
- 6
src/extension.ts 파일 보기

@ -1,4 +1,5 @@
'use strict';
import { Objects } from './system';
import { commands, ExtensionContext, extensions, languages, Uri, window, workspace } from 'vscode';
import { BlameabilityTracker } from './blameabilityTracker';
import { BlameActiveLineController } from './blameActiveLineController';
@ -14,18 +15,20 @@ import { ShowBlameHistoryCommand, ShowFileHistoryCommand } from './commands';
import { ShowLastQuickPickCommand, ShowQuickBranchHistoryCommand, ShowQuickCurrentBranchHistoryCommand, ShowQuickCommitDetailsCommand, ShowQuickCommitFileDetailsCommand, ShowQuickFileHistoryCommand, ShowQuickRepoStatusCommand} from './commands';
import { ToggleCodeLensCommand } from './commands';
import { Keyboard } from './commands';
import { IAdvancedConfig, IBlameConfig } from './configuration';
import { BuiltInCommands, WorkspaceState } from './constants';
import { IConfig } from './configuration';
import { ApplicationInsightsKey, BuiltInCommands, ExtensionId, WorkspaceState } from './constants';
import { GitContentProvider } from './gitContentProvider';
import { Git, GitService } from './gitService';
import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider';
import { Logger } from './logger';
import { Telemetry } from './telemetry';
// this method is called when your extension is activated
export async function activate(context: ExtensionContext) {
Logger.configure(context);
Telemetry.configure(ApplicationInsightsKey);
const gitlens = extensions.getExtension('eamodio.gitlens');
const gitlens = extensions.getExtension(ExtensionId);
const gitlensVersion = gitlens.packageJSON.version;
// Workspace not using a folder. No access to git repo.
@ -38,10 +41,10 @@ export async function activate(context: ExtensionContext) {
const rootPath = workspace.rootPath.replace(/\\/g, '/');
Logger.log(`GitLens(v${gitlensVersion}) active: ${rootPath}`);
const config = workspace.getConfiguration('gitlens');
const gitPath = config.get<IAdvancedConfig>('advanced').git;
const config = workspace.getConfiguration('').get<IConfig>('gitlens');
const gitPath = config.advanced.git;
configureCssCharacters(config.get<IBlameConfig>('blame'));
configureCssCharacters(config.blame);
let repoPath: string;
try {
@ -59,6 +62,12 @@ export async function activate(context: ExtensionContext) {
const gitVersion = Git.gitInfo().version;
Logger.log(`Git version: ${gitVersion}`);
const telemetryContext: { [id: string]: any } = Object.create(null);
telemetryContext.name = ExtensionId;
telemetryContext.version = gitlensVersion;
telemetryContext.git_version = gitVersion;
Telemetry.setContext(telemetryContext);
notifyOnUnsupportedGitVersion(context, gitVersion);
notifyOnNewGitLensVersion(context, gitlensVersion);
@ -110,6 +119,8 @@ export async function activate(context: ExtensionContext) {
context.subscriptions.push(new ShowQuickFileHistoryCommand(git));
context.subscriptions.push(new ShowQuickRepoStatusCommand(git, repoPath));
context.subscriptions.push(new ToggleCodeLensCommand(git));
Telemetry.trackEvent('initialized', Objects.flatten(config, 'config', true));
}
// this method is called when your extension is deactivated

+ 3
- 0
src/logger.ts 파일 보기

@ -1,6 +1,7 @@
'use strict';
import { ExtensionContext, OutputChannel, window, workspace } from 'vscode';
import { IAdvancedConfig } from './configuration';
import { Telemetry } from './telemetry';
const ConfigurationName = 'gitlens';
const OutputChannelName = 'GitLens';
@ -58,6 +59,8 @@ export class Logger {
if (level !== OutputLevel.Silent) {
output.appendLine([ex, ...params].join(' '));
}
Telemetry.trackException(ex);
}
static warn(message?: any, ...params: any[]): void {

+ 44
- 0
src/system/object.ts 파일 보기

@ -12,4 +12,48 @@ export namespace Objects {
yield [key, o[key]];
}
}
export function flatten(o: any, prefix: string = '', stringify: boolean = false): { [key: string]: any } {
let flattened = Object.create(null);
_flatten(flattened, prefix, o, stringify);
return flattened;
}
function _flatten(flattened: { [key: string]: any }, key: string, value: any, stringify: boolean = false) {
if (Object(value) !== value) {
if (stringify) {
if (value == null) {
flattened[key] = null;
}
else if (typeof value === 'string') {
flattened[key] = value;
}
else {
flattened[key] = JSON.stringify(value);
}
}
else {
flattened[key] = value;
}
}
else if (Array.isArray(value)) {
let len = value.length;
for (let i = 0; i < len; i++) {
_flatten(flattened, `${key}[${i}]`, value[i], stringify);
}
if (len === 0) {
flattened[key] = null;
}
}
else {
let isEmpty = true;
for (let p in value) {
isEmpty = false;
_flatten(flattened, key ? `${key}.${p}` : p, value[p], stringify);
}
if (isEmpty && key) {
flattened[key] = null;
}
}
}
}

+ 105
- 0
src/telemetry.ts 파일 보기

@ -0,0 +1,105 @@
'use strict';
import { Disposable, workspace } from 'vscode';
import * as vscode from 'vscode';
import * as appInsights from 'applicationinsights';
import * as os from 'os';
let _reporter: TelemetryReporter;
export class Telemetry extends Disposable {
static configure(key: string) {
_reporter = new TelemetryReporter(key);
}
static setContext(context?: { [key: string]: string }) {
_reporter && _reporter.setContext(context);
}
static trackEvent(name: string, properties?: { [key: string]: string }, measurements?: { [key: string]: number; }) {
_reporter && _reporter.trackEvent(name, properties, measurements);
}
static trackException(ex: Error) {
_reporter && _reporter.trackException(ex);
}
}
export class TelemetryReporter extends Disposable {
private _client: typeof appInsights.client;
private _context: { [key: string]: string };
private _disposable: Disposable;
private _enabled: boolean;
constructor(key: string) {
super(() => this.dispose());
appInsights.setup(key)
.setAutoCollectConsole(false)
.setAutoCollectExceptions(false)
.setAutoCollectPerformance(false)
.setAutoCollectRequests(false);
(appInsights as any).setAutoCollectDependencies(false)
.setOfflineMode(true);
this._client = appInsights.start().client;
this.setContext();
this._stripPII(appInsights.client);
this._onConfigurationChanged();
const subscriptions: Disposable[] = [];
subscriptions.push(workspace.onDidChangeConfiguration(this._onConfigurationChanged, this));
this._disposable = Disposable.from(...subscriptions);
}
dispose() {
this._disposable && this._disposable.dispose();
}
setContext(context?: { [key: string]: string }) {
if (!this._context) {
this._context = Object.create(null);
// Add vscode properties
this._context.code_language = vscode.env.language;
this._context.code_version = vscode.version;
// Add os properties
this._context.os = os.platform();
this._context.os_version = os.release();
}
if (context) {
Object.assign(this._context, context);
}
Object.assign(this._client.commonProperties, this._context);
}
trackEvent(name: string, properties?: { [key: string]: string }, measurements?: { [key: string]: number; }) {
if (!this._enabled) return;
this._client.trackEvent(name, properties, measurements);
}
trackException(ex: Error) {
if (!this._enabled) return;
this._client.trackException(ex);
}
private _onConfigurationChanged() {
this._enabled = workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true);
}
private _stripPII(client: typeof appInsights.client) {
if (client && client.context && client.context.keys && client.context.tags) {
const machineNameKey = client.context.keys.deviceMachineName;
client.context.tags[machineNameKey] = '';
}
}
}

불러오는 중...
취소
저장