I have a multicast OnExceptionAspect from Postsharp which is applied on the assembly level. This naturally means that all methods, upon throwing an exception, will invoke the Aspect.
Within the Aspect I'm logging the exception details including the values of the parameters passed when the exception occured, this is working properly.
However because this is applied to all methods in the assembly a log entry is created for each method in the stack as the exception bubbles up through each.
I'm out of ideas on how to prevent this, initially I was going to compare the exception (to see if it's the same one) but this just seems messy. Someone must have had this problem before, any ideas?
There are two solutions to this problem.
A. Use a thread-static field to store any exception that has already been logged.
[Serializable]
public class MyAspect : OnExceptionAspect
{
[ThreadStatic]
private static Exception lastException;
public override void OnException(MethodExecutionArgs args)
{
if(args.Exception != lastException)
{
string msg = string.Format("{0} had an error # {1}: {2}\n{3}",
args.Method.Name, DateTime.Now,
args.Exception.Message, args.Exception.StackTrace);
Trace.WriteLine(msg);
lastException = args.Exception;
}
}
}
B. Add a tag to the Exception object.
[Serializable]
public class MyAspect : OnExceptionAspect
{
private static object marker = new object();
public override void OnException(MethodExecutionArgs args)
{
if(!args.Exception.Data.Contains(marker))
{
string msg = string.Format("{0} had an error # {1}: {2}\n{3}",
args.Method.Name, DateTime.Now,
args.Exception.Message, args.Exception.StackTrace);
Trace.WriteLine(msg);
args.Exception.Data.Add(marker, marker);
}
}
}
FYI--Gael is a PostSharp guru because he is employed there...just so you are aware.
For what it is worth you can always tell where the exception originated by examining the StackTrace. The StackTrace is made available via args.Exception.StackTrace. You may try what Dustin Davis (another PostSharp employee) recommends here: PostSharp - OnExceptionAspect - Get line number of exception
Parse the StackTrace (via the method outlined here: How to split a stacktrace line into namespace, class, method file and line number?) then compare the args.Method.Name with the parsed results. If your args.Method.Name is the same as the originating method (found via parsing the StackTrace) then you know you should log it otherwise ignore.
Here is some code to make my solution more concrete (building on the prior two solutions cited):
[Serializable]
public class ExceptionWrapper : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
var st = new StackTrace(args.Exception, true);
var frame = st.GetFrame(0);
var lineNumber = frame.GetFileLineNumber();
var methodName = frame.GetMethod().Name;
if(methodName.Equals(args.Method.Name))
{
string msg = string.Format("{0} had an error # {1}: {2}\n{3}",
args.Method.Name, DateTime.Now,
args.Exception.Message, args.Exception.StackTrace);
Trace.WriteLine(msg);
}
}
}
(Or, honestly, you could just use one of Gael's recommended solutions.)
One way i could see this being done would be to define a custom exception and just throw that one in your aspect. then also in your aspect check the exception before loggin, if it's not your custom exception log it, otherwise don't log it and (re-throw?).
That's what the example code would look like:
[Serializable]
public class DatabaseExceptionWrapper : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
if(!(args.Exception is CustomException))
{
string msg = string.Format("{0} had an error # {1}: {2}\n{3}",
args.Method.Name, DateTime.Now,
args.Exception.Message, args.Exception.StackTrace);
Trace.WriteLine(msg);
}
throw new CustomException("There was a problem");
}
}
Of course you'd still have to define that exception and everything. :)
Related
I'm using a 3rd party library which makes several calls to the function:
Trace.WriteLine(string message);
This clutters up the visual studio output window and makes debugging my application difficult (for instance; XAML binding warnings).
I'm trying to find a way to stop all trace messages from a specific dll from dumping to the visual studio output window - is writing my own TraceListener the only path forward?
I can't make a TraceFilter / EventTypeFilter work for a string message without category -- although I can't find the documentation to back this up -- empirically:
TraceFilter.ShouldTrace(...)
is called by the following functions (not a complete set):
Trace.WriteLine(string message, string category);
Trace.TraceError(string message);
Trace.WriteLine(object o);
but isn't called by:
Trace.WriteLine(string message);
Does anyone know why this call avoids the ShouldTrace filter?
If you don't want to create your own TraceListener, the only way to suppress Trace messages from a problematic dll is to stop all Trace messages by using Trace.Listeners.Clear().
Note that this will stop your own Trace calls as well. I am mentioning this because I know of a few applications that never used Trace.WriteLine and were getting a severe performance hit from a very noisy library constantly writing to the output window.
I would recommend creating a TraceListener that uses reflection to look for the dll you want to ignore in the call stack.
It's not possible to override Trace.WriteLine, but it is possible to override some calls in the default TraceListener to achieve the same effect.
Using a TraceListener like the one below can help you clean up your output window in Visual Studio so you can focus on the events you are interested in, rather than getting bombarded by messages from a third party library.
See sample code below:
using System;
using System.Diagnostics;
using System.Reflection;
// The library that calls Trace, causing the messages you want to suppress.
using NoisyLibrary;
namespace TraceSuppress
{
/// <summary>
/// Trace listener that ignores trace messages from a specific assembly.
/// </summary>
public class AssemblyFilteredListener : DefaultTraceListener
{
private Assembly assemblyToIgnore;
public AssemblyFilteredListener(Assembly assemblyToIgnoreTracesFrom)
{
this.assemblyToIgnore = assemblyToIgnoreTracesFrom;
}
public bool TraceIsFromAssemblyToIgnore()
{
StackTrace traceCallStack = new StackTrace();
StackFrame[] traceStackFrames = traceCallStack.GetFrames();
// Look for the assembly to ignore in the call stack.
//
// This may be rather slow for very large call stacks. If you find that this is a bottleneck
// there are optimizations available.
foreach (StackFrame traceStackFrame in traceStackFrames)
{
MethodBase callStackMethod = traceStackFrame.GetMethod();
bool methodIsFromAssemblyToIgnore = (callStackMethod.Module.Assembly == this.assemblyToIgnore);
if (methodIsFromAssemblyToIgnore)
{
return true;
}
}
// The assembly to ignore was not found in the call stack.
return false;
}
public override void WriteLine(string message)
{
if (!this.TraceIsFromAssemblyToIgnore())
{
base.WriteLine(message);
}
}
public override void Write(string message)
{
if (!this.TraceIsFromAssemblyToIgnore())
{
base.Write(message);
}
}
}
class Program
{
static void SetupListeners()
{
// Clear out the default trace listener
Trace.Listeners.Clear();
// Grab the asssembly of the library, using any class from the library.
Assembly assemblyToIgnore = typeof(NoisyLibrary.LibraryClass).Assembly;
// Create a TraceListener that will ignore trace messages from that library
TraceListener thisApplicationOnlyListener = new AssemblyFilteredListener(assemblyToIgnore);
Trace.Listeners.Add(thisApplicationOnlyListener);
// Now the custom trace listener is the only listener in Trace.Listeners.
}
static void Main(string[] args)
{
SetupListeners();
// Testing
//-------------------------------------------------------------------------
// This still shows up in the output window in VS...
Trace.WriteLine("This is a trace from the application, we want to see this.");
// ...but the library function that calls trace no longer shows up.
LibraryClass.MethodThatCallsTrace();
// Now check the output window, the trace calls from that library will not be present.
}
}
}
According to ILSpy, the Trace.WriteLine(string message) is declared as abstract and needs to be overridden by derived classes:
public abstract void WriteLine(string message);
All other methods you mention check the ShouldTrace and ultimately call the Trace.WriteLine(string message) message.
E.g.:
public virtual void WriteLine(string message, string category)
{
if (Filter != null &&
!Filter.ShouldTrace(null, "", TraceEventType.Verbose, 0, message))
{
return;
}
if (category == null)
{
WriteLine(message);
return;
}
WriteLine(category + ": " + ((message == null) ? string.Empty : message));
}
So the real reason is in my opinion, a decision of the designer of the Trace class.
He could have made that Trace.WriteLine(string message) protected to incidate that it is not intended to be called directly, e.g.:
protected abstract void WriteLine(string message);
We have an exceptions library that is expected to be used over several solutions. We have several custom exception types contained within this library.
The question that has arisen: If we want to align error messages being used in these exceptions, what is the best practise way to accomplish this? For this question, assume that there are 3 or 4 methods across the solutions who want to throw these types of exceptions.
Let's take an example:
public class CustomException : Exception
{
// You can assume that we've covered the other default constructors for exceptions
public CustomException(string message)
: base(message)
{
}
}
The work we want to replace:
public void DoWork()
{
Guid id = Guid.NewGuid();
// ...
throw new CustomException(string.Format("The guid was: {0}.", id));
}
Our current ideas
1/ Define a new constructor that accepts a guid that defines the error message:
const string GuidMessageTemplate = "The guid was: {0}.";
public CustomException(Guid id)
: base(string.format(GuidMessageTemplate, id))
{
}
public void DoWork()
{
Guid id = Guid.NewGuid();
// ...
throw new CustomException(id);
}
2/ Allow each solution to define exception builder classes/methods that instantiate the consistent exceptions
public class ExceptionBuilder()
{
const string GuidMessageTemplate = "The guid was: {0}.";
public CustomException BuildCustomException(Guid id)
{
return new CustomException(string.format(GuidMessageTemplate, id));
}
}
public void DoWork()
{
Guid id = Guid.NewGuid();
// ...
var exception = BuildCustomException(id);
throw exception;
}
3/ Another option?
Use first approach. Your exception should encapsulate building error message. Via constructor exception should recieve only context specific information from outside world.If your exception receive full error message via constructor, then client can create an instance of your exception as follows:
class InvalidEmailException : Exception
{
public InvalidEmailException(string message) : base(message)
{}
}
client code:
void ClientMethod()
{
throw new InvalidEmailException(String.Format("GUID {0} is wrong", Guid.NewGuid()));
}
But wait, I expect Email in this exception!
Approach with exception builder is over engineering, just use first approach :)
This piece code works well, but if I want to use it in other programs, how can i do that?
Is it possible to create the exception like class library? If yes, how?
namespace Exception_CreatingUserDefined
{
public class FirstOperandSmallException : Exception
{
public FirstOperandSmallException(String message) : base (message)
{
}
}
public class operation
{
int op1, op2;
public void operatn()
{
if(op1 < op2)
{
throw (new FirstOperandSmallException("First Operand Should not be Small"));
}
else {
//Do nothing
}
}
}
class Test
{
static void Main(string[] args)
{
operation opr = new operation();
try
{
opr.operatn();
}
catch(FirstOperandSmallException e)
{
Console.WriteLine("FirstOperandSmallException : {0}",e.Message);
}
Console.Read();
}
}
}
As Kenny said, by simply including your namespace you are able to use any public classes you have defined inside it. To accomplish this, please do the following:
Make your exception class (and desired constructors) public.
Change the output type of this assembly to the 'Library' type. To do this, right click your project and go to Properties and set the output type as Library.
Also, common practice with Class Libraries is to remove your main (entrance) code, so it only has classes and methods.
I would ask why you need to create a Exception like this in the first place. You aren't adding any additional properties with your custom exception. If it was me I would just throw InvalidOperationException and not create a custom exception.
I would only create a custom exception if you have additional data you need to get into your Exception or if you have code that needs to specifically catch that exception. The framework has many built-in Exceptions you can use that cover a range of issues.
I wonder whether there is a short and simple way for checking whether variable/property values match some condition?
Currently one of the most popular line in my code is similar to this one:
if (string.IsNullOrWhiteSpace(someFileName))
{
throw new NullReferenceException("'someFileName' must not be null.");
}
then the exception gets logged in the catch part and the execution continues and so on.
I don't like writing this line all over the place and just changing the variable name. It would be great if one could write something like this:
Assert.IsNotNullOrWhiteSpace(someFileName);
and it threw an exception saying that "{my variable} must not be null" with maybe some additional information like the parent class etc. that would help you to debug the code if you only have the logs available.
The problem with writing such a utility class that I encountered was that the thrown exception had of course the wrong stack trace like it happened in the utility method and not inside the method that called the assertion function.
This kind of value checking is required to especially work at runtime because I most of the time check user input like settings, paths, inputs etc.
EDIT:
I think I should have given an example of what I try to achieve:
public class FileExtractor {
public Form MainForm { get; set; }
public void ExtractFile(string fileName) {
Assert.IsNotNullOrWhiteSpace(fileName);
Assert.IsNotNull(MainForm);
// ...
}
}
and the let's call it Assert library should do this:
public static Assert {
public static void IsNotNullOrWhiteSpace(this string value) {
if (string.IsNullOrWhiteSpace(value)) {
// throw an exception like it occured in the ExtractFile
// the message should contain a hint like: "fileName must not be null"
}
}
public static void IsNotNull(this object value) {
if (value == null) {
// throw an excaption like it occured in the ExtractFile,
// the messagge should contain a hint like: "FileExtractor.MainForm must not be null."
}
}
EDIT-2
#CodeCaster - unfortunately I cannot not use C# 6 yet.
After some research and inspirated by two other questions here on stackoverflow
How to get Property Value from MemberExpression without .Compile()?
and
get name of a variable or parameter
I came up with this so far:
namespace ExceptionTest
{
class Program
{
static void Main(string[] args)
{
object test = null;
Assert.IsNotNull(() => test);
}
}
static class Assert
{
public static void IsNotNull<T>(Expression<Func<T>> expression)
{
MemberExpression memberExpr = expression.Body as MemberExpression;
var constExpr = memberExpr.Expression as ConstantExpression;
var value = (memberExpr.Member as FieldInfo).GetValue(constExpr.Value);
if (value == null)
{
throw new ArgumentNullException(memberExpr.Member.Name);
}
}
}
}
It almost does what I need. The last thing is to modify the stack trace so that it points to the Main method and not to the IsNotNull
You could use Debug Methods (http://msdn.microsoft.com/en-us/library/System.Diagnostics.Debug_methods%28v=vs.110%29.aspx), which however only work when compiling in debug mode.
Maybe Debug.WriteLineIf(Boolean, String) does what you need?
http://msdn.microsoft.com/en-us/library/y94y4370%28v=vs.110%29.aspx
How about applying attributes to the properties
http://msdn.microsoft.com/en-us/library/dd901590(VS.95).aspx
I think that you should try with Fody library library. For null-guards there is a package that you can find here. All libs are available via Nuget.
Fody is some kind AOP library that uses "weaving" technique to manipulate IL of an assembly and inject additional code.
So NullReferenceExcpetion (or maybe NullArgumentException) will be thrown exactly from your method.
Example from GitHub:
Your code
public void SomeMethod(string arg)
{
// throws ArgumentNullException if arg is null.
}
public void AnotherMethod([AllowNull] string arg)
{
// arg may be null here
}
What gets complied
public void SomeMethod(string arg)
{
if (arg == null)
{
throw new ArgumentNullException("arg");
}
}
public void AnotherMethod(string arg)
{
}
I am fully aware that what I am about to ask is not good practice... but:
Let's say I have a class containing a function that I want to always return a value, but store any exceptions that might occur for later processing. Something Like:
public Exception _error { get; set; }
public bool IsValid()
{
try
{
//do something here to cause exception
return true;
}
catch (Exception ex)
{
_error = ex;
return false;
}
}
Now that I have stored the exception, is it at all possible to throw the exception from an outside method while maintaining both the original stack trace and exception type?
throw _error; //lose stack trace
throw new Exception("", _error) //lose type
Thanks for looking or answering.
EDIT:
Thanks to some additional points, I realize that the below idea only takes away information and doesn't really add or simplify the situation. Thanks again to everyone.
After pondering Pieter's answer and comments, I'm now wondering if making a wrapper Exception class like the below could be a partial solution. This overrides as much of the exception as possible to make the New exception look like its innerexception, including the stacktrace.. dirty I know, but interesting:
public class ExceptionWrapper : Exception
{
private Exception _innerException;
public ExceptionWrapper(Exception ex) : base("", ex)
{
_innerException = ex;
this.Source = ex.Source;
this.HelpLink = ex.HelpLink;
}
public override string StackTrace
{
get
{
return _innerException.StackTrace;
}
}
public override System.Collections.IDictionary Data
{
get
{
return _innerException.Data;
}
}
public override string Message
{
get
{
return _innerException.Message;
}
}
public new Exception InnerException
{
get
{
return _innerException.InnerException;
}
}
}
No, this is not possible.
However, you normally solve this is by wrapping the exception in a new exception:
throw new MyException("Wrapper", _error);
This does maintain the stack trace of _error, but you do get a new exception. Your solution in your second example is the correct way of handling these cases.
Consider using reflection to create a wrapper exception of the correct type (Activator.CreateInstance) and calling the constructor that will accept the inner exception you have stored.
For example:
[Test]
public void test()
{
Exception ex = new ArgumentNullException();
Exception wrapped = (Exception)Activator.
CreateInstance(ex.GetType(), "wrapped", ex);
Type expectedType = typeof(ArgumentNullException);
Assert.IsInstanceOf(expectedType, wrapped, "Is ArgumentNullException.");
Assert.AreEqual(ex, wrapped.InnerException, "Exception is wrapped.");
}
Update
In order to mitigate the constructor issue, you could consider using the default constructor (should be there for an exception that follows design guidelines, but not mandatory) and then patching up the new instance by setting its fields via reflection.
I agree the approach is highly "meh" it's more an exploration of an idea. I wouldn't recommend it.
The exception design guidelines require a default constructor, so this sort of behaviour may go on in the framework somewhere anyway. Perhaps for some sort of icky serialization\deserialization of exceptions across some sort of communications boundary?
It seems that .net-4.5 added a new API for capturing stack/info about exceptions and rethrowing them in different contexts. This is called ExceptionDispatchInfo. It is useful if you find yourself needing more control over running tasks indirectly, like if you do manual thread management for jobs or Task does not exactly fit your needs. In your example, it should look like this:
public ExceptionDispatchInfo _error { get; private set; }
public bool IsValid()
{
try
{
//do something here to cause exception
return true;
}
catch (Exception ex)
{
_error = ExceptionDispatchInfo.Capture(ex);
return false;
}
}
/// <summary>Throw underlying exception if invalid.</summary>
public void AssertWasValid() => _error?.Throw();
Now, it doesn’t preserve the original caller. The displayed stack trace shows the calls from the original try block into the code in there, a statement breaking the original and new parts of the stack, and then the calls into ExceptionDispatchInfo.Throw() itself as the new part of the shown stack. This seems similar to how traces with async code look. If you care about the original caller, seems this won’t work. But if you care about getting the line/method that threw the exception, this should be sufficient.