Added some usage details (#4711)

* added some details

* remove unused import

* added new metrics, removed churn

* merged master and code review comments

* code review comments

* normalized days to calendar days/weeks/months

* cleaned up code

* changed comment to start required check for PR

* fix failing test

* fix test

* removed null assignment

* fix null test script
This commit is contained in:
Aditya Bist
2019-04-11 12:07:20 -07:00
committed by GitHub
parent 4f8d14ed3e
commit bcea1b66be

View File

@@ -13,42 +13,156 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
export class SqlTelemetryContribution extends Disposable implements IWorkbenchContribution {
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@ITelemetryService private telemetryService: ITelemetryService,
@IStorageService storageService: IStorageService
) {
super();
const dailyLastUseDate = Date.parse(storageService.get('telemetry.dailyLastUseDate', StorageScope.GLOBAL, '0'));
const weeklyLastUseDate = Date.parse(storageService.get('telemetry.weeklyLastUseDate', StorageScope.GLOBAL, '0'));
const monthlyLastUseDate = Date.parse(storageService.get('telemetry.monthlyLastUseDate', StorageScope.GLOBAL, '0'));
const dailyLastUseDate: number = Date.parse(storageService.get('telemetry.dailyLastUseDate', StorageScope.GLOBAL, '0'));
const weeklyLastUseDate: number = Date.parse(storageService.get('telemetry.weeklyLastUseDate', StorageScope.GLOBAL, '0'));
const monthlyLastUseDate: number = Date.parse(storageService.get('telemetry.monthlyLastUseDate', StorageScope.GLOBAL, '0'));
const firstTimeUser: boolean = dailyLastUseDate === Date.parse('0');
let today = new Date().toUTCString();
let todayString: string = new Date().toUTCString();
// daily user event
if (this.diffInDays(Date.parse(today), dailyLastUseDate) >= 1) {
if (this.didDayChange(dailyLastUseDate)) {
// daily first use
telemetryService.publicLog('telemetry.dailyFirstUse', { dailyFirstUse: true });
storageService.store('telemetry.dailyLastUseDate', today, StorageScope.GLOBAL);
storageService.store('telemetry.dailyLastUseDate', todayString, StorageScope.GLOBAL);
}
// weekly user event
if (this.diffInDays(Date.parse(today), weeklyLastUseDate) >= 7) {
if (this.didWeekChange(weeklyLastUseDate)) {
// weekly first use
telemetryService.publicLog('telemetry.weeklyFirstUse', { weeklyFirstUse: true });
storageService.store('telemetry.weeklyLastUseDate', today, StorageScope.GLOBAL);
storageService.store('telemetry.weeklyLastUseDate', todayString, StorageScope.GLOBAL);
}
// monthly user events
if (this.diffInDays(Date.parse(today), monthlyLastUseDate) >= 30) {
/* send monthly uses once the user launches on a day that's in a month
after the last time we sent a monthly usage count */
const monthlyUseCount: number = storageService.getNumber('telemetry.monthlyUseCount', StorageScope.GLOBAL, 0);
if (this.didMonthChange(monthlyLastUseDate)) {
telemetryService.publicLog('telemetry.monthlyUse', { monthlyFirstUse: true });
storageService.store('telemetry.monthlyLastUseDate', today, StorageScope.GLOBAL);
}
// the month changed, so send the user usage type event based on monthly count for last month
// and reset the count for this month
let lastMonthDate = new Date(monthlyLastUseDate);
this.sendUsageEvent(monthlyUseCount, lastMonthDate);
const wasActiveLastMonth: boolean = storageService.getBoolean('telemetry.wasActiveLastMonth', StorageScope.GLOBAL, false);
if (firstTimeUser) {
// new user
this.sendGrowthTypeEvent(UserGrowthType.NewUser, lastMonthDate);
}
// continuing or returning user
this.sendGrowthTypeEvent(wasActiveLastMonth ? UserGrowthType.ContinuingUser : UserGrowthType.ReturningUser, lastMonthDate);
// set wasActiveUserLastMonth
storageService.store('telemetry.wasActiveLastMonth', true, StorageScope.GLOBAL);
// reset the monthly count for the new month
storageService.store('telemetry.monthlyUseCount', 1, StorageScope.GLOBAL);
storageService.store('telemetry.monthlyLastUseDate', todayString, StorageScope.GLOBAL);
} else {
// if it's the same month, increment the monthly use count
storageService.store('telemetry.monthlyUseCount', monthlyUseCount + 1, StorageScope.GLOBAL);
}
}
private didDayChange(lastUseDateNumber: number): boolean {
let nowDateNumber: number = Date.parse(new Date().toUTCString());
if (this.diffInDays(nowDateNumber, lastUseDateNumber) >= 1) {
return true;
} else {
let nowDate = new Date(nowDateNumber);
let lastUseDate = new Date(lastUseDateNumber);
return nowDate.getUTCDay() !== lastUseDate.getUTCDay();
}
}
private didWeekChange(lastUseDateNumber: number): boolean {
let nowDateNumber: number = Date.parse(new Date().toUTCString());
if (this.diffInDays(nowDateNumber, lastUseDateNumber) >= 7) {
return true;
} else {
let nowDate = new Date(nowDateNumber);
let lastUseDate = new Date(lastUseDateNumber);
return nowDate.getUTCDay() < lastUseDate.getUTCDay();
}
}
private didMonthChange(lastUseDateNumber: number): boolean {
let nowDateNumber: number = Date.parse(new Date().toUTCString());
if (this.diffInDays(nowDateNumber, lastUseDateNumber) >= 30) {
return true;
} else {
let nowDate = new Date(nowDateNumber);
let lastUseDate = new Date(lastUseDateNumber);
return nowDate.getUTCMonth() !== lastUseDate.getUTCMonth();
}
}
private diffInDays(nowDate: number, lastUseDate: number): number {
return (nowDate - lastUseDate) / (24 * 3600 * 1000);
return (nowDate - lastUseDate) / (3600 * 1000 * 24);
}
// Usage Metrics
private sendUsageEvent(monthlyUseCount: number, lastMonthDate: Date): void {
let userUsageType: UserUsageType | undefined;
if (monthlyUseCount === 1) {
userUsageType = UserUsageType.TireKicker;
} else if (monthlyUseCount >= 2 && monthlyUseCount <= 11) {
userUsageType = UserUsageType.Occasional;
} else if (monthlyUseCount >= 12 && monthlyUseCount <= 20) {
userUsageType = UserUsageType.Engaged;
} else if (monthlyUseCount > 20) {
userUsageType = UserUsageType.Dedicated;
}
if (userUsageType) {
this.telemetryService.publicLog('telemetry.userUsage',
{ userType: userUsageType, monthlyUseCount: monthlyUseCount, month: lastMonthDate.getMonth().toString(), year: lastMonthDate.getFullYear().toString() });
}
}
// Growth Metrics
private sendGrowthTypeEvent(growthType: UserGrowthType, lastMonthDate: Date): void {
this.telemetryService.publicLog('telemetry.userGrowthType', {
userGrowthType: growthType, month: lastMonthDate.getMonth().toString(), year: lastMonthDate.getFullYear().toString()
});
}
}
/**
Growth Metrics
Active here means opened app atleast 1 time in a month
*/
export enum UserGrowthType {
// first time opening app
NewUser = 1,
// was active before, wasn't active last month, but is active this month
ReturningUser = 2,
// was active last month and this month
ContinuingUser = 3
}
/**
* Usage Metrics
* TireKicker = 1 day/month
* Occasional = 2-11 days/month
* Engaged = 12-20 days/month
* Dedicated = 20+ days/month
*/
export enum UserUsageType {
/* 1 day per month */
TireKicker = 1,
/* 2-11 days per month */
Occasional = 2,
/* 12-20 days per month */
Engaged = 3,
/* 20+ days per month */
Dedicated = 4
}
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SqlTelemetryContribution, LifecyclePhase.Starting);