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 exception handling (make it consistent and clear) #915

Closed
wants to merge 20 commits into from

Conversation

tetrodoxin
Copy link
Contributor

and refactored respective occurrences.

It's the first shot and definitely object to discuss, but I had to start somewhere.

…nHelper

refactored occurrences of MustBeRethrown()
@tetrodoxin
Copy link
Contributor Author

How can I actually start the tests from command line? Since the VS test runner creates bin/ and obj/ directories which bother source code tests.

@tetrodoxin
Copy link
Contributor Author

Well, I nearly expected something like this, when I left out the configuration exception. So... back to scratch.

@304NotModified
Copy link
Member

Looks really good! 2 things I'm thinking we maybe should handle :

  • throw new Exception maybe a NLog specific one?
  • throw if throw exceptions is false.

@304NotModified
Copy link
Member

Msbuild NLog.proj /t:runtests? (now on mobile)

@304NotModified
Copy link
Member

Maybe you can pass the expected exception as type argument?

Eg

HandleException<TException > where TException = class, new()

PS still on mobile. Ignore the syntax errors :p

@tetrodoxin
Copy link
Contributor Author

So, I'm sort of back after some time at work.
I also thought about using generics with new(), but this way you have absolutely no chance to provide any error message text or inner exception, so the exception thrown would have the correct type, but no further content, which I considered a bad deal.
A factory delegate would be possible too, but I'm not sure if
ex.HandleException(x => new NLogConfigurationException("Error in...", x))
really would be a real benefit.

@tetrodoxin
Copy link
Contributor Author

An idea I head was something like a wrapper NLogWrapperException<TException> which possibly also could be casted to its inner exception (TException) and then extend XUnit's Assert.Throws<TException>() to check for TException and for NLogWrapperException<TException>, so testing would not be a real additional effort.

@304NotModified
Copy link
Member

I also thought about using generics with new(), but this way you have absolutely no chance to provide any error message text or inner exception, so the exception thrown would have the correct type, but no further content, which I considered a bad deal.

Yes you're right! I forgot that Message property is readonly for an Exception.

An idea I head was something like a wrapper NLogWrapperException which possibly also could be casted to its inner exception (TException)

Not sure if this is nice, but...

XUnit's Assert.Throws() to check for TException and for NLogWrapperException, so testing would not be a real additional effort.

This is a nice idea! No need for a cast I think, we can create a ShouldThrows() in NLogTestBase.

edit: this would be a breaking change. Still thinking if we can fix this otherwise....

@304NotModified
Copy link
Member

A factory delegate would be possible too, but I'm not sure if
ex.HandleException(x => new NLogConfigurationException("Error in...", x))
really would be a real benefit.

Or maybe something like:ex.HandException<TException> where TException : IExceptionFactory

and

class ExceptionFactory
{
 static TException  Create<TException > (string message, Exception innermessage)
....

}

@304NotModified
Copy link
Member

Thinking of this from scratch:

bool shouldThrow = ex.LogException();
if(shouldThrow) throw;

but then we're almost back... (MustBeRethrown is only replaced by LogException)

@tetrodoxin
Copy link
Contributor Author

It seems it would be a breaking change in any way we consider it useful. So spare it for later? Just fix the problematic occurences?

@304NotModified
Copy link
Member

It seems it would be a breaking change in any way we consider it useful.

Well not if we extend/rename the MustBeRethrown?

We get really soon complains if introduce a breaking change ;)

@tetrodoxin
Copy link
Contributor Author

If we just extend it the way I tried, we will break some tests that rely on specific exceptions to be thrown, which were the reason for me thinking about adjusting/extending the tests by accepting this wrapper exception. Since we cannot properly rethrow a catched exception outside the catch-block, we're stuck between redesign (breaking change) and very little changes.

@304NotModified
Copy link
Member

We're stuck between redesign (breaking change) and very little changes.

Agree with this. I'm doubting if there will be a huge benefit for the breaking change (compared to the little change) - yes it looks better, but every change in an unit test will result in changes needed by our users. So if we can fix it without breaking change, that's preferred, despite I really liked our approach.

@tetrodoxin
Copy link
Contributor Author

To summarize, by now we are at something like this:

if(ex.LogAndCheckRethrow()) throw;

aren't we? LogAndCheckRethrow() extension method would do right this, the logging and the check, if rethrowing is necessary. This would at least not really break any current behavior but ensure the way it was originally designed, rethrow the exception when rethrowExceptions=true and therefore satisfy issue #277
Tenminste iets, hè?

@304NotModified
Copy link
Member

Yes, I think that is the best option.

Sehr schön! :p

@304NotModified
Copy link
Member

Need some help on this @tetrodoxin ?

@tetrodoxin
Copy link
Contributor Author

I'm abroad these days and seldom online, will be back next week, at the latest.

-------- Original Message --------
From: Julian Verdurmen notifications@github.com
Sent: October 11, 2015 7:36:17 PM CEST
To: NLog/NLog NLog@noreply.github.com
Cc: "Andreas H." github@interlook.de
Subject: Re: [NLog] added HandleException() extension method (#915)

Need some help on this @tetrodoxin ?


Reply to this email directly or view it on GitHub:

#915 (comment)

Andreas Hübner
Sent with Kaiten-Mail on Android.

@304NotModified
Copy link
Member

OK thanks for the info!

@codecov-io
Copy link

Current coverage is 73.17%

Merging #915 into master will increase coverage by +0.25% as of f631942

@@            master    #915   diff @@
======================================
  Files          263     263       
  Stmts        14875   14838    -37
  Branches      1618    1615     -3
  Methods          0       0       
======================================
+ Hit          10847   10858    +11
+ Partial        416     412     -4
+ Missed        3612    3568    -44

Review entire Coverage Diff as of f631942


Uncovered Suggestions

  1. +0.10% via ...anceCounterTarget.cs#170...184
  2. +0.09% via ...argets/FileTarget.cs#1912...1924
  3. +0.08% via ...c/NLog/LogFactory.cs#180...191
  4. See 7 more...

Powered by Codecov. Updated on successful CI builds.

@tetrodoxin
Copy link
Contributor Author

I had to adjust one test class, namely VariableLayoutRendererTests, because it did not fit into the 'expected exception behavior'. It wasn't prepared for exceptions being rethrown, although it was activated in config.

@304NotModified
Copy link
Member

Thanks! I checked the code and have some questions:

I had to adjust one test class, namely VariableLayoutRendererTests, because it did not fit into the 'expected exception behavior'. It wasn't prepared for exceptions being rethrown, although it was activated in config.

I don't fully understand this. Should we change the unit tests for this?

  • In which cases we don't like to log to the internal log? (exception.MustBeRethrown(false))? I prefer to always log to the internal log?
  • In which case we like to call MustRethrowSevere? I think that one should be private? It's a bit unclear when we should use MustRethrowSevere and when MustRethrow. I think I would be nice if it was one method.

@304NotModified 304NotModified changed the title added HandleException() extension method Improve exception handling (make it consistent and clear) Nov 15, 2015
@tetrodoxin
Copy link
Contributor Author

proposal: LogSwallowException.

N.P. Changed that.

proposal: remove unneeded if and combine asignment & declaration of "shallRethrow"
src/NLog/Internal/ExceptionHelper.cs (160)

Oh, I just missed that one. Was a relict of several changes in the code/tries around it.

src/NLog/Common/InternalLogger.cs (341)
please remove "respectExceptions" (not used)

Actually, the mistake was, that respectExceptions wasn't used. I've corrected that.

@tetrodoxin
Copy link
Contributor Author

src/NLog/Internal/ExceptionHelper.cs
I think it's nice to have whole exception details in the log, so exception.toString()?

proposal: always add the exception to the end of the message. So no need to to pass exception twice (implicit and explicit). Need a lot of changes.

Well, I should have hit on it myself. I changed MustBeRethrown() that way, it always appends exception.ToString() and will fold that behavior into the respective method calls in code by refactoring string formatting.

@tetrodoxin
Copy link
Contributor Author

loglevel should be warn? (several places)

Yes and no. MustBeRethrown() uses warn level, if the exception is not to be rethrown, otherwise error level. I read the occurences you pointed out so, that they would produce the same behavior, meaning a warning would have been written, if the rethrow hasn't happened.Since no tests were broken, I considered that behavior plausible.

@tetrodoxin
Copy link
Contributor Author

src/NLog/Config/XmlLoggingConfiguration.cs (331)
is this the same as calling "logsafe"?

I guess you mean LogSwallowExceptions()?
Actually no. Granted, these lines are sort of a bit hacky, but to follow the expected (and test covered) behavior I had to use this combination of calls to MustBeRethrown(). The first one is nearly an equivalent to the former MustRethrowSevere() as it only throws that serious exceptions and does the logging to error level.
The second call is just for encapsulate the check to LogManager.ThrowExceptions to throw a custom exception in that case.

@tetrodoxin
Copy link
Contributor Author

I must admit, I have no idea why Var_default_after_set_null ever passed without setting ThowExceptions to false, because an NullReferenceException is obvious with the current code in VariableLayoutRenderer.Append()

@tetrodoxin
Copy link
Contributor Author

Ok, I can see you changed right this code :-)

@304NotModified
Copy link
Member

let me know when I can review it again :) Thanks!

@304NotModified
Copy link
Member

Yes and no. MustBeRethrown() uses warn level, if the exception is not to be rethrown, otherwise error level.

I was thinking about this. Is Error level not the best way for exceptions? (for all)?

@304NotModified 304NotModified added this to the 4.3 milestone Nov 19, 2015
@304NotModified 304NotModified added the enhancement Improvement on existing feature label Nov 19, 2015
@304NotModified
Copy link
Member

I think #1040 broke this PR :(

@304NotModified
Copy link
Member

If you added as me collaborator, I can help fixing the last stuff. Just let me know.

@304NotModified
Copy link
Member

bit busy on other stuff, will look at this next week

@304NotModified
Copy link
Member

superseded by #1117

@304NotModified
Copy link
Member

@tetrodoxin I like to have this in 4.3, so I'm busy fixing the conflict and some loose ends.

Thanks for the PR!

@tetrodoxin
Copy link
Contributor Author

I am really sorry for being absent that last couple of months and I hope, you at least could make some use of the code snippets, we worked out last year.
Cheers!

@304NotModified
Copy link
Member

Yes, we did :) This feature has been merged in 4.3

Thanks for the contributions!

@tetrodoxin tetrodoxin deleted the issue_277_exception_handling branch March 30, 2016 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvement on existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants