Logging during an application refers to the tracing of internal code actions and functions, user actions, as well as any errors or exceptions that may arise.
As I have learnt over the years, at a certain stage of application development logging becomes critical. It is imperative during testing (especially with multiple, external testers) that they can report any problems or issues in the most efficient manner; this usually entails sending a log file to the developer, which can be used to assist debugging.
VB.NET comes with its own ‘logging’ sub-system integrated into the language. It allows the developer to place entries into the log file at specified points in the code. These entry points are usually placed at strategic points, such as in the catch statement of a Try… Catch or at the end of a long process to indicate completion.
The logging sub-system of VB.NET resides under the My.Application.Log namespace. Under this namespace are several functions and concepts, that I will detail below, which will let you start logging in your own applications.
Several functions under this namespace allow you to write events to the log file. An ‘entry’ essentially, is composed of a string Message, a Severity Level and an Event ID.
The Message is a string that the developer specifies to appear in the log file. It should generally detail a stage in the code (e.g. “Starting update…”).
The Severity Level is used to determine how ‘critical’ the entry or exception is. This level is only used to help filter out critical events from the less critical ones. For example, an event of a failed update, “Update failed” should be classes at a error level, while an event such as “Starting update” should only be classed as an information level.
Other levels, such as a ‘critical’, are usually reserved for an error that causes the application to cease functioning.
The Event ID attribute is a way help index and identify the errors that may occur for correlation purposes. It is optional attribute when writing an event. It is usually reserved for error events as opposed to verbose events.
Writing Events to the Log
You can write events to the log by calling a function under the My.Application.Log namespace. The following code write an example event to the log;
My.Application.Log.WriteEntry("Starting to process function XYZ", TraceEventType.Verbose)
As noted above, the Event ID attribute is optional; it may be considered in-effective to index verbose level messages; reserving the event ID’s for error and critical level events.
Writing Errors to the Log
When writing Errors to the log a slightly different and specialized function may be used. The WriteError function will write details of an ‘exception’ caught during a Try… Catch statement. It is invoked similar to the code example below;
Throw New Exception("A sample error exception")
Catch ex As Exception
My.Application.Log.WriteException(ex, TraceEventType.Error, "Additional information or details")
Once the error exception is raised within the Try block, the WriteException event will write the exception details (ex) to the log. The same severity level option can be applied, as well as some additional notes to make debugging easier.
So where does the log file end up?
When the application closes, and the log file has been flushed to disk the file can be retrieved for analysis. By default it is placed in the user’s Roaming profile under a subdirectory relevant to your application name. To save some time, you can find out the direct path, and for example, show it in a message box, while running the program by executing the following line of code;
Level specific Logging
As with any logging sub-system, some performance overhead (while extremely minimal) may be invoked. To help reduce this, it is possible to only log events that may be considered more relevant than others.
As discussed above the Severity Level can help rank events on a scale of severity, from Verbose to Critical. Similarly we can choose to only log events that we deem important on a release application, for example only events higher than the Informational level. We can choose programmatically as to which events should be included and which should not. The code below sets this level to log events only Information and above.
My.Application.Log.TraceSource.Switch.Level = SourceLevels.Information
The hierarchy of severity levels can be determined using the table below (source).
|SourceLevels Value||Message severity required for output
|Error||Critical or Error
|Warning||Critical, Error, or Warning
|Information||Critical, Error, Warning, or Information
|Verbose||Critical, Error, Warning, Information, or Verbose
|ActivityTracing||Start, Stop, Suspend, Resume, or Transfer
|All||All messages are allowed.
|Off||All messages are blocked.
Logging becomes essential in larger, more complex programs with several testers. Hopefully the outline of the logging system above will make it simple to implement basic logging capabilities into your own application.