Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best approach to logging? [closed]

My (local, windows/mono) app logs important events to a text file. In case of a sudden crash/failure/forced exit, no data should remain unwritten (as far as it's possible). Thus I currently use a simple append-to-text-file approach:

Public Shared Sub LogAppEvent(ByVal EventData As String)
    Dim Config As ConfigHandler = ConfigHandler.GetSingleton()
    Dim AppLog As New IO.StreamWriter(Config.GetUserFilesRootDir() & ConfigOptions.AppLogName, True)
    AppLog.WriteLine(String.Format("[{0}] {1}", Date.Now.ToString(), EventData))
    AppLog.Close()
End Sub

This is highly sub-optimal, but log events are pretty rare. Would you recommand moving to the System.Diagnostics logging class?

Or maybe would you suggest another solution?

like image 697
Clément Avatar asked Oct 14 '10 15:10

Clément


People also ask

What are some of the best practices for implementing security logging?

Here are few points to consider to secure it: Redact/mask/anonymize sensitive information from event logs beforehand, to prevent sensitive information from being logged in plain text (e.g., PHI/PII information) Enforce role-based access controls. Perform log integrity checks to ensure that logs are not tampered with.

What are the five levels of logging?

Logging levels explained. The most common logging levels include FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL, and OFF.


2 Answers

If a super basic approach like this is functionally sufficient for your needs, you can stick with it. But, you might ask yourself a few questions to make sure:

  • Is it possible for events to be logged concurrently by multiple threads? This function is not threadsafe

  • Is error notification needed?

  • Is there a risk of the log files growing without bounds with no automated pruning?

  • Would you benefit from more extensive logging so that you had more info about events leading up to an error?

  • Would you benefit from more detail about errors (stack trace, exception details, etc)

  • Does your program run on multiple computers? If so, how do logs get to you?

  • Is there any need/value in tools to help analyze log files (either singularly or finding patterns such as common errors across many log files)?

If you decide that you have other requirements, there are a number of free logging frameworks such as NLog or log4net that can help record more detailed logs, and there are several commercial products such as GIBRALTAR and SmartInspect available that can help with log management and analysis.

like image 142
Jay Cincotta Avatar answered Oct 20 '22 00:10

Jay Cincotta


As mentioned earlier, NLog and log4net are both good logging frameworks. As Jeff mentions above, System.Diagnostics is also a reasonable choice (for more than just logging to the EventLog). Trying to add some value to my answer, rather than just parroting what has already been said, you can enhance your System.Diagnostics logging by using TraceSources and by using the free Ukadc.Diagnostics library from codeplex.

With TraceSources you can created "named loggers", similar to how you can do it in NLog and log4net. These TraceSources can be configured to log at certain levels (varying per TraceSource) and they can be sent to various destinations (TraceListeners). All TraceSources can log to the same listener or some can log to some listeners while others log to other listeners. Any TraceSource can also be sent to multiple TraceListeners.

Here is how you would use TraceSources in code (assume that TraceSource "abc" has been configured in the app.config file to log "Info" and higher priority messages and has been configured to log to the file "log.txt").

public class MyClass
{
  static TraceSource ts = new TraceSource("abc"); //Common idiom for NLog and log4net, not sure if as common for TraceSource

  public void Func1(int x)
  {
    ts.Information("Entering Func1");
    ts.Verbose("x = {0}", x); //Won't log if "abc" is configured to log Info and HIGHER messgaes
    ts.Information("Exiting Func1");
  }
}

One huge benefit of Ukadc.Diagnostics, over "plain" TraceSources, is that you can configure NLog/log4net style output formatting so you can have much more control over what fields show up in your logging output and what format.

Three things that are pretty useful from NLog/log4net that are not available in System.Diagnostics are:

  1. Ability to automatically log call site information (method/function)

  2. Additional logging context (GDC - global logging properties, MDC - thread logging properties in NLog/log4net parlance). System.Diagnostics does have Trace.CorrelationManager.LogicalOperationStack, which is similar to NDC.

  3. Hierarichal loggers.

Hierarichical loggers means that you could configure an "ancestor" logger and any "descendent" loggers will inherit those settings. For example, say that you have a class whose fully (namespace) qualified type name is Namespace1.Namespace2.Class. With NLog/log4net you could configure logging information (level, destination) for "Namespace1" and if you requested a logger based on the fully qualified name of any type in Namespace1, it would inherit Namespace1's settings. You can achieve something similar to this using TraceSources by looking at how Castle implemented their TraceSource-based logging abstraction. In particular, look at the Initialize function. It is pretty easy to get working (in your own thin wrapper around TraceSource) and, as a side benefit, makes the configuration of your TraceSources a little bit easier since you don't have to configure every single TraceSource individually. Note that you could easily add the ability to have a "root" configuration by configuring a TraceSource called "" and adding some code in the Castle scheme to default to the "" configuration if no actual ancestors are found. You could then, for example, configure "*" to log at, say Verbose, and then specifically configure certain TraceSources (either by class or by namespace) to be off or at a different level. Without hierarichal loggers, to do the same thing with TraceSources would required you to configure every single TraceSource to log at "Verbose" that you want at verbose.

While I talked a lot about loggers for classes and namespaces, NLog, log4net, and TraceSources all also allow you to define your logger names as arbitrary strings. As such, you cold define a logger hierarchy by functional area rather than by namespace/class:

Database
Database.Connect
Database.Query
Database.Update
Database.SQL
Amazon
Amazon.Books
Amazon.Books.Fiction
Amazon.Books.Nonfiction
Amazon.Electronics
Amazon.Electronics.Video
Amazon.Electronics.Music
Amazon.Electronics.Computer

So, you could turn on "Amazon" logging and all Amazon stuff log (without having to explicitly configure each and every "child" TraceSource) and Database stuff would not. Or, you could turn Amazon on and Amazon.Electronics off and only the Amazon.Books (and children) would log.

Finally, if you do go with NLog or log4net, it is worth mentioning that NLog has just made a new release, NLog 2.0, (in beta).

like image 38
wageoghe Avatar answered Oct 20 '22 01:10

wageoghe