I try to write my first demo using EF7.
I have installed Microsoft.Extensions.Logging.Console 1.0.0-rc2-final
To log.
But when i try to use the follwoing code:
public static void LogToConsole(this DbContext context)
{
var contextServices = ((IInfrastructure<IServiceProvider>) context).Instance;
var loggerFactory = contextServices.GetRequiredService<ILoggerFactory>();
loggerFactory.AddConsole(LogLevel.Verbose);
}
I couldn't find the Verbose enum !
Instead i get the following :
Could someone help me to explain what's happened and which one should i use to log ?
Back in December, the original log levels were changed a bit to be more consistent with other logging systems. As part of this change, Verbose was renamed to Trace and moved in severity below Debug.
As for what log level you should use, it depends a lot on what you want to log and what you expect to see. See the recommendations in the documentation; to quote the first three bullet points:
Log using the correct LogLevel. This will allow you to consume and route logging output appropriately based on the importance of the messages.
Log information that will enable errors to be identified quickly. Avoid logging irrelevant or redundant information.
Keep log messages concise without sacrificing important information.
To choose the correct log level, you should first familiarize yourself with what they mean. Ordered from lowest severity to highest:
Trace – For the most detailed messages, containing possibly sensitive information. Should never be enabled in production.
Debug – For possibly interactive investigation during development; useful for debugging but no real long term value.
Information – For tracking the flow of the application.
Warning – For unnormal (but expected) events in the application, including errors and exceptions, which are properly handled and do not impact the application’s execution (but could still be a sign of potential problems).
Error – For real failures which cause the current activity to fail, leaving the application in a recoverable state though, so other activities will not be impacted.
Critical – For failures on the application level which leaves the application in a unrecoverable state and impacts further execution.
You can find similar explanations in the offical documentation and in the project’s logging guidelines.
Use LogLevel.Debug. The levels got renamed and shuffled around in RC2. See the announcement for more details.
Related
In an application with long running task and dependency injection log files can easily become flooded with useless data. This makes it harder to follow log files and drains storage space.
Examples:
A background service that polls a database every 10 seconds for data and logs to say that it is checking for data and how much data is retrieved
A transient service (DI) that has some logging in a method called by the constructor
For example 1, the background service logging is useful for diagnostics when something goes wrong but can easily flood the log file.
For example 2, each time the transient service is constructed, (which might be a lot) that logging in the method called by the constructor is logged.
Obviously, the logs can be split into different files e.g. debug level log file and general log file - this can make the general log file easier to follow but doesn't deal with log files taking up too much space. It also may result in the separation some info that paints a clearer picture of what is happening.
Is there anything more that can be done apart from splitting up the log files and being more selective about what's logged. Are there any best practices for this or any resources that provide good approaches to tackling this problem, or is it just a case of figuring out what's best to do in the specific scenario at hand?
You want to control the logging behaviour by using the correct LogLevel when logging messages.
You should have a look at the LogLevel Enum as it will clearly show you when to use which level.
In the appsettings.json of your application you can then set the minimum log level depending on the deployment environment.
You are referring to trace or information logging which should only be used in a test or development environment in order to get as much information as possible when something is wrong.
Usually only enabled when you are trying to reproduce a known error.
In a production environment you will only log Error or Critical messages. In your exception handling you could log some additional information about parameters that where passed into the failing method along with the stack trace. This should give you enough information to reproduce the error in dev or test where you can debug the application or enable trace logs.
Consider using Structured Logging for those scenarios.
Problems have been reported to me regarding the performance of a live site. I can't seem to replicate any of these issues on any dev or staging environments, and the profilers I have ran against dev has revealed nothing unusual.
This has led me to turn to a diagnostics trace for a simple timing trace so I can at least try and isolate the cause and try and narrow it down.
I'm quite happy to add
System.Diagnostics.Trace.WriteLine("....");
wherever necessary and add a listener (via web.config entry) to write out to a log file, but could this massively impact the performance of the live environment itself?
Is there anything else I need to consider when, potentially, leaving this to run over the weekend? i.e. is it best that I specify how large the log file is to get before closing and opening a new one?
It depends how much data you are going to log so turn on the logger and check if your application behaves normally. Also if logging to a log file slows down your application consider a faster TraceListener such as EventLogTraceListener (you may create a dedicated event log for this purpose with maximum size and log rolling). In case logging to a file is not a problem get EssentialDiagnostics RollingFileTraceListener. It has many options including setting maximum file size and the number of rolled files.
Use a logging framework like log4NET and make logging like:
LogManager.GetCurrentClassLogger().Debug("...");
When you disable logging afterwards in the configuration, these functions are not executed by the framework.
If you need to do string formatting for your messages: Use "DebugFormat()" which will not do the formatting if it is not needed by the level of logging desired.
I use the following method in my ASP.NET web application to receive the stack trace for an exception:
public static void getStackTraceInfo(System.Diagnostics.StackTrace trace)
{
for (int i = 0; i < trace.FrameCount; i++)
{
int nLine = trace.GetFrame(i).GetFileLineNumber();
int nCol = trace.GetFrame(i).GetFileColumnNumber();
string methodName = trace.GetFrame(i).GetMethod().Name;
}
}
try
{
}
catch(Exception ex)
{
getStackTraceInfo(new System.Diagnostics.StackTrace(ex, true));
}
It gives me full line/column/method name information if I run it in the Visual Studio 2010 dev environment, but in a production environment on the IIS it returns all 0's and the method name as empty string.
Do I need to do anything special to make it work on IIS as well?
It gives me full line/column/method name information if I run it in the Visual Studio 2010 dev environment, but in a production environment on the IIS it returns all 0's and the method name as empty string.
Correct. Read the name of the type carefully; that Diagnostics is important. The types in that namespace were designed for diagnosing problems in a debug environment.
Do I need to do anything special to make it work on IIS as well?
No; you need to not use diagnostic tools in production.
If for some reason you want to use diagnostic tools in a production environment, at a minimum you'll need to push the PDB files to the production environment. This might be a dangerous and foolish thing to do, as we'll see below. I recommend that you do not do so.
Some questions you did not ask:
What tool should I be using to get caller information in a production environment?
If you need to get the line number, etc, of a method call, the tool you probably should be using is the new CallerLineNumber and related attributes in C# 5.0. Here's a good blog on them:
http://blog.slaks.net/2011/10/subtleties-of-c-5s-new-callerlinenumber.html
If you need to get information about the stack trace of an exception, what you see is what you get.
In a debug environment does the StackTrace object provide a guarantee that the stack trace tells me where the current call came from?
No. A stack trace does not tell you where you came from in the first place. A stack trace tells you where you are going next. This is useful because there is often a strong correlation between where you came from and where you're going next; usually you're going back to where you came from.
This is not always true though. The CLR can sometimes figure out where to go next without knowing where you came from, in which case the stack trace doesn't contain the information you need.
For example, tail call optimizations can remove frames from the stack. Inlining optimizations can make a call to a method look like part of the calling method. Asynchronous workflows in C# 5 completely divorce "where you came from" and "where you're going next"; the stack trace of an asynchronous method resumed after an await tells you where you are going after the next await, not how you got into the method before the first await.
Stack traces are unreliable, so do not rely on them. Use them only as a diagnostic aid.
Why is it particularly dangerous to expose diagnostic information in ASP?
Because attackers will attempt to cause your server to fail by throwing "exceptional" inputs at it. If that brings the server down, great, the attackers will be happy. If it keeps the server up but leaks information about your source code to the attacker, even better. Now they have more information to use to mount a more sophisticated attack.
ASP servers should profer up as little diagnostic information as possible in a production environment. The less debug information you have in that production environment, the less likely you are to make a mistake and expose your implementation details to an attacker.
I'm developing a GUI app in C#.
It's a multithread app, and I would like to wrap all the threads (some of them I don't open, e.g. NetClient.StartDownload which is a none blocking function) with a try/catch statement so that if an exception is thrown and uncaught, I could log it and report to base.
I tried using Application.ThreadException and AppDomain.CurrentDomain.UnhandledException, but they seem to only catch GUI exceptions.
Is there a different way I need to handle this?
The code in each thread would need to have a try-catch. Exceptions are not marshalled across threads... and an unhandled exception just brings the application down.
To catch all Exceptions - just use the base Exception type.
catch(Exception e) { // log e }
Updated:
You could take a look at AppDomain.UnhandledException - handle this event for logging unhandled exceptions on any thread ; however you can't stop the application from going down. For more check out
http://www.albahari.com/threading/#_Introduction - towards the end of that page.
The best answer is: don't. There's already a system for doing this built right into the operating system.
If you let the exceptions "bubble up" and out of the program, modern OS'es include Windows Error Reporting, which will give the user the option of sending an error report to Microsoft. (Note: do not send error reports automatically - think long and hard about the legal ramifications regarding privacy laws...)
The error report includes not just the exception information and full stack trace, but also includes a good portion of your process' memory, as well as exactly which OS modules were loaded (so you can even tell whether the client had a relevant Windows Update patch applied). It wraps up all of this information into a minidump file (and also includes a few XML files with additional info).
This error report is uploaded to Microsoft's servers, so you don't have to worry about setting up and maintaining a "call home" server. All error reports for your programs are categorized using advanced heuristics into "buckets", with each "bucket" containing reports that are likely to be caused by the same bug.
Microsoft exposes all of this information to you (as the software publisher) through a site called Winqual. Using Winqual, you can examine all of the error reports, and use their heuristical bucketizing algorithms to decide which bugs are most impacting your customers. You can also download each individual report for more detailed investigation.
If you have a symbol server and source control server set up in your organization (and you certainly should), then you can just load the minidump from a downloaded error report right into Visual Studio, and it will automagically check the old source out of source control and allow you to inspect the exact state of the program at the moment it crashed.
Finding and fixing bugs has never been this easy.
To summarize, here's what you need to do:
Set up a symbol server and a source server in your organization. Establish a release policy to ensure that all releases get source-indexed pdbs added to the symbol server before they get released to the customer.
Establish an account with Winqual. You'll need an Authenticode code-signing certificate; if you get a non-VeriSign code-signing cert, then you'll also have to spend $100 for an "organizational certificate" from VeriSign.
Modify your release policy to include creating mapping files for your releases. These mapping files are uploaded to Winqual before shipping the release.
Do not catch unexpected exceptions. If you do ever need to catch them, be sure to rethrow using throw and not throw ex, so the stack trace and original program state is preserved.
For more information, I can highly recommend Debugging .NET 2.0 Applications by John Robbins. In spite of the "2.0" in the title, this book is still completely relevant today (except that the only source server example is using Visual SourceSafe, which was a complete joke even back then). Another good book if you need to do a lot of debugging is Advanced .NET Debugging, though it is starting to show its age, especially since the new VS2010 debugging advancements make a lot of its techniques out of date.
We need to catch exceptions at the smallest possible unit. As mentioned by Gishu, Exceptions which occur in the threads do not get propgated back to the main thread in many cases.
I had blogged about a similar experience some time back at WCF service unhandled exception error
What kind of information should an Application Log ideally contain? How is it different from Error Log?
You are going to get a lot of different opinions for this question.....
Ultimately it should contain any information that you think is going to be relevant to your application. It should also contain information that will help you determine what is happening with the application. That is not to say it should contain errors, but could if you wanted to use it that way.
At a minimum I would suggest that you include:
application start/stop time
application name
pass/fail information (if applicable)
Optional items would be:
call processing (if not too intensive)
errors if you decide to combine application and error logs
messaging (if not too intensive)
One thing you want to keep in mind is that you do not want to be writing so much information to your logs that you impact your application performance. Also, want to make sure you don't grow your log files so large that you run out of disk space.
A true error log should really contain:
The stack trace of where the error took place
The local variables present at the point of error.
A timestamp of when the error took place.
Detail of the exception thrown (if it is an exception).
A general application log file, for tracking events, etc, should contain less internal information, and perhaps be more user friendly.
To be honest, the answer really depends on what software the log is for.
Ideally, it should contain exactly the information you need to diagnose an application problem, or analyze a particular aspect of its past behavior. The only thing that makes this hard to do is that you do not know in advance exactly what problems will occur or which aspects of the application behavior will interest you in the future. You can't log every single change in application state, but you have to log enough. How much is enough? That's hard to say and very application-dependent. I doubt a desktop calculator logs anything.
An error log would just log any errors that occur. Unexpected exceptions and other unexpected conditions.
An application log usually contains errors, warning, events and non-critical information in difference to an error log that usually contains only errors and critical warnings.
The application log should contain all the information necessary for audit. This may include such things as successful/unsuccessful log on and any specific actions. The error log can be a subset of the application log or a separate log containing only information related to errors in the application.