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

Commit 53d7ad2

Browse files
authored
Merge pull request #441 from github/grokys/login-count-metric
Track login count metric.
2 parents 4d09ce5 + 94171b3 commit 53d7ad2

File tree

5 files changed

+34
-11
lines changed

5 files changed

+34
-11
lines changed

src/GitHub.App/Factories/RepositoryHostFactory.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,31 @@ public class RepositoryHostFactory : IRepositoryHostFactory
1919
readonly IAvatarProvider avatarProvider;
2020
readonly ITwoFactorChallengeHandler twoFactorChallengeHandler;
2121
readonly CompositeDisposable hosts = new CompositeDisposable();
22+
readonly IUsageTracker usage;
2223

2324
[ImportingConstructor]
2425
public RepositoryHostFactory(
2526
IApiClientFactory apiClientFactory,
2627
IHostCacheFactory hostCacheFactory,
2728
ILoginCache loginCache,
2829
IAvatarProvider avatarProvider,
29-
ITwoFactorChallengeHandler twoFactorChallengeHandler)
30+
ITwoFactorChallengeHandler twoFactorChallengeHandler,
31+
IUsageTracker usage)
3032
{
3133
this.apiClientFactory = apiClientFactory;
3234
this.hostCacheFactory = hostCacheFactory;
3335
this.loginCache = loginCache;
3436
this.avatarProvider = avatarProvider;
3537
this.twoFactorChallengeHandler = twoFactorChallengeHandler;
38+
this.usage = usage;
3639
}
3740

3841
public IRepositoryHost Create(HostAddress hostAddress)
3942
{
4043
var apiClient = apiClientFactory.Create(hostAddress);
4144
var hostCache = hostCacheFactory.Create(hostAddress);
4245
var modelService = new ModelService(apiClient, hostCache, avatarProvider);
43-
var host = new RepositoryHost(apiClient, modelService, loginCache, twoFactorChallengeHandler);
46+
var host = new RepositoryHost(apiClient, modelService, loginCache, twoFactorChallengeHandler, usage);
4447
hosts.Add(host);
4548
return host;
4649
}

src/GitHub.App/Models/RepositoryHost.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class RepositoryHost : ReactiveObject, IRepositoryHost
2929
readonly ITwoFactorChallengeHandler twoFactorChallengeHandler;
3030
readonly HostAddress hostAddress;
3131
readonly ILoginCache loginCache;
32+
readonly IUsageTracker usage;
3233

3334
bool isLoggedIn;
3435
readonly bool isEnterprise;
@@ -37,12 +38,14 @@ public RepositoryHost(
3738
IApiClient apiClient,
3839
IModelService modelService,
3940
ILoginCache loginCache,
40-
ITwoFactorChallengeHandler twoFactorChallengeHandler)
41+
ITwoFactorChallengeHandler twoFactorChallengeHandler,
42+
IUsageTracker usage)
4143
{
4244
ApiClient = apiClient;
4345
ModelService = modelService;
4446
this.loginCache = loginCache;
4547
this.twoFactorChallengeHandler = twoFactorChallengeHandler;
48+
this.usage = usage;
4649

4750
Debug.Assert(apiClient.HostAddress != null, "HostAddress of an api client shouldn't be null");
4851
Address = apiClient.HostAddress;
@@ -238,6 +241,7 @@ IObservable<AuthenticationResult> LoginWithApiUser(UserAndScopes userAndScopes)
238241
if (result.IsSuccess())
239242
{
240243
var accountCacheItem = new AccountCacheItem(userAndScopes.User);
244+
usage.IncrementLoginCount();
241245
return ModelService.InsertUser(accountCacheItem).Select(_ => result);
242246
}
243247

src/GitHub.Exports/Services/IUsageTracker.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ public interface IUsageTracker
1010
void IncrementLinkToGitHubCount();
1111
void IncrementCreateGistCount();
1212
void IncrementUpstreamPullRequestCount();
13+
void IncrementLoginCount();
1314
}
1415
}

src/GitHub.Exports/Services/UsageTracker.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ public void IncrementUpstreamPullRequestCount()
126126
SaveUsage(usage);
127127
}
128128

129+
public void IncrementLoginCount()
130+
{
131+
var usage = LoadUsage();
132+
++usage.Model.NumberOfLogins;
133+
SaveUsage(usage);
134+
}
135+
129136
UsageStore LoadUsage()
130137
{
131138
var result = fileExists(storePath) ?

src/UnitTests/GitHub.App/Models/RepositoryHostTests.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public async Task LogsTheUserInSuccessfullyAndCachesRelevantInfo()
3131
var hostCache = new InMemoryBlobCache();
3232
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
3333
var loginCache = new TestLoginCache();
34-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
34+
var usage = Substitute.For<IUsageTracker>();
35+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
3536

3637
var result = await host.LogIn("baymax", "aPassword");
3738

@@ -57,7 +58,8 @@ public async Task DoesNotLogInWhenRetrievingOauthTokenFails()
5758
var hostCache = new InMemoryBlobCache();
5859
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
5960
var loginCache = new TestLoginCache();
60-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
61+
var usage = Substitute.For<IUsageTracker>();
62+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
6163

6264
await Assert.ThrowsAsync<NotFoundException>(async () => await host.LogIn("jiminy", "cricket"));
6365

@@ -85,7 +87,8 @@ public async Task UsesUsernameAndPasswordInsteadOfAuthorizationTokenWhenEnterpri
8587
var hostCache = new InMemoryBlobCache();
8688
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
8789
var loginCache = new TestLoginCache();
88-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
90+
var usage = Substitute.For<IUsageTracker>();
91+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
8992

9093
var result = await host.LogIn("Cthulu", "aPassword");
9194

@@ -126,7 +129,8 @@ public async Task DoesNotFallBackToOldScopesWhenGitHubAndTwoFactorAuthFailsAndEr
126129
var hostCache = new InMemoryBlobCache();
127130
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
128131
var loginCache = new TestLoginCache();
129-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
132+
var usage = Substitute.For<IUsageTracker>();
133+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
130134

131135
await host.LogIn("aUsername", "aPassowrd");
132136

@@ -152,7 +156,8 @@ public async Task RetriesUsingOldScopeWhenAuthenticationFailsAndIsEnterprise()
152156
var hostCache = new InMemoryBlobCache();
153157
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
154158
var loginCache = new TestLoginCache();
155-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
159+
var usage = Substitute.For<IUsageTracker>();
160+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
156161

157162
await host.LogIn("jiminy", "aPassowrd");
158163

@@ -171,7 +176,8 @@ public async Task SupportsGistIsTrueWhenGistScopeIsPresent()
171176
var hostCache = new InMemoryBlobCache();
172177
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
173178
var loginCache = new TestLoginCache();
174-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
179+
var usage = Substitute.For<IUsageTracker>();
180+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
175181

176182
var result = await host.LogIn("baymax", "aPassword");
177183

@@ -188,7 +194,8 @@ public async Task SupportsGistIsFalseWhenGistScopeIsNotPresent()
188194
var hostCache = new InMemoryBlobCache();
189195
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
190196
var loginCache = new TestLoginCache();
191-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
197+
var usage = Substitute.For<IUsageTracker>();
198+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
192199

193200
var result = await host.LogIn("baymax", "aPassword");
194201

@@ -209,7 +216,8 @@ public async Task SupportsGistIsTrueWhenScopesAreNull()
209216
var hostCache = new InMemoryBlobCache();
210217
var modelService = new ModelService(apiClient, hostCache, Substitute.For<IAvatarProvider>());
211218
var loginCache = new TestLoginCache();
212-
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>());
219+
var usage = Substitute.For<IUsageTracker>();
220+
var host = new RepositoryHost(apiClient, modelService, loginCache, Substitute.For<ITwoFactorChallengeHandler>(), usage);
213221

214222
var result = await host.LogIn("baymax", "aPassword");
215223

0 commit comments

Comments
 (0)