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

Conversation

grokys
Copy link
Contributor

@grokys grokys commented Jun 9, 2016

Adds metrics to the extension.

grokys and others added 22 commits May 30, 2016 13:17
Some of it commented out using //// for things that aren't supported in
GHfVS - needs a tidy up when we decide what we're going to track. Also
not used anywhere yet!
As it may not exist.
For some reason the UsageTracker isn't being found by MEF though.
Also only include metrics service if build is internal.
And increment launch count when package initialized.
Also add supporting for generating complex properties like UIState
using ReactiveUI;
using Rothko;

#pragma warning disable CS0649
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you still need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope! Well spotted 👓! Will remove.

this.cache = cache;
this.repositoryHosts = repositoryHosts;
this.userSettings = userSettings;
this.client = (IMetricsService)serviceProvider.GetService(typeof(IMetricsService));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to blow up miserably if the service is not found. You need to use TryGetService<IMetricsService> here.

Use a dictionary of metrics keys with setter methods as values, so that
BuildUsageModel and ClearCounters use the same data and never go out of
sync.
public class UsageTracker : IUsageTracker
{
// Whenever you add a counter make sure it gets added to _both_
// BuildUsageModel and ClearCounters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a sign that we need to refactor the code so that we don't accidentally forget things. I opened #359 to fix this, comments welcome!

Copy link
Contributor Author

@grokys grokys Jun 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this came from the GHfW codebase - the changes in your PR look good to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, I forgot this is mostly GHfW code. Cool, feel free to merge it in then!

So use TryGetService. Also removed unnecessary braces.
else
{
return Observable.Return(Unit.Default);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's those pesky braces again...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, these come from GHfW - do you want me to change them or should we be avoiding unnecessary differences with GHfW when the other code is identical?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GHfW is not going to have any changes to this code, so it doesn't matter if it's identical or not (and it's not anymore anyway with the other PR coming in). I'd rather have consistency in the code base and make this ours.

To be very honest, I'd rather have

            return client != null
                ? Observable.Defer(() =>
                {
                    log.Info("User has enabled sending anonymized usage statistics to GitHub");
                    return client.SendOptIn();
                })
                : Observable.Return(Unit.Default);

because that's the form that we use the most in logic like this around the codebase, but that doesn't get on my nerves as much as those floating braces 😉

@shana
Copy link
Contributor

shana commented Jun 14, 2016

Make sure to test this without the script submodule to make sure we're not accidentally relying on internal things and breaking external contributors.

List of metrics keys with setter methods
@shana
Copy link
Contributor

shana commented Jun 14, 2016

Also, if there's no MetricsService, then all the client. accesses will go 💥 , so need to check all those nulls ftw.

@shana
Copy link
Contributor

shana commented Jun 14, 2016

/me kicks the ⚽ over

@grokys
Copy link
Contributor Author

grokys commented Jun 16, 2016

Just checked this with scripts de-inited. TryGetService<T> needed a [return: AllowNull] but now that is fixed, seems to work fine.

@shana
Copy link
Contributor

shana commented Jun 22, 2016

This is looking fine and I'm 👍 for merging, but we can get a couple of tests for the clear counters and usage model building there, to make sure we're clearing everything that matters and that the built model has all the relevant keys? There might be tests already in the Desktop repo that we can reuse.

Steven Kirk added 6 commits June 23, 2016 13:53
Metrics may need to be sent before our plugin is fully loaded, so we can't use Rx.
…trics

Conflicts:
	src/GitHub.App/Services/UsageTracker.cs
And remove accidentally committed file in there.
{
var result = File.Exists(storePath) ?
SimpleJson.DeserializeObject<UsageStore>(File.ReadAllText(storePath)) :
new UsageStore { Model = new UsageModel() };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing is going to need exception handling, there's multiple things that can go wrong here. I'd like to follow the same pattern that https://github.com/github/VisualStudio/blob/master/src/GitHub.VisualStudio/Services/ConnectionManager.cs has - delegates for IO methods that can be mocked later on by our unit tests, a separate method that ensures the cache file exists, and splitting up reading/writing from serializing/deserializing, since one can fail because of the OS but the latter can fail because we break the format (and we can catch that in unit tests)

Note: ConnectionManager is not checking for IO exceptions at the moment. It's never failed because that would require two VS instances running at the same time and accessing ConnectionManager at exactly the same time, which is unlikely to happen (most cache accesses are user-initiated when logging in, so a user would have to login at the same time in two VS instances, unlikely). However, metrics are timer based which means the likelihood of two VS instances racing for the same file access could potentially be higher, so we need to watch out for this. Any crashes here will crash VS.

Steven Kirk and others added 5 commits June 23, 2016 15:59
As there can be >1 instance of VS running. There is still the
possibility of race conditions here but as they would be unlikely and
the impact would be minimal, I'm tempted to just accept the possibility
rather than make the code more complex.
This is the same pattern used by `ConnectionManager` which allows us to
pass in mocked rothko interfaces for testing, but ensure that the rothko
dependency isn't loaded at runtime. However in GitHub.Exports we don't
have and (possibly) don't want a dependency on rothko so we need to work
out what to do there.
@shana shana force-pushed the feature/metrics branch from bc9c43d to 3900a41 Compare July 1, 2016 10:27
@shana
Copy link
Contributor

shana commented Jul 1, 2016

Merging this in. We need to do a build with this, deploy the central metrics branch and test a few metrics, so we can have some data to graph.

@shana shana merged commit fc02bbe into master Jul 1, 2016
@shana shana deleted the feature/metrics branch July 1, 2016 10:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants