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

Improve EventLogTarget installation logic - handle MaximumKilobytes for apps without elevated privileges #3017

Merged

Conversation

TheCorio
Copy link
Contributor

Remove MaximumKilobytes setting from GetEventLog(), because when app is run without elevated privileges, the method spams exceptions.
Move MaximumKilobytes setting to installation (and initialization) phase, when the application is typically run with elevated privileges.
Add logic to not override a bigger value of MaximumKilobytes, because the Event log can be used by multiple Sources, each having its own space requirements.

Remove MaximumKilobytes setting from GetEventLog(), because when app is run without elevated privileges, the method spams exceptions.
Move MaximumKilobytes setting to installation (and initialization) phase, when the application is typically run with elevated privileges.
Add logic to not override a bigger value of MaximumKilobytes, because the Event log can be used by multiple Sources, each having its own space requirements.
@codecov
Copy link

codecov bot commented Nov 13, 2018

Codecov Report

Merging #3017 into dev will decrease coverage by <1%.
The diff coverage is 71%.

@@          Coverage Diff           @@
##             dev   #3017    +/-   ##
======================================
- Coverage     80%     80%   -<1%     
======================================
  Files        338     341     +3     
  Lines      26615   27014   +399     
  Branches    3521    3586    +65     
======================================
+ Hits       21261   21574   +313     
- Misses      4356    4419    +63     
- Partials     998    1021    +23

@TheCorio
Copy link
Contributor Author

Hi again, @304NotModified, what are the expected actions to address the "codecov/patch" check?

@304NotModified
Copy link
Member

it warns us for the coverage on the new code, it's 17% instead of 50%.

the code is never touched with an unit test, would be nice if we could do that:

image

To improve testability wrap EventLog with EventLogStaticWrapper and EventLogInstanceWrapper - implementations of IEventLogStaticWrapper and IEventLogInstanceWrapper.
Fix spelling, typos, clarify some comments.
Refactor several unit tests into a 'Theory' with InlineData, in particular "TruncatedMessagesShould..." and "SplittedMessagesShould..." tests.
Add unit tests to check MaxKilobytes initialized from configuration, EventLogTarget.MaxKilobytes setter for positive, negative, corner cases.
Add unit tests to check the behaviour during installation using EventLogStaticMock and EventLogInstanceStub.
@TheCorio
Copy link
Contributor Author

Hi, @304NotModified. Could you please check if the codecov/patch actually ran on 84319d6?

@304NotModified 304NotModified self-assigned this Nov 29, 2018
/// Gets or sets the provider of Windows event log static methods to be utilized by <see cref="EventLogTarget"/>.
/// </summary>
/// <remarks>Introduced to improve the testability of the class.</remarks>
protected internal IEventLogStaticWrapper EventLogStaticMethods { get; set; } = EventLogStaticWrapper.Instance;
Copy link
Contributor

@snakefoot snakefoot Dec 3, 2018

Choose a reason for hiding this comment

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

Think it would be nicer if you implemented an internal constructor that took an internal IEventLogWrapper-interface as input parameter. The default constructor would then call the new internal constructor with a private-class-implementation of the IEventLogWrapper-interface. Ofcourse the unit-tests will not be able to test initialization from NLog.config, but I think that is okay. protected internal means that it becomes part of the public interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I get your point on injecting the implementation in the constructor instead of the property. But you mentioned an IEventLogWrapper, do you suggest merging the IEventLogStaticWrapper and IEventLogInstanceWrapper?

Also, you think these new interfaces and implementations should not fall under protected internal?

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 suggest merging the IEventLogStaticWrapper and IEventLogInstanceWrapper?

Yes I would prefer just a single interface. And this interface and the constructor getting it as parameter are both marked as internal-only (Not protected).

Move magic numbers to constants.
Inject the event log wrapper through internal constructor.
Unite the IEventLogStaticWrapper and IEventLogInstanceWrapper into a single IEventLogWrapper.
@TheCorio
Copy link
Contributor Author

TheCorio commented Dec 6, 2018

Hi, @snakefoot. I've addressed your comments in 5017749, but the build failed. Can you, or maybe @304NotModified, assist?

@snakefoot
Copy link
Contributor

Was thinking that all public constructors should call the unified internal constructor:

        private readonly IEventLogWrapper _eventLogWrapper;

        /// <summary>
        /// Initializes a new instance of the <see cref="EventLogTarget"/> class.
        /// </summary>
        public EventLogTarget()
            : this(null, null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EventLogTarget"/> class.
        /// </summary>
        /// <param name="name">Name of the target.</param>
        public EventLogTarget(string name)
            : this(null, null)
        {
            Name = name;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EventLogTarget"/> class.
        /// </summary>
        public EventLogTarget(IAppDomain appDomain)
            : this(null, appDomain)
        {
        }

        internal EventLogTarget(IEventLogWrapper eventLogWrapper, IAppDomain appDomain)
        {
            _eventLogWrapper = eventLogWrapper ?? new EventLogWrapper()
            appDomain = appDomain ?? LogFactory.CurrentAppDomain;
            Source = appDomain.FriendlyName;
            Log = "Application";
            MachineName = ".";
            MaxMessageLength = EventLogMaxMessageLength;
            OptimizeBufferReuse = GetType() == typeof(EventLogTarget);  // Class not sealed, reduce breaking changes
        }

@snakefoot
Copy link
Contributor

@Coriolanuss I know it is weird with the constructor public EventLogTarget(IAppDomain appDomain) but sadly enough it has become part of the public interface. Removing it would be a breaking change, and has to wait for NLog 5.0

We have to keep it until NLog ver. 5.0 where it can be removed. You are welcome to add the obsolete attribute. Ex:

        [Obsolete("This constructor will be removed in NLog 5. Marked obsolete on NLog 4.6")]
        public EventLogTarget(IAppDomain appDomain)
            : this(null, appDomain)
        {
        }

@TheCorio
Copy link
Contributor Author

Hi @snakefoot, I have brought back the constructor. Any other suggestions?

@snakefoot
Copy link
Contributor

snakefoot commented Dec 12, 2018 via email

@TheCorio
Copy link
Contributor Author

It's nice to hear.
@304NotModified, do you have any comments?

Copy link
Member

@304NotModified 304NotModified left a comment

Choose a reason for hiding this comment

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

Looks good! please move the new interfaces/classes (the interface to the "internal" folder and namespace) to new files (don't forget to copy the license header) and then I will merge this one.

PS: builds failed, not sure what's wrong but restarted all of them

@304NotModified
Copy link
Member

No I think it looks great. Especially with the improved tests. But I don't have the final verdict :)

You approval says a lot anyway 👍

Copy link
Member

@304NotModified 304NotModified left a comment

Choose a reason for hiding this comment

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

please move the new interfaces/classes (the interface to the "internal" folder and namespace) to new files (don't forget to copy the license header)

@304NotModified 304NotModified changed the title Improve EventLogTarget installation logic (merged into dev) Improve EventLogTarget installation logic - handle MaximumKilobytes for apps without elevated privileges Dec 28, 2018
@304NotModified 304NotModified added this to the 4.6 milestone Dec 28, 2018
@304NotModified 304NotModified removed their assignment Dec 28, 2018
@304NotModified
Copy link
Member

please move the new interfaces/classes (the interface to the "internal" folder and namespace) to new files (don't forget to copy the license header)

Maybe that isn't that easy with the multi projects now, so fine for now :)

@304NotModified 304NotModified merged commit 49be04f into NLog:dev Dec 30, 2018
@304NotModified
Copy link
Member

304NotModified commented Dec 30, 2018

Merged, thanks for the contribution and unit tests!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvement on existing feature event-log-target
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants