Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 6c852c2

Browse files
authored
Merge pull request #1130 from github/refactor/usage-tracker
Make it easier to add new usage metrics.
2 parents 85c169f + d6a1e42 commit 6c852c2

29 files changed

+641
-417
lines changed

src/GitHub.App/Models/RepositoryHost.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ public IObservable<AuthenticationResult> LogInFromCache()
7676
{
7777
var user = await loginManager.LoginFromCache(Address, ApiClient.GitHubClient);
7878
var accountCacheItem = new AccountCacheItem(user);
79-
usage.IncrementLoginCount().Forget();
79+
80+
await usage.IncrementCounter(x => x.NumberOfLogins);
8081
await ModelService.InsertUser(accountCacheItem);
8182

8283
if (user != null)
@@ -107,7 +108,8 @@ public IObservable<AuthenticationResult> LogIn(string usernameOrEmail, string pa
107108
{
108109
var user = await loginManager.Login(Address, ApiClient.GitHubClient, usernameOrEmail, password);
109110
var accountCacheItem = new AccountCacheItem(user);
110-
usage.IncrementLoginCount().Forget();
111+
112+
await usage.IncrementCounter(x => x.NumberOfLogins);
111113
await ModelService.InsertUser(accountCacheItem);
112114

113115
if (user != null)

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ async Task<IPullRequestModel> PushAndCreatePR(IRepositoryHost host,
537537
await Task.Delay(TimeSpan.FromSeconds(5));
538538

539539
var ret = await host.ModelService.CreatePullRequest(sourceRepository, targetRepository, sourceBranch, targetBranch, title, body);
540-
await usageTracker.IncrementUpstreamPullRequestCount();
540+
await usageTracker.IncrementCounter(x => x.NumberOfUpstreamPullRequests);
541541
return ret;
542542
}
543543

src/GitHub.App/Services/RepositoryCloneService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public async Task CloneRepository(
6464
try
6565
{
6666
await vsGitServices.Clone(cloneUrl, path, true, progress);
67-
await usageTracker.IncrementCloneCount();
67+
await usageTracker.IncrementCounter(x => x.NumberOfClones);
6868
}
6969
catch (Exception ex)
7070
{

src/GitHub.App/ViewModels/GistCreationViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ IObservable<Gist> OnCreateGist(object unused)
9191
newGist.Files.Add(FileName, SelectedText);
9292

9393
return gistPublishService.PublishGist(apiClient, newGist)
94-
.Do(_ => usageTracker.IncrementCreateGistCount().Forget())
94+
.Do(_ => usageTracker.IncrementCounter(x => x.NumberOfGists).Forget())
9595
.Catch<Gist, Exception>(ex =>
9696
{
9797
if (!ex.IsCriticalException())

src/GitHub.App/ViewModels/PullRequestDetailViewModel.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ public async Task Load(string remoteRepositoryOwner, IPullRequestModel pullReque
454454

455455
if (firstLoad)
456456
{
457-
usageTracker.IncrementPullRequestOpened().Forget();
457+
usageTracker.IncrementCounter(x => x.NumberOfPullRequestsOpened).Forget();
458458
}
459459

460460
if (!isInCheckout)
@@ -604,19 +604,37 @@ IObservable<Unit> DoCheckout(object unused)
604604
.GetDefaultLocalBranchName(LocalRepository, Model.Number, Model.Title)
605605
.SelectMany(x => pullRequestsService.Checkout(LocalRepository, Model, x));
606606
}
607-
}).Do(_ => usageTracker.IncrementPullRequestCheckOutCount(IsFromFork).Forget());
607+
}).Do(_ =>
608+
{
609+
if (IsFromFork)
610+
usageTracker.IncrementCounter(x => x.NumberOfForkPullRequestsCheckedOut).Forget();
611+
else
612+
usageTracker.IncrementCounter(x => x.NumberOfLocalPullRequestsCheckedOut).Forget();
613+
});
608614
}
609615

610616
IObservable<Unit> DoPull(object unused)
611617
{
612618
return pullRequestsService.Pull(LocalRepository)
613-
.Do(_ => usageTracker.IncrementPullRequestPullCount(IsFromFork).Forget());
619+
.Do(_ =>
620+
{
621+
if (IsFromFork)
622+
usageTracker.IncrementCounter(x => x.NumberOfForkPullRequestPulls).Forget();
623+
else
624+
usageTracker.IncrementCounter(x => x.NumberOfLocalPullRequestPulls).Forget();
625+
});
614626
}
615627

616628
IObservable<Unit> DoPush(object unused)
617629
{
618630
return pullRequestsService.Push(LocalRepository)
619-
.Do(_ => usageTracker.IncrementPullRequestPushCount(IsFromFork).Forget());
631+
.Do(_ =>
632+
{
633+
if (IsFromFork)
634+
usageTracker.IncrementCounter(x => x.NumberOfForkPullRequestPushes).Forget();
635+
else
636+
usageTracker.IncrementCounter(x => x.NumberOfLocalPullRequestPushes).Forget();
637+
});
620638
}
621639

622640
class CheckoutCommandState : IPullRequestCheckoutState

src/GitHub.App/ViewModels/RepositoryCreationViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ IObservable<Unit> OnCreateRepository(object state)
273273
SelectedAccount,
274274
BaseRepositoryPath,
275275
repositoryHost.ApiClient)
276-
.Do(_ => usageTracker.IncrementCreateCount().Forget());
276+
.Do(_ => usageTracker.IncrementCounter(x => x.NumberOfReposCreated).Forget());
277277
}
278278

279279
ReactiveCommand<Unit> InitializeCreateRepositoryCommand()

src/GitHub.App/ViewModels/RepositoryPublishViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ IObservable<ProgressState> OnPublishRepository(object arg)
159159
var account = SelectedAccount;
160160

161161
return repositoryPublishService.PublishRepository(newRepository, account, SelectedHost.ApiClient)
162-
.Do(_ => usageTracker.IncrementPublishCount().Forget())
162+
.Do(_ => usageTracker.IncrementCounter(x => x.NumberOfReposPublished).Forget())
163163
.Select(_ => ProgressState.Success)
164164
.Catch<ProgressState, Exception>(ex =>
165165
{

src/GitHub.Exports/GitHub.Exports.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@
147147
<Compile Include="Models\ICommentModel.cs" />
148148
<Compile Include="Models\IInlineCommentModel.cs" />
149149
<Compile Include="Models\IPullRequestReviewCommentModel.cs" />
150+
<Compile Include="Models\UsageData.cs" />
151+
<Compile Include="Services\IUsageService.cs" />
150152
<Compile Include="Settings\PkgCmdID.cs" />
151153
<Compile Include="ViewModels\IHasErrorState.cs" />
152154
<Compile Include="ViewModels\IHasLoading.cs" />
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
namespace GitHub.Models
4+
{
5+
/// <summary>
6+
/// Wraps a <see cref="UsageModel"/> with a <see cref="LastUpdated"/> field.
7+
/// </summary>
8+
public class UsageData
9+
{
10+
/// <summary>
11+
/// Gets or sets the last update time.
12+
/// </summary>
13+
public DateTimeOffset LastUpdated { get; set; }
14+
15+
/// <summary>
16+
/// Gets the model containing the current usage data.
17+
/// </summary>
18+
public UsageModel Model { get; set; }
19+
}
20+
}
Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Reflection;
23

34
namespace GitHub.Models
45
{
@@ -39,41 +40,26 @@ public class UsageModel
3940

4041
public UsageModel Clone(bool includeWeekly, bool includeMonthly)
4142
{
42-
return new UsageModel
43+
var result = new UsageModel();
44+
var properties = result.GetType().GetRuntimeProperties();
45+
46+
foreach (var property in properties)
4347
{
44-
IsGitHubUser = IsGitHubUser,
45-
IsEnterpriseUser = IsEnterpriseUser,
46-
AppVersion = AppVersion,
47-
VSVersion = VSVersion,
48-
Lang = Lang,
49-
NumberOfStartups = NumberOfStartups,
50-
NumberOfStartupsWeek = includeWeekly ? NumberOfStartupsWeek : 0,
51-
NumberOfStartupsMonth = includeMonthly ? NumberOfStartupsMonth : 0,
52-
NumberOfUpstreamPullRequests = NumberOfUpstreamPullRequests,
53-
NumberOfClones = NumberOfClones,
54-
NumberOfReposCreated = NumberOfReposCreated,
55-
NumberOfReposPublished = NumberOfReposPublished,
56-
NumberOfGists = NumberOfGists,
57-
NumberOfOpenInGitHub = NumberOfOpenInGitHub,
58-
NumberOfLinkToGitHub = NumberOfLinkToGitHub,
59-
NumberOfLogins = NumberOfLogins,
60-
NumberOfPullRequestsOpened = NumberOfPullRequestsOpened,
61-
NumberOfLocalPullRequestsCheckedOut = NumberOfLocalPullRequestsCheckedOut,
62-
NumberOfLocalPullRequestPulls = NumberOfLocalPullRequestPulls,
63-
NumberOfLocalPullRequestPushes = NumberOfLocalPullRequestPushes,
64-
NumberOfForkPullRequestsCheckedOut = NumberOfForkPullRequestsCheckedOut,
65-
NumberOfForkPullRequestPulls = NumberOfForkPullRequestPulls,
66-
NumberOfForkPullRequestPushes = NumberOfForkPullRequestPushes,
67-
NumberOfWelcomeDocsClicks = NumberOfWelcomeDocsClicks,
68-
NumberOfWelcomeTrainingClicks = NumberOfWelcomeTrainingClicks,
69-
NumberOfGitHubPaneHelpClicks = NumberOfGitHubPaneHelpClicks,
70-
NumberOfPRDetailsViewChanges = NumberOfPRDetailsViewChanges,
71-
NumberOfPRDetailsViewFile = NumberOfPRDetailsViewFile,
72-
NumberOfPRDetailsCompareWithSolution = NumberOfPRDetailsCompareWithSolution,
73-
NumberOfPRDetailsOpenFileInSolution = NumberOfPRDetailsOpenFileInSolution,
74-
NumberOfPRReviewDiffViewInlineCommentOpen = NumberOfPRReviewDiffViewInlineCommentOpen,
75-
NumberOfPRReviewDiffViewInlineCommentPost = NumberOfPRReviewDiffViewInlineCommentPost,
76-
};
48+
var cloneValue = property.PropertyType == typeof(int);
49+
50+
if (property.Name == nameof(result.NumberOfStartupsWeek))
51+
cloneValue = includeWeekly;
52+
else if (property.Name == nameof(result.NumberOfStartupsMonth))
53+
cloneValue = includeMonthly;
54+
55+
if (cloneValue)
56+
{
57+
var value = property.GetValue(this);
58+
property.SetValue(result, value);
59+
}
60+
}
61+
62+
return result;
7763
}
7864
}
7965
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using GitHub.Models;
4+
5+
namespace GitHub.Services
6+
{
7+
/// <summary>
8+
/// Provides services for <see cref="IUsageTracker"/>.
9+
/// </summary>
10+
public interface IUsageService
11+
{
12+
/// <summary>
13+
/// Checks whether the last updated date is the same day as today.
14+
/// </summary>
15+
/// <param name="lastUpdated">The last updated date.</param>
16+
/// <returns>True if the last updated date is the same day as today; otherwise false.</returns>
17+
bool IsSameDay(DateTimeOffset lastUpdated);
18+
19+
/// <summary>
20+
/// Checks whether the last updated date is the same week as today.
21+
/// </summary>
22+
/// <param name="lastUpdated">The last updated date.</param>
23+
/// <returns>True if the last updated date is the same week as today; otherwise false.</returns>
24+
bool IsSameWeek(DateTimeOffset lastUpdated);
25+
26+
/// <summary>
27+
/// Checks whether the last updated date is the same month as today.
28+
/// </summary>
29+
/// <param name="lastUpdated">The last updated date.</param>
30+
/// <returns>True if the last updated date is the same month as today; otherwise false.</returns>
31+
bool IsSameMonth(DateTimeOffset lastUpdated);
32+
33+
/// <summary>
34+
/// Starts a timer.
35+
/// </summary>
36+
/// <param name="callback">The callback to call when the timer ticks.</param>
37+
/// <param name="dueTime">The timespan after which the callback will be called the first time.</param>
38+
/// <param name="period">The timespan after which the callback will be called subsequent times.</param>
39+
/// <returns>A disposable used to cancel the timer.</returns>
40+
IDisposable StartTimer(Func<Task> callback, TimeSpan dueTime, TimeSpan period);
41+
42+
/// <summary>
43+
/// Reads the local usage data from disk.
44+
/// </summary>
45+
/// <returns>A task returning a <see cref="UsageData"/> object.</returns>
46+
Task<UsageData> ReadLocalData();
47+
48+
/// <summary>
49+
/// Writes the local usage data to disk.
50+
/// </summary>
51+
Task WriteLocalData(UsageData data);
52+
}
53+
}
Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,15 @@
11
using GitHub.VisualStudio;
22
using System.Runtime.InteropServices;
33
using System.Threading.Tasks;
4+
using System;
5+
using System.Linq.Expressions;
6+
using GitHub.Models;
47

58
namespace GitHub.Services
69
{
710
[Guid(Guids.UsageTrackerId)]
811
public interface IUsageTracker
912
{
10-
Task IncrementLaunchCount();
11-
Task IncrementCloneCount();
12-
Task IncrementCreateCount();
13-
Task IncrementPublishCount();
14-
Task IncrementOpenInGitHubCount();
15-
Task IncrementLinkToGitHubCount();
16-
Task IncrementCreateGistCount();
17-
Task IncrementUpstreamPullRequestCount();
18-
Task IncrementLoginCount();
19-
Task IncrementPullRequestCheckOutCount(bool fork);
20-
Task IncrementPullRequestPullCount(bool fork);
21-
Task IncrementPullRequestPushCount(bool fork);
22-
Task IncrementPullRequestOpened();
23-
Task IncrementWelcomeDocsClicks();
24-
Task IncrementWelcomeTrainingClicks();
25-
Task IncrementGitHubPaneHelpClicks();
26-
Task IncrementPRDetailsViewChanges();
27-
Task IncrementPRDetailsViewFile();
28-
Task IncrementPRDetailsCompareWithSolution();
29-
Task IncrementPRDetailsOpenFileInSolution();
30-
Task IncrementPRReviewDiffViewInlineCommentOpen();
31-
Task IncrementPRReviewDiffViewInlineCommentPost();
13+
Task IncrementCounter(Expression<Func<UsageModel, int>> counter);
3214
}
3315
}

src/GitHub.InlineReviews/Services/InlineCommentPeekService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Tuple<ITextSnapshotLine, ITrackingPoint> GetLineAndTrackingPoint(ITextView textV
157157
ExpandCollapsedRegions(textView, line.Extent);
158158
peekBroker.TriggerPeekSession(textView, trackingPoint, InlineCommentPeekRelationship.Instance.Name);
159159

160-
usageTracker.IncrementPRReviewDiffViewInlineCommentOpen().Forget();
160+
usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentOpen).Forget();
161161

162162
return Tuple.Create(line, trackingPoint);
163163
}

src/GitHub.InlineReviews/Services/PullRequestSessionService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ public async Task<IPullRequestReviewCommentModel> PostReviewComment(
293293
path,
294294
position);
295295

296-
await usageTracker.IncrementPRReviewDiffViewInlineCommentPost();
296+
await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentPost);
297297

298298
return new PullRequestReviewCommentModel
299299
{
@@ -329,7 +329,7 @@ public async Task<IPullRequestReviewCommentModel> PostReviewComment(
329329
body,
330330
inReplyTo);
331331

332-
await usageTracker.IncrementPRReviewDiffViewInlineCommentPost();
332+
await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentPost);
333333

334334
return new PullRequestReviewCommentModel
335335
{

src/GitHub.TeamFoundation.14/Home/GitHubHomeSection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,11 @@ void ShowWelcomeMessage()
154154
{
155155
case "show-training":
156156
visualStudioBrowser.OpenUrl(new Uri(TrainingUrl));
157-
usageTracker.IncrementWelcomeTrainingClicks().Forget();
157+
usageTracker.IncrementCounter(x => x.NumberOfWelcomeTrainingClicks).Forget();
158158
break;
159159
case "show-docs":
160160
visualStudioBrowser.OpenUrl(new Uri(GitHubUrls.Documentation));
161-
usageTracker.IncrementWelcomeDocsClicks().Forget();
161+
usageTracker.IncrementCounter(x => x.NumberOfWelcomeDocsClicks).Forget();
162162
break;
163163
case "dont-show-again":
164164
teamExplorerServices.HideNotification(welcomeMessageGuid);

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@
321321
<Compile Include="Helpers\Browser.cs" />
322322
<Compile Include="Services\JsonConnectionCache.cs" />
323323
<Compile Include="Services\UIProvider.cs" />
324+
<Compile Include="Services\UsageService.cs" />
324325
<Compile Include="Services\UsageTracker.cs" />
325326
<Compile Include="Services\LoginManagerDispatcher.cs" />
326327
<Compile Include="Services\UsageTrackerDispatcher.cs" />

src/GitHub.VisualStudio/GitHubPackage.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,10 @@ async Task<object> CreateService(IAsyncServiceContainer container, CancellationT
230230
}
231231
else if (serviceType == typeof(IUsageTracker))
232232
{
233-
var uiProvider = await GetServiceAsync(typeof(IGitHubServiceProvider)) as IGitHubServiceProvider;
234-
return new UsageTracker(uiProvider);
233+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
234+
var serviceProvider = await GetServiceAsync(typeof(IGitHubServiceProvider)) as IGitHubServiceProvider;
235+
var usageService = serviceProvider.GetService<IUsageService>();
236+
return new UsageTracker(serviceProvider, usageService);
235237
}
236238
else if (serviceType == typeof(IUIProvider))
237239
{

src/GitHub.VisualStudio/Menus/BlameLink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public async void Activate(object data = null)
3030
var browser = ServiceProvider.TryGetService<IVisualStudioBrowser>();
3131
browser?.OpenUrl(link.ToUri());
3232

33-
await UsageTracker.IncrementOpenInGitHubCount();
33+
await UsageTracker.IncrementCounter(x => x.NumberOfOpenInGitHub);
3434
}
3535
}
3636
}

src/GitHub.VisualStudio/Menus/CopyLink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async void Activate(object data = null)
3232
Clipboard.SetText(link);
3333
var ns = ServiceProvider.TryGetService<IStatusBarNotificationService>();
3434
ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage);
35-
await UsageTracker.IncrementLinkToGitHubCount();
35+
await UsageTracker.IncrementCounter(x => x.NumberOfLinkToGitHub);
3636
}
3737
catch
3838
{

src/GitHub.VisualStudio/Menus/OpenLink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public async void Activate(object data = null)
2828
var browser = ServiceProvider.TryGetService<IVisualStudioBrowser>();
2929
browser?.OpenUrl(link.ToUri());
3030

31-
await UsageTracker.IncrementOpenInGitHubCount();
31+
await UsageTracker.IncrementCounter(x => x.NumberOfOpenInGitHub);
3232
}
3333
}
3434
}

0 commit comments

Comments
 (0)