Is passive logging possible in .NET?

前端 未结 6 406
北海茫月
北海茫月 2021-02-02 03:19

I\'m frequently frustrated by the amount of logging I have to include in my code and it leads me to wonder if there\'s a better way of doing things.

I don\'t know if thi

相关标签:
6条回答
  • 2021-02-02 03:28

    In addition to the logging methods mentioned by Jon, its probably also worth noting another useful feature in VS for tracing program flow, and that is the ability to have non-breaking breakpoints that will simply output a message or run a macro when hit (note you can print variable values as well)

    Right click on your breakpoint and choose the When Hit... context menu item.

    And of course one other very useful feature is the Trace object and Trace Listners in System.Diagnostics.

    0 讨论(0)
  • 2021-02-02 03:33

    This is the classic example from Aspect Oriented Programming. See PostSharp for a very good CLR-based library.

    0 讨论(0)
  • 2021-02-02 03:42

    You can use PostSharp to log "around" the method. This is exactly the kind of thing AOP is good at. You might want to start with Log4PostSharp - a plugin specifically for logging.

    0 讨论(0)
  • 2021-02-02 03:47

    I've written a logging library recently that uses the IDisposable interface to wrap regions with logging context. Basically, there's a LogSite disposable object that you use like this:

    using(var logger = new LogSite("methodName", new object[] { p1, p2, p3 })
    {
        // code that does stuff goes here
    }
    

    The LogSite object has a bunch of convenient overloads for the constructor such as MethodBase so you can just use MethodBase.GetCurrentMethod() and use reflection to get the actual name of the method and parameters (instead of a hard-coded strings).

    The way it works is this -- In the constructor, it writes to the log with all the trace information to indicate it entered the block. In the Dispose method, it writes an exit entry.

    While disposing, it also checks Marshal.GetExceptionCode() for a non-zero value to see if the code inside the using threw an exception or exited normally. It doesn't give you the exception, so that will have to be logged explicitly in the catch handler, but it does indicate "pass/fail" for that region. This allows your logging scope to be more specific than just the method, since you could have lots of these blocks in a single method, and know which one threw the exception exactly.

    Also, since there's a "logger" object now available, your catch handler just looks like:

    try { ... } 
    catch (Exception ex)
    { 
        logger.LogException(ex);
    }
    

    The logger already knows the method name, parameter information, and all that, and has internal methods for formating the exception information.

    Getting into the architecture below this high-level object, there's a concept of "LogDisposition" which handles the "pass/fail" we determined earlier, and there's a concept of "LogEntryType" which is a filter (implemented with Flags enum) that indicates what kind of log entry is being passed (Error, Trace, etc).

    The thing that actually does the logging is just a publisher/listener pattern. The publisher takes the passed in log entry, and much like a multi-cast delegate, keeps a registry of LogListener instances (should be setup at the start of program, or added in dynamically as needed), and passes the log entry to those instances.

    The LogListeners in turn, filter out what kind of log entries they care about.. So if you don't want the method entry and exit points for non-error conditions, they don't have to show up in the log. This can be controlled at run-time to allow the user to do things like turn on and off detailed logging at will. Since the publisher can write to a variety of loglisteners, you can hook up something that writes to a file, or writes to the database, or displays error notifications in the GUI... etc.

    It's a pretty good system, and requires a relatively small amount of coding to get relatively rich logging.

    I could give you a code sample if you wanted... You can contact me through my (nearly completely inactive) blog (see my account profile).

    Hope that helps.

    0 讨论(0)
  • 2021-02-02 03:48

    This is one of the textbook (not sure which textbook has AoP in it but you get the idea) examples of AoP - logging : where you want to stick something before and after a method.

    You might want to explore the AoP route, PostSharp is one of the popular ones, along with Microsoft Unity (IoC too), Castle.

    One simplistic example of AoP is you add your code before and after methods, instead of adding the method calls inside the actual methods. As you've tagged the question with C# you might want to just look into making an extension method to log it, which is already in this question.

    I would take a practical approach: how much actual logging are you doing? Can you get away with just an extension method instead of razzle-dazzle'ing the person reading your code. The logging built into the .NET framework is decent already.

    0 讨论(0)
  • 2021-02-02 03:48

    I use the opensource Apache log4net in all of my projects. It's a very simple implementation with all kinds of extensions that allow you to log to databases, zip files, rolling log files, RRS feeds, telnet clients, etc. Logging is basically as simple as:

    'Will print stack trace after message'
    log.err(ex.message,ex)
    
    log.warn("warn")
    log.info("info")
    log.debug("debug")
    

    Logging parameters such as the output format and log level to output are all read real time while your app is in runtime.

    0 讨论(0)
提交回复
热议问题