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

SLVS-1723 Introduce log contexts #5913

Open
wants to merge 14 commits into
base: feature/hardening-q4
Choose a base branch
from

Conversation

georgii-borovinskikh-sonarsource
Copy link
Contributor

@georgii-borovinskikh-sonarsource georgii-borovinskikh-sonarsource commented Dec 19, 2024

Base automatically changed from feature/hardening-q4-6 to master December 20, 2024 10:16
@georgii-borovinskikh-sonarsource georgii-borovinskikh-sonarsource changed the base branch from master to feature/hardening-q4 December 23, 2024 09:07
@georgii-borovinskikh-sonarsource georgii-borovinskikh-sonarsource changed the base branch from feature/hardening-q4 to gb/collections-immutable-reference December 23, 2024 09:16
@@ -119,6 +119,10 @@ public void LogVerbose(string message, params object[] args)
{
// no-op
}

public ILogger ForContext(params string[] context) => 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.

This class is removed in the CFamily branch

Base automatically changed from gb/collections-immutable-reference to feature/hardening-q4 December 24, 2024 09:44
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not really happy with the design decisions as we are creating a lot of instances of the logger and the context, which will increase the memory usage and the performance overhead especially because logging is a very used operation.

I would rather make the LoggerBase and LoggerContextManager Mef exportable components with the creation policy non-shared.
Then the contextManager of a logger can be configured to hold a specific context or to enhance existing contexts.

}
}
[ExcludeFromCodeCoverage]
internal class SystemDebugLoggerWriter : ILoggerWriter

Choose a reason for hiding this comment

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

The class name does not match the file name anymore.

using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.TestInfrastructure;
using SonarLint.VisualStudio.Core.Logging;
using SonarLint.VisualStudio.Integration.Helpers;

namespace SonarLint.VisualStudio.Integration.UnitTests.Helpers
{
[TestClass]
public class SonarLintOutputTests

Choose a reason for hiding this comment

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

The class name is outdated: it no longer matches the class under test

[Export(typeof(ILoggerFactory))]
[PartCreationPolicy(CreationPolicy.NonShared)]
[method: ImportingConstructor]
public class LoggerFactory(ILoggerContextManager loggerContextManager) : ILoggerFactory

Choose a reason for hiding this comment

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

The LoggerFactory is a level an abstraction that does not actually bring any value. It's just used in a test class and in the Container.cs.
Please remove it completely and all test classes related to it

MefTestHelpers.CheckTypeCanBeImported<LoggerContextManager, ILoggerContextManager>();

[TestMethod]
public void MefCtor_CheckIsSingleton() =>

Choose a reason for hiding this comment

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

Test name is wrong

MefTestHelpers.CheckIsNonSharedMefComponent<LoggerContextManager>();

[TestMethod]
public void EmptyContext()

Choose a reason for hiding this comment

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

Suggested change
public void EmptyContext()
public void Ctor_EmptyContext()

}

private static StringBuilder AppendProperty(StringBuilder builder, string property) =>
builder.Append('[').Append(property).Append(']').Append(' ');

Choose a reason for hiding this comment

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

I think this is a lot more readable

Suggested change
builder.Append('[').Append(property).Append(']').Append(' ');
builder.AppendFormat("[{0}] ", property);

builder.Append('[').Append(property).Append(']').Append(' ');

private static StringBuilder AppendPropertyFormat(StringBuilder builder, string property, params object[] args) =>
builder.Append('[').AppendFormat(property, args).Append(']').Append(' ');

Choose a reason for hiding this comment

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

A lot more readable

Suggested change
builder.Append('[').AppendFormat(property, args).Append(']').Append(' ');
builder.AppendFormat("[{0}] ", new StringBuilder().AppendFormat(property, args));

private static StringBuilder AppendProperty(StringBuilder builder, string property) =>
builder.Append('[').Append(property).Append(']').Append(' ');

private static StringBuilder AppendPropertyFormat(StringBuilder builder, string property, params object[] args) =>

Choose a reason for hiding this comment

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

Please make the return type for both AppendProperty void. Or create extension methods for this class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What's the motivation for that?

Choose a reason for hiding this comment

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

The return type of AppendPropertyFormat is not used. Additionally, it feels awkward to receive a stringBuilder instance then return it unchanged.

ILoggerWriter writer,
ILoggerSettingsProvider settingsProvider) : ILogger
{
public ILogger ForContext(params string[] context) =>

Choose a reason for hiding this comment

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

Creating a new instance for each context feels like a very bad design decision as this will increase the memory usage and the performance overhead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not a correct conclusion. The instances are lightweight (partially thanks to immutable lists and lazy string property initialization, but in general they don't hold a lot of data apart from a few object references and the aforementioned property list and formatted string). This will not increase the overhead in any meaningful way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On top of that, most of these instances will be created in user-class constructors and therefore will be long-living.

Copy link
Contributor

Choose a reason for hiding this comment

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

It is a correct conclusion and it will bring more pressure to the garbage collector, which will impact the performance.

On top of that, most of these instances will be created in user-class constructors and therefore will be long-living.

This is correct for the LoggerBase instances. That's why I see no reason why it shouldn't be a Mef component with a non-shared creation policy (which will basically lead to the same thing but without the need of factories).
This is not true, however for the LoggerContextManager and I think we can find better design than just creating instances for each context.

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, that's not true. It will, of course impact the performance, as pretty much every single added allocation or instruction does, but the question is will it impact it in any meaningful way? The answer is no. It has less of an impact on memory than the existing string allocations inside the logger.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Uncustomized logger context manager has references to 2 empty immutable lists and 2 non-initialized lazies...

public string FormatedContext => formatedContext.Value;
public string FormatedVerboseContext => formatedVerboseContext.Value;

public ILoggerContextManager CreateAugmentedContext(IEnumerable<string> additionalContexts) => new LoggerContextManager(contexts.AddRange(additionalContexts), verboseContexts);

Choose a reason for hiding this comment

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

Creating a new instance for each context feels like a very bad design decision as this will increase the memory usage and the performance overhead.

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.

2 participants