Application Insights not reporting custom properties and call stack - c#

I'm logging different exceptions with the following method that accepts the exception as well as some context information string.
public void LogException(string notes, Exception e)
{
var properties = new Dictionary<string, string>()
{
{ "notes", notes }
};
telemetry.TrackException(e, properties);
}
The exceptions are reported correctly, but they are missing
The custom property "notes"
The call stack

is the exception actually thrown ? are you catching that exception? if you just do
client.TrackException( new Exception() );
there won't be a stack frames on some OS's / runtimes.
but if you do
try
{
throw new Exception();
}
catch (Exception e)
{
client.TrackException( e );
}
you will get a stack trace. something about the act of throwing the exception actually populates the underlying frame the sdk uses.
for your custom property, that should be showing up right away, although sometime's there's a lag between a new custom property being sent the first time, and when it shows up in metadata as a field to display. Also, you're limited to 200 distinct named custom properties, so if you've already sent 200 other properties, the "notes" field will just get thrown away.
in general for UWP / release / .net native, you should still have frames, they just won't be very readable, they'll be memory addresses, but there's still a stack of them, and if you have the pdb's, etc, you can reverse engineer what was where.
though the above looks like "catastrophic failure" exceptions that might not have stack frames available?

Related

How does the console obtain the stack trace of an exception?

In C# I'm trying to modify the StackTrace property of a custom exception I created. For this, I just override the StackTrace getter and it seems to be working (Exception has it as a virtual method, so it should work). This is my custom exception:
class CustomTimeoutException : Exception
{
private string oldStack;
public CustomTimeoutException(string message, String stack)
: base(message)
{
oldStack = stack;
}
public override string StackTrace
{
get
{
return oldStack;
}
}
public override string Message
{
get
{
return "lalalala2";
}
}
public override System.Collections.IDictionary Data
{
get
{
return null;
}
}
}
I'm using this class the following way:
class Program
{
static void Main(string[] args)
{
try
{
Program p = new Program();
p.throwTimeout2();
}
catch(TimeoutException e)
{
CustomTimeoutException tor = new CustomTimeoutException(e.Message + "with more", e.StackTrace);
Console.WriteLine(tor);
Console.WriteLine(tor.StackTrace);
throw tor;
}
}
public void throwTimeout2()
{
throwTimeout();
}
public void throwTimeout()
{
throw new TimeoutException("this is a message ");
}
}
When I write the property StackTrace to the console, it prints the StackTrace of the TimeoutException, which means it's in fact overriding it. But, when the console shows the error, the StackTrace is not the one it gets from my property, yet the Message is the one it gets from the Message property I'm also overriding.
So, where does the console get the StackTrace of the exception from? I'm using Visual Studio for running.
(Note: one thing I still really don't understand about your question is that, while you seem to be asking for a way to affect how an exception is reported to the console, you also say that you have some "tool" that apparently has access to the Exception object itself and is reporting on the inner-most exception, i.e. following the InnerException property chain until it reaches the last one. These two statements seem to be in contradiction with each other, so I'm not really sure I completely understand the question. Still, I spent some time looking into it, and will share what I have regardless. :) .)
IMHO, there is not a good way to do what you want. There is an ugly way (see below), but I don't recommend it. Especially since your main limitation is the "tool that uses the message"; it is IMHO a very bad idea to go changing production code just to suit some tool. That path leads to big maintenance headaches, if not outright buggy code.
If you really must change the exception message, you should just bite the bullet and toss the entire stack trace text you want to preserve into the message as well. Trying to mess around with the stack trace of the eventually-thrown exception itself is bad news.
That said…
If you were to add diagnostic calls to Console.WriteLine() to your method overrides, you would confirm (as you've probably already guessed) that the StackTrace property is not called when the exception is re-thrown and reported by the CLR to the console. Overriding the property is not going to help.
There are at least two problems with trying that strategy:
The StackTrace property is just a string containing formatted information about the stack trace. The Exception object does actually contain a private field _stackTrace. When you execute the throw statement with an Exception object, the CLR stores the current stack trace information into this field. You would have to find some way to overwrite this field after the fact, to fake a throw site different from the actual one.
The CLR exception handling leverages existing Windows exception handling infrastructure. One of the first things that happens when an exception is thrown is the exception handling code attempts to find a handler up the stack. If it fails to find one, then you get the "Unhandled Exception:" message. But note that in the process, the stack has not been unwound. Thus, the exception handling code does not even need to inspect the Exception object at all to determine the throw site; the stack is still there, and its state can be reported directly. There is literally nothing you can do with the Exception object that would affect reporting, if indeed the exception handling code is looking directly at the stack state.
Now, as it happens, for the version of .NET I'm running on my Windows 8.1 machine, it appears that the CLR is reporting the stack trace as stored in the Exception object and not directly inspecting the stack, per option #2 above. So something like this actually works:
ExceptionWrapper class
class ExceptionWrapper : Exception
{
private readonly string _trace;
private readonly string _message;
private readonly string _toString;
private readonly object _stackTrace;
public ExceptionWrapper(Exception e)
{
_trace = e.StackTrace;
_message = e.Message + ", wrapped";
_toString = e.ToString();
_stackTrace = typeof(Exception).GetField("_stackTrace",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e);
}
public override string StackTrace { get { return _trace; } }
public override string Message
{
get
{
typeof(Exception)
.GetField("_stackTrace", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, _stackTrace);
return _message;
}
}
public override string ToString() { return _toString; }
}
Test program
class Program
{
static void Main(string[] args)
{
try
{
M1();
}
catch (Exception e)
{
throw;
}
}
private static void M1()
{
try
{
M();
}
catch (Exception e)
{
throw new ExceptionWrapper(e);
}
}
static void M()
{
throw new Exception("test exception");
}
}
There is a very significant caveat though. This works only because of two specific facts:
The CLR is not taking advantage of the current stack state, but instead is trusting the Exception object to contain correct stack information in the _stackTrace field.
The CLR calls the Message getter of the Exception object before retrieving the stack trace. This gives the object an opportunity to overwrite the _stackTrace field before the CLR accesses it for the purpose of reporting the stack trace.
Both of these are, as near as I can tell, completely undocumented implementation details. The second one in particular is very fragile; while I can see why the CLR might always have to stick with the first detail, I see no reason at all that Microsoft (never mind other implementors of the CLS) should feel compelled to preserve the behavior in the second point.
Writing code that relies on these implementation details is just asking for trouble. Whatever the broader goal here is, I simply cannot imagine it would be worthwhile to suffer the risk of breaking your project for this need. IMHO, it would be much more reasonable to simply rewrite this "tool" you are trying to accommodate.
Tools are (or at least should be) inherently simple in nature, and not only would rewriting it allow you to produce the results you want without mucking around with private implementation details in third-party code, it would also give you the chance to a) add new features, such as providing options for controlling how to process exception data (e.g. looking at something other than the inner-most exception), and b) have a tool for which you do have the source code, with which you can make further improvements in the future.
I strongly advise that you not paint yourself into this particular corner. :)

Bubble up exception with custom properties and log with serilog

I came across a situation where I thought it'd be good to rethrow an exception, appending additional information to it (for example in properties in a custom exception) that when caught further up the stack would be logged with the additional info in the form of properties of a message template in Serilog - the end goal being so I can then filter on those properties in Seq. This scenario might be a warning that I need to rethink my exception handling, but I thought I'd ask if this has been done before with Serilog? Recommended/discouraged?
Update
Here's an example scenario:
Using serilog and Seq we apply a "Department" property to a log so that a department can easily see all exceptions that are likely their responsibility.
Now the app for this scenario basically does two things:
Step 1: Query data.
Step 2: If no exceptions in step 1, post it somewhere else.
A few layers deep in step 1 there is a particular exception that I know is the responsibility of a particular department. So I'd like to apply a department property to this exception when it is logged but at the same time have it be caught further up the stack so that the exception prevents continuation of everything else. Also, I only want to log the exception once.
My current approach is to define a custom exception with a dictionary that can hold properties for the log:
public class ExtPropertiesException : Exception
{
// Constructors here...
/// <summary>
/// Properties to log with the error message
/// </summary>
public Dictionary<string, object> ExtProperties { get; set; }
}
So when I catch an exception I know is a particular departments responsibility I rethrow it as ExtPropertiesException or as an exception that inherits it, attaching the original exception as the inner exception.
Then back up the stack where the general steps are I've got a catch:
try
{
// Step 1
// Step 2
}
catch (ExtPropertiesException ex)
{
if (ex.ExtProperties != null)
{
foreach (var prop in ex.ExtProperties)
{
logger = logger.ForContext(prop.Key, prop.Value);
}
}
logger.Error(ex, ex.Message);
}
This seems to be doing what I need, but it'd be great to know whether it's a best practice before repeating it elsewhere.
I was initially doing the logs and applying the property at the time I catch the exception and then just returning false or null to indicate failure and abandon future steps, however I've found it difficult for unit testing as I can't determine the type of errors from outside the methods.
Thanks
Best practice is hard to judge; rather than the ForContext() code above you can do:
try
{
// Step 1
// Step 2
}
catch (ExtPropertiesException ex)
{
logger.Error(ex, "Exception caught, data is {#ExtProperties}", ex.ExtProperties);
}
This will attach a single "object" property to the event, carrying the data from ExtProperties.

How to find exceptions thrown by OpenReadAsync method

Consider the following code:
using (IRandomAccessStream stream = await storageFile.OpenReadAsync())
{
using (DataReader dataReader = new DataReader(stream))
{
uint length = (uint)stream.Size;
await dataReader.LoadAsync(length);
txtbox.Text = dataReader.ReadString(length);
}
}
storageFile.OpenReadAsync may throw exception, System.IO.FileNotFoundException is one possible exception type. MSDN topic StorageFile.OpenReadAsync http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.storagefile.openreadasync doesn't contain list of exception types thrown by this method. How can I find this information from documentation? I can catch an Exception type, but this is poor programming practice.
In cases where it is impossible to find all list of exceptions I usually use approach from VS SDK ErrorHandler.IsCriticalException:
try
{
// ...
}
catch(Exception e)
{
if (ErrorHandler.IsCriticalException(e))
{
throw;
}
// log it or show something to user
}
You can decompile the Microsoft.VisualStudio.Shell.11.0.dll to find the list of exceptions, which ErrorHandler defines as Critical:
StackOverflowException
AccessViolationException
AppDomainUnloadedException
BadImageFormatException
DivideByZeroException
In the case of Windows Runtime I think that it will be good also to verify some of the HResult values in Exception, like E_OUTOFMEMORY, E_ABORT, E_FAIL, and maybe something else.
Also I found that BugSense is awesome help for logging exceptions. I use it not only for unhandled exception, but also for situations like this, where I have no idea what this method can throw. It allows to send custom logging (including exceptions) with BugSenseHandler.Instance.LogException, so I just collect information about different kind of exceptions (including exceptions with some unexpected HResult) and make some improvements for my app in each release.

exception call stack truncated without any re-throwing

I have an unusual case where I have a very simple Exception getting thrown and caught in the same method. It isn’t re-thrown (the usual kind of problem naïve programmers have). And yet its StackFrame contains only one the current method. Here’s what it looks like:
at (my class).MyMethod() in C:\(my file path and line)
In reality there are probably 30 methods leading up to this in the VS2010 debugger's call stack, going across half a dozen different assemblies. It seems impossible for all that to have been optimized out. Moreover, this code is built in debug mode, without optimizations, for .NET 4. I even have (based on http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx) .ini files (including one named [app].vshost.ini) in the same folder containing:
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
Also, the method calls are not at the end of methods, so tail-recursion optimization seems further unlikely.
As to how it is called: there are no uses of reflection on the call stack, no Invoke() or BeginInvoke() of any kind. This is just a long chain of calls from a button click. The click handler is about 10 calls down the call stack. Beneath that you have the usual WndProc, NativeWindow.Callback, native/managed transitions, and message loop. This is ultimately inside a ShowDialog() call which is run from a C# EXE assembly.
Now, I found that I can construct instances of the StackTrace class in my catch handler, and if I pass the Exception object, the call stack is also short. If instead I just call new StackTrace() with no arguments, it yields a complete call stack.
I’ve used Reflector in an attempt to debug into the internals of the Exception class getting thrown and its call stack constructed, but I couldn’t set breakpoints in Exception or in StackTrace. I could set them in Environment.GetStackTrace() and this method (which Exception calls) does not appear to get called during the construction and throwing process, but I don’t know if the debugger is really working properly. (This method does get triggered for some other things though, so I'm not sure what to make of it.)
Here’s an excerpt of the method:
private void MyMethod()
{
...
try
{
throw new ApplicationException("Test failure");
}
catch (Exception e)
{
StackTrace stackTrace1 = new StackTrace(e);
StackTrace stackTrace2 = new StackTrace(e, false);
StackTrace stackTrace3 = new StackTrace(e, true);
StackTrace stackTrace4 = new StackTrace();
string STs = stackTrace1.ToString() + "\n---\n"
+ stackTrace2.ToString() + "\n---\n"
+ stackTrace3.ToString() + "\n---\n"
+ stackTrace4.ToString();
Log(EventSeverity.Debug, STs);
...
}
}
It’s really pretty simple: Throw exception, catch and log it.
I get the same results either in the debugger or when running standalone—a one-line call stack. And I know I have seen this problem elsewhere in our code base. Previously I had assumed it was due to re-throwing exceptions, but in a lot of cases it we log right inside the initial catch block. I’m quite baffled and all the web searching I’ve done hasn’t produce anything.
This is a little too much to add as a comment to the answer provided, but here's some more information:
I now see that this behavior is discussed at
http://dotnetthoughts.wordpress.com/2007/10/27/where-did-my-exception-occur/ and that it is actually described at http://msdn.microsoft.com/en-us/library/system.exception.stacktrace.aspx (though I think one could easily miss what they're saying there).
So I guess my "solution" will be a little hit-or-miss. We have a central method we usually call to format exceptions. Inside that method, I'll create a new StackTrace() both with and without the Exception object. Then I'll look for the method that is at the bottom of the Exception's stack trace, and display everything beneath that in the new StackTrace(), indicating it was called by that series of calls.
The down side of course is that if this method isn't used, the information won't be there. But I had to expect some kind of code change somewhere.
When an exception is thrown, only a partial stack trace will be used in the Exception.StackTrace property. The stack only shows calls up until the method that is catching the exception. To get the full stack (as you have noted) you should create a new StackTrace() object.
I can't find any links on it at the moment but I believe the stack trace is built by walking up the stack while throwing the exception. Once the exception reaches a catch block, the stack stops being compiled. Therefore, you only get a partial stack.
Typically, a catch block is not concerned with who called it, but where the exception is originating from.

c# "finally" block that only runs on exceptions

Edit: I have looked at the answers code: NONE of them do what I want (I've checked). It would seem that there is no way to do what I want in native c#. I guess that's not a disaster just a shame given that .NET does support it (see accepted answer).
Thanks all.
I have c# code (part of a test framework that will never be run except under a debugger) like this who's point it to avoid actually catching the exception as that makes debugging the code in the unwound part of the stack a royal pain.
Bool bad = true;
try
{
MightThrow();
bad = false;
}
finally
{
if(bad) DoSomeLoggingOnFailure();
//// Does not catch!!!!
//// exception continues to unwind stack.
//// Note that re throwing the exception is NOT
//// the same as not catching it in the first place
}
is their a better way to do this?
A solution would have to behave exactly like that under the debugger with regards to un-caught exceptions. It would have to result in the only one first chance exception and the debugger breaking at the point that the exception was originally thrown, not in a catch block.
Specifically I need the debugger on un-caught exceptions to stop a in side MightThrow.
The following doesn't work because it fails to have the debugger break in the correct place
try { ... } catch { throw; }
And this doesn't work because it loses stack info (and also breaks in the wrong place).
try { ... } catch(Exception e) { throw e; }
I known that in D I could use a scope(failure) block
So, in .NET what you're asking for is theoretically possible, but it's not going to be easy.
CIL actually defines five types of exception handling block! The try, catch and finally ones you're used to in C#, and two others:
filter - similar to a catch block but can run arbitrary code to determine whether it wants to handle the error, rather than just matching on type. This block has access to the exception object, and has the same effect on the exception stack trace as a catch block.
fault - similar to a finally block, however it is only run when an exception occurs. This block does not have access to the exception object, and has no effect on the exception stack trace (just like a finally block).
filter is available in some .NET languages (e.g. VB.NET, C++/CLI) but is not available in C#, unfortunately. However I don't know of any language, other than CIL, that allows the fault block to be expressed.
Because it can be done in IL means not all is lost, though. In theory you could use Reflection.Emit to dynamically emit a function that has a fault block and then pass the code you want to run in as lambda expressions (i.e. one for the try part, one for the fault part, and so on), however (a) this isn't easy, and (b) I'm unconvinced that this will actually give you a more useful stack trace than you're currently getting.
Sorry the answer isn't a "here's how to do it" type thing, but at least now you know! What you're doing now is probably the best approach IMHO.
Note to those saying that the approach used in the question is 'bad practice', it really isn't. When you implement a catch block you're saying "I need to do something with the exception object when an exception occurs" and when you implement a finally you're saying "I don't need the exception object, but I need to do something before the end of the function".
If what you're actually trying to say is "I don't need the exception object, but I need to do something when an exception occurs" then you're half way between the two, i.e. you want a fault block. As this isn't available in C#, you don't have an ideal option, so you may as well choose the option that is less likely to cause bugs by forgetting to re-throw, and which doesn't corrupt the stack trace.
How about this:
try
{
MightThrow();
}
catch
{
DoSomethingOnFailure();
throw; // added based on new information in the original question
}
Really, that's all you did. Finally is for things that must run regardless of whether an exception occurred.
[Edit: Clarification]
Based on the comments you've been mentioning, you want the exception to continue being thrown without modifying its original stack trace. In that case, you want to use the unadorned throw that I've added. This will allow the exception to continue up the stack and still allow you to handle part of the exception. Typical cases might be to close network connections or files.
[Second edit: Regarding your clarification]
Specifically I need the debugger on
un-caught exceptions to stop at the
original point of the throw (in
MightThrow) not in the catch block.
I would argue against ever breaking a best-practice (and yes, this is a best-practice for partially handling exceptions) to add some minor value to your debugging. You can easily inspect the exception to determine the location of the exception throw.
[Final edit: You have your answer]
kronoz has thoughtfully provided you with the answer you sought. Don't break best practices -- use Visual Studio properly! You can set Visual Studio to break exactly when an exception is thrown. Here's official info on the subject.
I was actually unaware of the feature, so go give him the accepted answer. But please, don't go trying to handle exceptions in some funky way just to give yourself a hand debugging. All you do is open yourself up to more bugs.
If you're interested in the debugger simply stopping precisely where the exception occurred then have you considered first-chance exceptions?
If you open Tools|Exceptions then tick the Common Language Runtime Exceptions box, the debugger will stop at the point of exception regardless of any try/catch/finally blocks.
Update: You can specify the precise exception you wish to catch by expanding the [+] tree in the Exceptions dialog. Though of course it will fire every time any exception of the specified type[s] occur[s], you can switch it on and off at will even in the middle of a debugging session, so with judicious use of breakpoints you can get it to do your bidding. I used it successfully to get around the 'target of an invocation has thrown an exception' ball ache originating from using reflection to instantiate objects. Very useful tool in such circumstances. Also note the locals and stack trace should be firmly available as far as I recall (just did a quick test and they are available), so no problems there.
Of course if you want to log things then that is outside the scope of an IDE debugger; and in which case first-chance exceptions won't help you!
Give it a go at least; I found them very useful and they might be more appropriate for your issue than you think.
What's wrong with:
try
{
MightThrow();
}
catch
{
DoSomthingOnFailure();
throw;
}
For code that should only run on exceptions, use the catch block:
try
{
MightThrow();
}
catch (Exception ex)
{
// this runs only when there was an exception
DoSomthingOnFailure();
// pass exception on to caller
throw;
}
finally
{
// this runs everytime
Cleanup();
}
This is what you want. It will only call this method when an error occurs, and the "throw" statement will re-throw the exception with the callstack intact.
try
{
MightThrow();
}
catch
{
DoSomthingOnFailure();
throw;
}
A "finally" block that runs only on failure is called "catch" (with no parameters). :-)
Now, there is a small caveat. If you want to have a specialised "catch" case for a particular exception type and have a generic "catch" that works for all exceptions, you'll have to do a bit of a custom logic.
Thus, I would do something like:
try
{
MightThrow();
}
catch(MyException ex)
{
// Runs on MyException
MySpecificFailureHandler()
// Since we have handled the exception and can't execute the generic
// "catch" block below, we need to explicitly run the generic failure handler
MyGenericFailureHandler()
}
catch
{
// Runs on any exception hot handled specifically before
MyGenericFailureHandler()
// If you want to mimic "finally" behavior and propagate the exception
// up the call stack
throw;
}
finally
{
// Runs on any failure or success
MyGenericCleanupHandler();
}
Every example so far is losing the original StackTrace according to my tests. Here's a solution that should work for you.
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
try
{
MightThrow();
}
catch (Exception ex)
{
DoSomethingOnFailure();
PreserveStackTrace(ex);
throw;
}
How about only catching an exception that "MightThrow" does not throw?
Bool bad = true;
try
{
MightThrow();
bad = false;
}
catch (SomePrivateMadeUpException foo)
{
//empty
}
finally
{
if(bad) DoSomeLoggingOnFailure();
}
Let me recap your requirements the way I understand them:
You want some code that is run only when an exception is generated, in order to do some logging.
You want to run your test framework under debugger and break at the point at which the exception is thrown.
To meet your first requirement, you should write the code the way everybody suggested - using parameterless catch and throw.
To meet your second requirement while using the parameterless catch, you could configure your debugger to break when an exception is throw, not only when there's an unhandled exception. I suspect you know how to do it, but I'll put it here for answer completeness: in VS you can do that in Debug -> Exception -> Common Language Runtime Exceptions -> check the Thrown checkbox.
If you know that your app throws a lot of handled exceptions, that might not be an option for you. At that point, your only choice left to meet your first requirement is to either write the code to use finally for exception logging purposes or look into the direct IL emitting route as Greg Beech suggests.
However, whether the finally code is being executed depends on the debugger you are using. In particular, VS will break on an unhadled exception before the finally is executed and will not let you continue. Thus, unless you detach from the process at that point, your logging code will never be executed. In other words, the second requirement will interfere with meeting the first requirement.
You could encapsulate your logic in a custom class, something like:
public class Executor
{
private readonly Action mainActionDelegate;
private readonly Action onFaultDelegate;
public Executor(Action mainAction, Action onFault)
{
mainActionDelegate = mainAction;
onFaultDelegate = onFault;
}
public void Run()
{
bool bad = true;
try
{
mainActionDelegate();
bad = false;
}
finally
{
if(bad)
{
onFaultDelegate();
}
}
}
}
And use it as:
new Executor(MightThrow, DoSomeLoggingOnFailure).Run();
Hope this helps.
Isn't this the same as:
try
{
MightThrow();
}
catch (Exception e)
{
DoSomethingOnFailure();
throw e;
}
?
You could write, or have someone write for you, a small assembly in VB.net which implements a TryFaultCatchFinally(of T) method that accepts four delegates:
TryMethod -- An Action(of T) to perform the "Try" block.
FaultMethod -- A Predicate(Of T, Exception) which, if an exception occurs, will be called before any "finally" blocks run; if it returns true the Catch block will run--otherwise it won't.
CatchMethod -- An Action(Of T, Exception) to be performed if an exception had occurred and FaultMethod returned true; happens after "finally" blocks run.
FinallyMethod -- An Action(OF T, Exception, Boolean) to be performed as a "Finally" block. The passed-in exception will be null if TryMethod ran to completion, or will hold the exception that caused it to exit. The Boolean will be true if the exception was caught, or false otherwise.
Note that when the FaultMethod is executed, one may be able to examine the state of objects that caused the exception, before such state is destroyed by Finally blocks. One must use some care when doing this (any locks that were held when the exception was thrown will continue to be held) but the ability may still sometimes be handy, especially when debugging.
I'd suggest the routine look something like:
Shared Sub TryFaultCatchFinally(Of T)(ByVal TryProc As Action(Of T), _
ByVal FaultProc As Func(Of T, Exception, Boolean), _
ByVal CatchProc As Action(Of T, Exception), _
ByVal FinallyProc As Action(Of T, Exception, Boolean), _
ByVal Value As T)
Dim theException As Exception = Nothing
Dim exceptionCaught As Boolean = False
Try
TryProc(Value)
theException = Nothing
exceptionCaught = False
Catch Ex As Exception When CopyExceptionAndReturnFalse(Ex, theException) OrElse FaultProc(Value, Ex)
exceptionCaught = True
CatchProc(Value, Ex)
Finally
FinallyProc(Value, theException, exceptionCaught)
End Try
End Sub
No, I think this is a common idiom the way you have it.
EDIT
To be clear, the "catch" then "rethrow" strategies offer the same run-time semantics, however they change the experience when the VS debugger is attached. Tooling and maintenance is important; debugging often requires you to 'catch all first-chance exceptions' and if you end up with lots of 'spurious' first-chance exceptions due to catch-then-rethrow in your code, it really hurts the ability to debug the code. This idiom is about interacting well with the tooling, as well as clearly expressing the intent (you don't want to 'catch', decide can't handle, and rethrow, instead you just want to log that an exception did happen but let it pass on by).
Have you considered using the DebuggerStepThrough attribute?
http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggerstepthroughattribute.aspx
[DebuggerStepThrough]
internal void MyHelper(Action someCallback)
{
try
{
someCallback();
}
catch(Exception ex)
{
// Debugger will not break here
// because of the DebuggerStepThrough attribute
DoSomething(ex);
throw;
}
}
With exception filters added in C# 6, one option is to make use of a false returning exception filter, like so:
void PerformMightThrowWithExceptionLogging()
{
try
{
MightThrow();
}
catch (Exception e) when (Log(e))
{
// Cannot enter here, since Log returns false.
}
}
bool Log(Exception e)
{
DoSomeLoggingOnFailure(e);
// Return false so the exception filter is not matched, and therefore the stack is kept.
// This means the debugger breaks where the exception actually happened, etc.
return false;
}
See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch for more details on exception filters.
try
{
MightThrow();
}
catch
{
DoSomethingOnFailure();
}

Categories

Resources