I would like to configure the NLog.config file(.net framework web app) to log some specific properties of exception.
I want only type,stackTrace and message.
I read this layout render
${exception:format=String:innerFormat=String:maxInnerExceptionLevel=Integer:innerExceptionSeparator=String
:separator=String:exceptionDataSeparator=string}
but I cannot understand how to log only these properties that I want.
Strange that other reply was removed, since it was completely correct. Let me write it one more time. The examples below can also be found on the Wiki-page that you have found yourself.
Renders Exception-Message:
${exception:Format=Message}
Renders Exception-Type:
${exception:Format=Type}
Renders Exception-StackTrace:
${exception:Format=StackTrace}
They can also be combined:
${exception:Format=Message,Type}
If you have issues with unexpected output, then you are probably victim of not properly deploying the updated NLog.config.
As mentioned in the blog below, could the attribute, _bpf_accountid_value be used when not found in the default solution? Trying something similar with leads, I am trapping the error "the given key not present in dictionary".
I am on the lead form and for testing purposes I traverse the BPF and without manually finishing it,
I am trying to make my custom workflow "Finish" it, on demand.
I hesitate to show my code because it is commented with various attempts and will only loose the focus of this specific question.
Please help.
https://community.dynamics.com/365/b/crmmemories/posts/finish-a-business-process-flow-in-c
I just verified in my instance as the BPF will have its own entity, I can find those attributes. You can check too using CRM REST Builder or the native Advanced find - download fetchxml.
There is a difference between OOB like Lead entity BPF and custom entity BPF like below: (_bpf_xxx_projectinspectionsid_value vs _leadid_value)
https://crmdev.crm.dynamics.com/api/data/v9.1/xxx_inspectionflows(00000000-0000-0000-0000-000000000000)?$select=_bpf_xxx_projectinspectionsid_value,bpf_name,businessprocessflowinstanceid
https://crmdev.crm.dynamics.com/api/data/v9.1/leadtoopportunitysalesprocesses(00000000-0000-0000-0000-000000000000)?$select=businessprocessflowinstanceid,_leadid_value
I know similar questions have been asked a million times. I've read them and I still cannot get to the bottom of this. I'm using the Novell.Directory.Ldap c# library in my code (Winforms, c#). It works very similar to the microsoft ldap libraries but it can also access the attributes specific to Novell eDirectory.
using Novell.Direcotry.Ldap; is in there. I also added the reference and pointed it to the Novell.Directory.Ldap.dll file.
string LDAPServerIP = "12.34.56.78";
string serverUserName = "cn=Rrunner,o=acme";
string serverPassword = "#nvi1";
LdapConnection ldapConn = new LdapConnection();
MessageBox.Show(ldapConn.ToString());
ldapConn.SecureSocketLayer = true;
ldapConn.Connect(LDAPServerIP, 636);
ldapConn.Bind(serverUserName, serverPassword);
I get a NullReferenceException when it gets to the ldapConn.Connect() method.
Stepping through in the debugger is can see the ldapConn object, and it is a Novell.Directory.Ldap.LdapConnection object and seems to have sensible values assigned to it. For example, it does get SSL set to true, and at the point of the exception it even has already had the Host(string) variable set to the LDAPServerIP, and the Port(int) set to 636 just as the ldapConn.Connect() ordered. Given this information, I put a try/catch on just that statement to get past it since it is putting the attribute in anyways. It then will also get the exception on the Bind() method, and bind did put the appropriate values (userDN and password) into the object as well.
That section of code I copied directly from another program I use/write and it works perfectly fine in that so I don't know why it shouldn't work in this program. The only difference is that this is a differnt project in Visual Studio.
Given that, I've tried going through the things again that could be different because its a different project:
I've tried verifying that the reference to the Novell supplied is in the project. I'm fairly certain that part must be working because the object in memory is of the correct type and has a bunch of attributes that my program doesn't tell it about so they had to come from that dll file.
The SSL cert exists on my computer in a spot where .net can find it as this is the same computer that I develop the program that does connect to LDAP successfully.
What am I misssing? It seems like it has to be something really simple.
I found it finally. It was something really simple, and something that had to be set due to being a different project. I needed to add Mono.Security.dll and the reference to it.
Let's say you are using a library that returns error codes. You'd like to write a wrapper for the library, and you'd like to handle errors with exceptions in the code.
If the library is still in development by someone else, and if the error codes may change (there can be new ones, there can be deprecated ones, or some error codes may change meaning slightly), what would your solution be to handle this?
This is the situation that I'm in right now. In my case, the library is written in C++, and we're using C#. The coder of the library says the error codes may change, and I have to find a way to work with it.
Our initial solution is to:
Create an XML file that has the error codes in different categories (terminal ones, input errors, and so on).
Wrapper fetches these error codes on start.
Throws the appropriate exception by checking the category of the error code.
So let's say a method returns error code 100, then the wrapper checks the category of the error code. If it is a terminal error it throws a terminal error exception, if it is a user input error it throws a user input error exception.
This should work, but I feel like this is not the optimal solution. I'd like to know how good written enterprise software handle change of error codes.
What would you suggest doing?
Edit: I have already questioned the fact that error codes will be changing and the coder of the library says the code is in development. It's an algorithm, so even the way the algorithm works changes as it's original research (he's writing his PhD on that). So he says there may be different errors, or some may be irrelevant in the future.
The data-driven approach you're taking, using the XML file, seems like a good one, given the circumstances. However I'd question why the error codes are changing at all - this suggests that no proper design has been carried out for the library being developed. It ought to have a well-defined structure for its error codes, rather than requiring you to keep changing your interpretation of them.
You may want to try having an overall "library exception" exception class, and subclassing it for each different type of exception you want to throw based on the "type" of the library error. At least that way, you can catch all library errors, even if one of the specific types of exception slips through the net. ie. you'd catch something like LibraryException after trying to catch TerminalErrorException.
I guess you will solve this problem easier if you change your vision of the situation a little bit:
You are dealing with the framework, let's call that an external
framework.
On the other hand, you are writing a wrapper for the
framework - internal framework.
Your code (client application) uses internal framework, assuming that it provides the functionality used for the problem domain. As I understand, and as I believe, client application should not have any idea about the external framework.
Now, the question comes down to the following one: is the internal framework's functionality clearly outlined and finalized? or is that changing too?
If it's changing (possibly because of the external framework), then the internal framework is under the development. This means, client application needs to wait until internal framework is ready to announce a first version ready (possibly after the external framework is complete).
Now error handling:
Errors in the application serve like contracts. Caller of the function expects particular exceptional situations, and particular kinds of errors only. Each possible error is predefined and documented by each function, similar to its input parameters and return values.
What it means for you:
Define the final design of the internal framework (the sooner the better).
Decide what kinds of errors each function of the internal framework can throw.
Use internal framework from your client application and expect only expected and documented exceptions. Don't try/catch anything that is not expected from the internal framework. Basically, follow the contract.
If error code changes, that does not change the concept of the function in the internal framework. It still needs to throw the same kind of error it threw before (according to the contract). The only part that needs to be changed is, how to translate the new code to one of the expected (contracted) errors. You can solve it any way that works better.
Why is the last assumption fine? because we said the internal application's design is final and is not going to change. Error contracts are part of the final design too.
Example:
//external.
int Say(char* message);
//internal.
///<summary>
/// can throw (CONTRACT): WrongMessageException, SessionTimeOutException
void Say(string message) {
int errorCode = External.Say(message);
//translate error code to either WrongMessageException or to SessionTimeOutException.
}
Cannot translate? something is wrong either with current contracted errors or the external framework: maybe you should terminate the process? something went wrong, unexpected!!!
//client.
...
try {
Internal.Say("Hello");
}
catch (WrongMessageException wme) {
//deal with wrong message situation.
}
catch (SessionTimeOutException stoe) {
//deal with session timeout situation.
}
Let me know if anything raises the question.
Translating error codes to Exceptions:
This obviously is some kind of categorizing for each error code. Category can be each destination exception, and exceptions can be categorized by functions. This is exactly what the error contract means: categorize Exceptions by functions; and categorize error codes by exceptions.
Below is a pseudo configuration for this. Take this as an initial idea of how to categorize:
category Say [can throw]: { WrongMessageException, SessionTimeOutException }
category WrongMessageException [by error code]: { 100, 101 }
category SessionTimeOutException [by error code]: { 102, 103, 104 }
Of course you don't need to write a parser for such kind of impressions (this was human readable pseudo configuration). You can store similar sentences using XML or any kind of source, which will help you configure error translation rules and function contracts.
Reference
Book: Jeffrey Richter - CLR via C#, 3rd edition. Chapter 20 - Exceptions and State Management. Sub-Chapter - Guidelines and Best Practices. Sub-Sub-Chapter - Hiding an Implementation Detail to Maintain a "Contract".
This chapter will describe exceptions as contracts and will explain how to categorize contracts thrown by the function. This can confirm the correctness and the credibility of the explanations provided here.
What about this:
You said you have stored Error categories some where (DB or XML file)
lets amuse we have some master detail tables called ErrorCategory(Master) and ErrorDetail(Detail)
I will recommand adding a column (property) to your Errorcategory Table
Called CustomExceptionType, it will be a text property containing full name of assembly and class name of specified exception (ex: CustomExceptions,CustomExceptions.TerminalError )
We will need a base class 4 all of our custom exceptions, lets call it BaseCustomException calss
We will need an ExceptionFactory Class lets call it CustomExceptionFactory class
Our ExceptionFactory will have a method called CreateException, something like this
Public BaseCustomException CreateException(EceptinCategory category, ExceptionDetail detail)
{
var customException = Activator.CreateInstance(category.CustomExceptionType) as BaseCustomException;
customException.SetDetails(detail);
return customException;
}
so in run time our CustomExceptionFactory object will use CustomExceptionType to create a an instance of specific exception using Reflection.
I prefer CustomExceptionFactory & BaseCustomException to be implemented in a assembley
and all derived CustomExceptions be implemented in another assembly so our main application will be non related to CustomExceptions.Dll
In futur by changing of C++ factory, our main application will not need rebuilding and all we need is change in data of tables and impementaion in CustomExceptions.Dll.
(same solution could be implemnted using XML or Configuration file or ...)
Hop this will help.
OK, if you want to be flexible and not to depend on the code I think using reflection to generate custom class when you first run the application would be the best. Here is the rough explanation. If you like it I can explain it further.
The provider of the C++ code should create a class that will hold all error codes - for example public class Errors{public static readonly IOError = 100}.
When you start your application you will check this class for modification and if it is modified you will generate exception class for each error code.
In the above example it you will generate class IoException that inherit Exception .net class.
After that you can use it in the wrapper and catch each exception individually.
Another possible solution is to amend the xml that you are mentioned - for each error code add exception class - using the example the for error code 100 you will have IoException class. after that you need to implement this class and use it...
Better to depreciate old codes and leave their designations reserved than to have your code designations constantly changing. Since your author doesn't seem interested in design, have him report warnings and errors on the stderr stream that you can retrieve.
In addition, it seems simple enough to construct a CSV or XML with code-string pairs that the algorithm writer is free to edit as he sees fit. Reserve certain ranges of code number for different types of errors (1000s for input errors, 2000s for terminal errors, etc) have your wrapper interpret the return code using the code-string pair he wrote.
Then throw your exception based on the type of error, determined by the number range.
We have a "log" class which uses Relection.MethodBase to send current class info to the log.
The reflection.MethodBase stuff happens in the class itself.
However, I'd like to move that stuff to a single external "log" singleton type class.
In this scenario the external log class needs to get the CALLING info, not the current method info. I'm using stacktrace to do this, which isn't in the Reflection namespace.
Can I guarantee that "that" specific information (calling method) will be there in a production environment?
var stackTrace = new StackTrace();
return LogManager.GetLogger(stackTrace.GetFrame(1).GetMethod().DeclaringType);
cheers!
Yes, even in a "release" build without any PDB's you will have the method names in a stack trace. But personally I would consider this a code smell. It implies a very fragile code path (for example what happens if you make a WriteLine method that calls a Write method, do you look at the caller's caller in that case?). It also is probably not cheap to take a snapshot of the stack trace on every logging call.
I recently posted a question about using MEF to inject a logger into my class and I wanted to associate a type name with the log data as well. MEF worked out pretty well for me as I was able to import an ILogger instance for each class that wanted to use it and when the ILogger instance was imported, I would set its Category property to the name of the current class. No reflection, no stack trace. It worked pretty nicely for me.
Josh has it right. Taking stack traces is very expensive and should be avoided. It's a bit hard to understand exactly what you are doing, but it sounds rather bad. My first suggest would be to take another look at your production environment and see what logging services are already in place and how you can use them.
If you cannot, then I'd be looking into already available APIs such as Log4j, SLF4j and Commons logging to see how you could utilise them. Finally, if still not useable, you can at least look at their source to see how they do things. Also the source for JUnit does stack trace analysis if I remember correctly so there's another source of ideas.
But my last word would be to keep things as simple as possible. Don't go around creating stack traces. Generally speaking you are really only concerned about them when an exception happens and then it is handed to you. You don't need to do anything except pass it along.