Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enumerate all .NET Framework installations #572

Merged
merged 10 commits into from
Nov 6, 2020

Conversation

lucas-zimerman
Copy link
Collaborator

@lucas-zimerman lucas-zimerman commented Nov 4, 2020

Closes #531

When running a .NET Application, Sentry will add a list of installed .NET Frameworks with the events.
The operation can be opted-out.

@lucas-zimerman lucas-zimerman marked this pull request as draft November 4, 2020 18:28
@codecov-io
Copy link

codecov-io commented Nov 4, 2020

Codecov Report

Merging #572 (71713bd) into main (2e3a433) will increase coverage by 0.15%.
The diff coverage is 81.57%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #572      +/-   ##
==========================================
+ Coverage   62.88%   63.04%   +0.15%     
==========================================
  Files         176      179       +3     
  Lines        4985     5019      +34     
  Branches      854      861       +7     
==========================================
+ Hits         3135     3164      +29     
- Misses       1624     1627       +3     
- Partials      226      228       +2     
Impacted Files Coverage Δ
...rmAbstractions/NetFxInstallationsEventProcessor.cs 72.72% <72.72%> (ø)
src/Sentry/SentryOptionsExtensions.cs 68.62% <75.00%> (+0.54%) ⬆️
...ntry/Integrations/NetFxInstallationsIntegration.cs 100.00% <100.00%> (ø)
...Sentry/PlatformAbstractions/FrameworkInfo.NetFx.cs 71.23% <100.00%> (ø)
...ormAbstractions/FrameworkInstallationExtensions.cs 100.00% <100.00%> (ø)
src/Sentry/SentryOptions.cs 93.10% <100.00%> (+0.18%) ⬆️
...ntry/PlatformAbstractions/FrameworkInstallation.cs 50.00% <0.00%> (+25.00%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2e3a433...d28b296. Read the comment docs.

Copy link
Member

@bruno-garcia bruno-garcia left a comment

Choose a reason for hiding this comment

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

Looking nice! Got a screenshot of what it looks like in Sentry?

CHANGELOG.md Outdated Show resolved Hide resolved
internal static readonly string NetFxInstallationsKey = ".NET Framework";

private readonly Lazy<IEnumerable<FrameworkInstallation>> _netFxInstallations =
new Lazy<IEnumerable<FrameworkInstallation>>(() => FrameworkInfo.GetInstallations());
Copy link
Member

Choose a reason for hiding this comment

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

You need to consider multiple threads will capture events concurrently.

Use ExecutionAndPublication here.

Another point is error handling. You need to make sure an exception thrown in Lazy ctor doesn't crash the whole process (or in this case since we'd handle it in the SDK, drop the whole event).

As stated earlier, a Lazy<T> object always returns the same object or value that it was initialized with, and therefore the Value property is read-only. If you enable exception caching, this immutability also extends to exception behavior. If a lazy-initialized object has exception caching enabled and throws an exception from its initialization method when the Value property is first accessed, that same exception is thrown on every subsequent attempt to access the Value property

We need to enable such caching, and when trying to access Value do that under a try catch.
If an exception is thrown, log that with options.DiagnosticLogger?.LogError and flip a flag in the object (a field) so that you don't try to access Value again. From that point a LogDebug is enough just to note that we skipped the integration.

}

[Fact]
public void Process_NetFxInstallationsKeyExist_UnchangedSentryEvent()
Copy link
Member

Choose a reason for hiding this comment

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

We need a test that verifies we can actually add something to the context. Maybe call FrameworkInfo.GetInstallations() and assert the items are there.

Ideally another that we can serialize the contexts once you add the items to that list.

@bruno-garcia
Copy link
Member

Also check if it returns anything because this code will run on Mono on Linux for example and there's no .NET Framework there

@lucas-zimerman
Copy link
Collaborator Author

lucas-zimerman commented Nov 5, 2020

Looking nice! Got a screenshot of what it looks like in Sentry?

Sure, for the next Commit :D

EDIT: I don't think there'll be any problems with mono due to #if NETFX (and GetInstallations is using Win32 code)

image

@bruno-garcia
Copy link
Member

EDIT: I don't think there'll be any problems with mono due to #if NETFX (and GetInstallations is using Win32 code)

#if NETFX is true on Mono

@lucas-zimerman
Copy link
Collaborator Author

EDIT: I don't think there'll be any problems with mono due to #if NETFX (and GetInstallations is using Win32 code)

#if NETFX is true on Mono

Yeah, the test is failing because of that :c

@lucas-zimerman lucas-zimerman marked this pull request as ready for review November 6, 2020 00:07
{
var versionsDictionary = new Dictionary<string, string>();
var installations = FrameworkInfo.GetInstallations();
foreach (var profile in installations.Select(p => p.Profile).Distinct())
Copy link
Member

Choose a reason for hiding this comment

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

Why Distinct here? Isn't this going to work on the object references?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The goal of distinct is to avoid repeating keys to be inserted into the Dictionary and the foreach loop will then group the releases by profiles.

Copy link
Member

Choose a reason for hiding this comment

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

But you're doing Distinct on a reference type so unless GetHashCode and Equals was overriden, it will dedupe on the reference.

Copy link
Member

Choose a reason for hiding this comment

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

Confirmed offline that it fails with dupe key in Map otherwise

Copy link
Member

@bruno-garcia bruno-garcia left a comment

Choose a reason for hiding this comment

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

LGTM. Just clarifying if that Distinct does something or not

{
var versionsDictionary = new Dictionary<string, string>();
var installations = FrameworkInfo.GetInstallations();
foreach (var profile in installations.Select(p => p.Profile).Distinct())
Copy link
Member

Choose a reason for hiding this comment

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

But you're doing Distinct on a reference type so unless GetHashCode and Equals was overriden, it will dedupe on the reference.

@@ -103,7 +103,7 @@ public static IEnumerable<FrameworkInstallation> GetInstallations()
if (version != null && versionKey.GetInt("Install") == 1)
{
// 1.0 to 3.5
Version.TryParse(version, out var parsed);
_ = Version.TryParse(version, out var parsed);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this some sort of analyzer we have that warns about this? I don't see it on my end and I'd say adding those _ makes things more noisy.

Copy link
Member

Choose a reason for hiding this comment

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

I get the warnings too. Visual Studio

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

image
The Sentry project is a bit noisy about unused return parameters, it compiles, but leaves a lot of error messages here. (I am running Visual Studio Community without any addon)

@bruno-garcia bruno-garcia merged commit db6d590 into getsentry:main Nov 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enumerate all .NET Framework installations
4 participants