.NET: Logging entry / exit without AOP? - c#

I want to be able to log when code execution enters a method and then exits, I was wondering is anyone has any comments on the best way to achieve this?
I know an AOP way of injecting the logging code at runtime exists but I wanted to have a little more control and PostSharp seems to be a pay framework.
What level of logging would you recommend here, I would think DEBUG.
What about logging timings? How long it takes for the method to enter vs exit
I would love to know what others are doing here and what frameworks you are using.
I am looking at going with log4net.
What i was thinking about logging was the parameters and the name of the method and the values of the parameters, and exiting I was thinking of logging the value of the object that I am returning if returning any at all..
What is everyone else doing?
Thanks in advance

If you don't want to use PostSharp (although there's a free version) or have a runtime proxy generated, there's an open-source alternative for static weaving called Afterthought.
Alternatively, you can use one of the profiling tools. VS Ultimate has one built-in.

Well, you could certainly create a "disposable logger" that could "automatically" log your information for the methods that you choose:
public class EnterExitLogger : IDisposable
{
Logger logger;
string name;
public EnterExitLogger(Logger logger, string name, params object [] args)
{
this.logger = logger;
this.name = name;
this.logger.Debug("Entering {0}", this.name);
int i = 0;
foreach (var a in args)
{
this.logger.Debug("arg[{0}] = {1}", i, a);
i++;
}
}
public void Dispose()
{
this.Logger.Debug("Exiting {0}", this.name);
}
}
And then use it like this:
public class MyClass
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public void SomeMethod(int x, int y)
{
using (new EnterExitLogger(logger, "SomeMethod", x, y))
{
//Do your work here
}
}
}
This doesn't strike me as a particularly good idea, and I doubt that I would do it myself. On the other hand, it does achieve some form of Enter/Exit logging without using AOP. If you really want "automatic" Enter/Exit logging, I'm not sure how to achieve it without AOP or Enterprise Library's version (whose name escapes me).
Obviously there will be some overhead in creating and disposing the EnterExitLogger in my proposed solution, but maybe it is not enough to be a negative for you.

Related

using(), access data from parent callee for logging purposes

I have a custom build log framework that logs to a database.
For example it can do
L.e("Error invalid password", userGuid);
This works fine for general use but the application is quite complex and there are a lot of different parts that are called from the main code. For example a login sequence could send an SMS for OTP which is handled by a completely other part of the system and it does not make sense to pass a lot of values thru just for logging purposes.
What I want to achieve is to tag the log with for example userGuid so that I can search for everything related to this specific user. I also want to tag any logging in the SMS module even though the SMS module does not know anything about the user concept.
So what I am thinking of is if it is possible to get the current threadid and store some things regarding the logging in a higher level. I wonder if this is at all possible.
Psuedo code:
void Login(UserName, Password) {
User user = UserManager.GetUser(UserName)
using(L.SetUser(user.ID)) { //Here I want to use user.ID later in code that dont know the context
SmsManager.SendOtp(user.Phonenumber)
}
}
public class SmsManager {
public static void SendOtp(string phonenumber) {
if (phonenumber == "") {
L.error("Phone number is empty"); //How can I use the value from L.SetUser above? Could I use a hash table of threadids in L or would that be a bad idea?
}
}
}
Kind regards
Jens
Can you show us some snippets from L? Is that a static class? Does SetUser set a static variable? You could use the using block the way you suggest. You'd want to implement IDisposable and clear the UserID value in the Dispose method. But if UserID is a static variable, then this solution will not work in a multi-threaded environment (without some other changes). And the design just seems odd to me.
Overall seems like you are using static a lot. That can get you into trouble.
There are lots of possible solutions. Tough to say what's best without seeing some more code. Here is one way using dependency injection to keep your modules separate, as you want.
Define an interface for your logger.
public interface ILogger
{
void Error(string message);
}
Implement with a class that adds the user information:
public class MessageWithUserLogger : ILogger
{
private readonly string _userId;
public MessageWithUserLogger(string userId)
{
_userId = userId;
}
public void Error(string message)
{
L.error(message, _userId);
}
}
Change SmsManager class to be non-static and depend on the ILogger abstraction rather than the L implementation:
public class SmsManager
{
private readonly ILogger _logger;
public SmsManager(ILogger logger)
{
_logger = logger;
}
public void SendOtp(string phonenumber)
{
if (phonenumber == "")
{
_logger.Error("Phone number is empty");
}
}
}
Inject the logger with userID when that information is available:
void Login(UserName, Password)
{
User user = UserManager.GetUser(UserName);
ILogger logger = new MessageWithUserLogger(user.ID);
SmsManager smsManager = new SmsManager(logger);
smsManager.SendOtp(user.Phonenumber);
}
The using statement is not intended to be used like this. The using statement was introduced to be able to define a limited scope, and at the same time make sure objects are disposed using the IDisposable interface (see also https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement).
The way you are using the using statement makes it seems as if the property is sent when you start the scope, and would somehow be "unset" afterwards, but this is not the case.
When working with loggers and starting from your pseudo code, I would say your logging framework should be extended to create a context specific logger when you go into the using, and then pass the logging context to the static function. it would look then as below:
void Login(UserName, Password) {
User user = UserManager.GetUser(UserName)
using(var logContext = L.CreateContext(user.ID)) { //Here I want to use user.ID later in code that dont know the context
SmsManager.SendOtp(logContext, user.Phonenumber)
}
}
public class SmsManager {
public static void SendOtp(LogContext logContext, string phonenumber) {
if (phonenumber == "") {
logContext.error("Phone number is empty"); //How can I use the value from L.SetUser above? Could I use a hash table of threadids in L or would that be a bad idea?
}
}
}
Instead of passing the log context, it is theoretically possible to store the context inside the L object and map it to a thread ID, and, later on in the functions check if there is a specific log context for that thread when you log something. In the IDisposable interface implementation of the LogContext object, you should then remove the context (which corresponds with the end of your using() scope). I would however not do this, because it "hides" a bunch of logic, but even more, it relies on the fact that every function will be executed in the same thread. This in combination with hiding this, makes it a possible source of errors (if the user of the code isn't aware that this is linked to the thread, and changes the thread, you might miss information, make wrong assumptions based on the logging, etc). I think it is not bad practice if you have functions like the SMS manager that has a number of helper functions, to pass in a context specific object.
Also, be aware that this is a concept that exists in most popular logging libraries such as Serilog, and, in almost all cases, writing your own logging libraries isn't the most profitable business (since most of these libraries also have extensions that allow you to write a custom sink, which for example would then write the log output to a database for your specific scenario (but you get all the rest for free).

C# xUnit Test listeners

I'm building a selenium test framework based on .Net Core and the team decided to go with xUnit. All's well and good everything has been going ok but for a while now, we've been trying to replicate the functionality of Java TestNG listeners without much luck.
I've been digging around the xunit git repo and found a few instances where some interfaces such ITestListener have been used. After digging deeper, I found that these listeners are from a package called TestDriven.Framework and I wanted to know exactly how would I use a test listener created using those interfaces?
So far this is my simple test listener that should write something when the test fails:
public class Listener
{
readonly int totalTests;
public Listener(ITestListener listener, int totalTests)
{
this.totalTests = totalTests;
TestListener = listener;
TestRunState = TestRunState.NoTests;
}
public ITestListener TestListener { get; private set; }
public TestRunState TestRunState { get; set; }
public void onTestFail(ITestFailed args)
{
Console.WriteLine(args.Messages);
}
}
Now, I know you can do this inside a tear down hook but remember, this is just a simple example and what I have in mind is something more complex. So to be precise, where/how exactly would I register the test to use this listener? In Java TestNg I would have #Listeners but in C# I'm not too sure.
Edit 1 so the example worked and managed to add it to my own project structure but when I try to use this
class TestPassed : TestResultMessage, ITestPassed
{
/// <summary>
/// Initializes a new instance of the <see cref="TestPassed"/> class.
/// </summary>
public TestPassed(ITest test, decimal executionTime, string output)
: base(test, executionTime, output) {
Console.WriteLine("Execution time was an awesome " + executionTime);
}
}
I'm having trouble registering this one, or if i'm even registering it right. As far as the examples go, I have found the actual message sinks but also found the actual test status data which i'm not exactly sure how to use.
I haven't worked with TestNG, but I did some quick reading and I think I see what you're after.
To demonstrate, I've created a very basic proof-of-concept implementation of the xUnit [IMessageSink] interface (https://github.com/xunit/abstractions.xunit/blob/master/src/xunit.abstractions/Messages/BaseInterfaces/IMessageSink.cs).
public class MyMessageSink : IMessageSink
{
public bool OnMessage(IMessageSinkMessage message)
{
// Do what you want to in response to events here.
//
// Each event has a corresponding implementation of IMessageSinkMessage.
// See examples here: https://github.com/xunit/abstractions.xunit/tree/master/src/xunit.abstractions/Messages
if (message is ITestPassed)
{
// Beware that this message won't actually appear in the Visual Studio Test Output console.
// It's just here as an example. You can set a breakpoint to see that the line is hit.
Console.WriteLine("Execution time was an awesome " + ((ITestPassed)message).ExecutionTime);
}
// Return `false` if you want to interrupt test execution.
return true;
}
}
The sink is then registered via an IRunnerReporter:
public class MyRunnerReporter : IRunnerReporter
{
public string Description => "My custom runner reporter";
// Hard-coding `true` means this reporter will always be enabled.
//
// You can also implement logic to conditional enable/disable the reporter.
// Most reporters based this decision on an environment variable.
// Eg: https://github.com/xunit/xunit/blob/cbf28f6d911747fc2bcd64b6f57663aecac91a4c/src/xunit.runner.reporters/TeamCityReporter.cs#L11
public bool IsEnvironmentallyEnabled => true;
public string RunnerSwitch => "mycustomrunnerreporter";
public IMessageSink CreateMessageHandler(IRunnerLogger logger)
{
return new MyMessageSink();
}
}
To use my example code, just copy the classes into your test project (you'll also need to add a reference to the xunit.runner.utility NuGet package). The xUnit framework will automagically discover the IRunnerReporter--no need to explicitly register anything.
If this seems like it's headed in the right direction, you can find a lot more info in the xUnit source code. All of the interfaces involved are well-documented. There are a few existing implementations in the xunit.runner.reporters namespace. AssemblyRunner.cs also demonstrates one possible method for dispatching the different event types to individual handlers.
Edit 1
I've updated the implementation of MyMessageSink (above) to demonstrate how you might listen for an ITestPassed message. I also updated the link embedded in that code snippet--the previous link was to implementations, but we should really use these abstractions.
The if (message is IMessageType) pattern is pretty crude, and won't scale well if you want to listen for many different message types. Since I don't know your needs, I just went with the simplest thing that could possibly work--hopefully it's enough that you can improve/extend it to fit your needs.

Log4Net message construction cost when not debugging

According to this log4net article you should check if debug is enabled prior to any Log.Debug statements to eliminiate the statement construction cost. Is there a better alternative to always having to check if(Log.IsDebugEnabled) prior to any log statements?
Log4Net example:
if (log.IsDebugEnabled)
{
log.Debug("This is entry number: " + i );
}
I don't want to pay the overhead cost of statement construction, but also don't want to check prior to every log statement.
#Grhm and #David have good ideas, but I don't think that David's wrapper is as good as it could be. Wrapping log4net that way. Simply implementing Debug, Info, etc on the wrapper and delegating those down to log4net's Debug, Info, etc methods break log4net's ability to log the call site information. If you wrap this way and tell log4net to log the call site info, log4net will write out the call site in the wrapper, not the call site in your actual code, which is what you want.
I personally don't like using a singleton logger as you lose the ability to tweak logging levels in different parts of your program. If you are working on several components, you might want Info level logging turned on for one component, but only Warn logging (or none at all) for other components. With a singleton logger, all logging in all of your application will be at the same level.
You are denying yourself a lot of log4net's built in (and powerful) capabilities when you wrap log4net incorrectly and when you use a single logger to cover your entire application.
I answered a similar question (about maintaining call site information) here:
how to log method name when using wrapper class with Log4net
To save time, I have included a code example here (uncompiled and untested, but should be close)...
public class MyLog4NetWrapper
{
ILog log;
public MyLog4NetWrapper(string loggerName)
{
log = LogManager.GetLogger(loggerName)
}
public MyLog4NetWrapper(type loggerType)
{
log = LogManager.GetLogger(loggerType)
}
public void Info(string message)
{
if (log.IsInfoEnabled) log.Logger.Log(typeof(MyLog4NetWrapper), LogLevel.Info, message, null);
}
//Defer expensive calculations unless logging is enabled - thanks Grhm for the example
public void Info(Func<string> formattingCallback )
{
if(log.IsInfoEnabled)
{
log.Logger.Log(typeof(MyLog4NetWrapper), LogLevel.Info, formattingCallback(), null);
}
}
//Debug, Warn, Trace, etc are left as an exercise.
}
You can create these loggers in your code like this:
public class MyClass
{
private static readonly ILog log = new MyLoggerWrapper(typeof(MyClass));
public void DoSomething()
{
log.Info("Hello world!");
}
}
The trick to writing a log4net wrapper that preserves the call site information is to use the Log method and to pass the type of your wrapper as the first parameter.
If you are going to write a wrapper in order to implement the functionality that you asked about (deferring execution of any expensive code in the logging call without explicitly checking to see if the desired logging level is enabled), then you might as well put that code in the wrapper rather than implement it as an extension method (which will also suffer from the same loss of call site problem I described above).
Good luck!
The easiest and cleanest way might be the use of the DebugFormat method which actually does the check if the debug level is enabled (see Github-Code of log4net).
but also don't want to check prior to every log statement
When you find yourself repeating the same code over and over, it sounds like a common abstraction may be in order. In this case you can, for example, create a custom wrapper for Log4Net. Something as simple as:
public static class Logger
{
private static ILog _log;
static Logger()
{
log4net.Config.XmlConfigurator.Configure();
_log = log4net.LogManager.GetLogger("Log4Net");
}
public static void Debug(string message)
{
if (_log.IsDebugEnabled)
_log.Debug(message);
}
public static void Info(string message)
{
_log.Info(message);
}
public static void Warn(string message)
{
_log.Warn(message);
}
public static void Error(string message)
{
_log.Error(message);
}
public static void Error(string message, Exception ex)
{
_log.Error(message, ex);
}
public static void Fatal(string message)
{
_log.Fatal(message);
}
public static void Fatal(string message, Exception ex)
{
_log.Fatal(message, ex);
}
}
In this case I made the logger instance static. I'm not 100% sure that will always work as expected. Normally I use this behind a dependency injection framework and configure the logger dependency to be a singleton, handled by the framework. You might instead make this an instance class with instance methods and put it behind a static factory class instead. Test and tweak as necessary.
There are a couple of added benefits here:
Your dependency in Log4Net is isolated to a single class. So if you ever want to use a different logger, you only have to change one class instead of everything in the entire project.
You can easily abstract this behind a dependency injector.
Any other common functionality you want to include in all logging statements can be easily and globally included here.
An example I commonly use for the third benefit might be something like this:
private static string GetLocation()
{
var frame = new StackTrace(1).GetFrame(1);
var method = frame.GetMethod();
return string.Format("{0}:{1}.{2}({3})", Environment.MachineName, method.ReflectedType.FullName, method.Name, frame.GetFileLineNumber().ToString());
}
This gets more meaningful debugging information from the runtime system (though there may be a performance hit, for high-volume systems it's worth testing). So my pass-through error logging function might look like this:
public void Error(string message, Exception ex)
{
_log.Error(string.Format("{0}:{1}", GetLocation(), message), ex);
}
You could use a lambda expression. Like:
log.Debug(() => "This is entry number:" + i);
That way the lambda is only evaluated after the .IsDebugEnabled call.
We have an extension class defined (taken from http://www.beefycode.com/post/Extension-Methods-for-Deferred-Message-Formatting-in-Log4Net.aspx) that has extension methods like:
public static class Log4NetExtensionMethods
{
public static void Debug( this ILog log, Func<string> formattingCallback )
{
if( log.IsDebugEnabled )
{
log.Debug( formattingCallback() );
}
}
// .. other methods as required...
}
I'm not sure if log4net have added lamda type support in more recent releases - but this has been working for me.
If you include the namespace log4net.Util, you are able to call the following extension methods on log4net ILog:
public static void ErrorExt(this ILog logger, Func<object> callback)
This will only call the lambda function when logging error level is enabled. No need to write your own extension methods. It also protects from creating an error while constructing the actual log message by wrapping the creation in a try catch method.
I would look at preprocessor (precompile?) directives.
#if DEBUG
{your logging code here}
#endif
Something like that should do it for you, and then the code only gets compiled in Debug Mode.
You can also use the the Conditional attribute on a method like this:
[System.Diagnostics.Conditional("DEBUG")]
private void YourMethodNameHere(YourMethodSignatureHere)
Take a look at this old question for more information on when/why/how you might use them.
http://stackoverflow.com/questions/3788605/if-debug-vs-conditionaldebug

Debugging exceptions in a Async/Await (Call Stack)

I use the Async/Await to free my UI-Thread and accomplish multithreading. Now I have a problem when I hit a exception. The Call Stack of my Async parts allways starts with ThreadPoolWorkQue.Dipatch(), which doesn't help me very much.
I found a MSDN-Article Andrew Stasyuk. Async Causality Chain Tracking about it but as I understand it, its not a ready to use solution.
What is the best/easiest way to debug if you use multithreading with Async/Await?
The article you found does a good job of explaining why call stacks don't work the way most of us think they do. Technically, the call stack only tells us where the code is returning to after the current method. In other words, the call stack is "where the code is going", not "where the code came from".
Interestingly, the article does mention a solution in passing, but doesn't expound on it. I have a blog post that goes explains the CallContext solution in detail. Essentially, you use the logical call context to create your own "diagnostic context".
I like the CallContext solution better than the solution presented in the article because it does work will all forms of async code (including fork/join code like Task.WhenAll).
This is the best solution I know of (other than doing something really complex like hooking into the profiling API). Caveats of the CallContext approach:
It only works on .NET 4.5 full. No support for Windows Store apps, .NET 4.0, etc.
You do have to "instrument" your code manually. There's no way AFAIK to inject it automatically.
Exceptions don't capture the logical call context automatically. So this solution works fine if you're breaking into the debugger when exceptions are thrown, but it's not as useful if you're just catching the exceptions in another place and logging them.
The code (depends on the immutable collections NuGet library):
public static class MyStack
{
private static readonly string name = Guid.NewGuid().ToString("N");
private static ImmutableStack<string> CurrentContext
{
get
{
var ret = CallContext.LogicalGetData(name) as ImmutableStack<string>;
return ret ?? ImmutableStack.Create<string>();
}
set
{
CallContext.LogicalSetData(name, value);
}
}
public static IDisposable Push([CallerMemberName] string context = "")
{
CurrentContext = CurrentContext.Push(context);
return new PopWhenDisposed();
}
private static void Pop()
{
CurrentContext = CurrentContext.Pop();
}
private sealed class PopWhenDisposed : IDisposable
{
private bool disposed;
public void Dispose()
{
if (disposed)
return;
Pop();
disposed = true;
}
}
// Keep this in your watch window.
public static string CurrentStack
{
get
{
return string.Join(" ", CurrentContext.Reverse());
}
}
}
Usage:
static async Task SomeWorkAsync()
{
using (MyStack.Push()) // Pushes "SomeWorkAsync"
{
...
}
}
Update: I released a NuGet package (described on my blog) that uses PostSharp to inject the pushes and pops automatically. So getting a good trace should be a lot simpler now.

Achieving DI without 3rd party framework

I am writing a plugin as part of a plugin architecture. The way plugins are created is via reflection and CreateInstance. Therefore the default constructor is called. This code I cannot touch and I am trying to find a sensible way to use DI without the ability to use a framework.
I believe I have 3 options:
i) Poor Man's DI (PMDI)
ii) Factory Pattern
iii) TinyIOC or similar (one cs file that handles DI)
I started looking at PMDI but then a dependency needed another dependency so I ended up with something similar to this which is ugly and could get worse:
public MyMainPluginClass() : this(new Repo(new Logger()))
{
}
public MyMainPluginClass(IRepo repo)
{
}
I then moved onto the idea of a Factory Pattern but could not find any decent demo code. I assume I would have something like this:
public static FactoryUtility
{
public static IRepo GetRepo()
{
return new Repo(GetLogger());
}
public static ILogger GetLogger()
{
return new Logger();
}
}
public MyMainPluginClass() : this(FactoryUtility.GetRepo())
{
}
public MyMainPluginClass(IRepo repo)
{
}
Is that how it would look?
I then came across TinyIOC which is one class that does all the dependency registering but I believe it requires to be setup in a Program.cs which I don't have in a class library. If someone has any experience using this could it be used like so:
public MyMainPluginClass()
{
var container = TinyIoCContainer.Current;
container.AutoRegister();
var implementation = container.Resolve<IRepo>();
MyMainPluginClass(implementation);
}
public MyMainPluginClass(IRepo repo)
{
}
Are there any alternative approaches to achieve DI without using a 3rd party library and if not which approach would choose from above?
NOTE: The code above has not been compiled and is just an idea of what I think would work. Please post corrections if they are valid approaches.
Since you're using .NET 4, you might want to consider using MEF, as it's built into the framework itself. This looks like fairly straightforward DI, which MEF handles well, as it's intended mainly for extensibility.
For details, see the Learn More page on the MEF CodePlex site.
I went with TinyIOC in the end. Unfortunately the plugin's constructor gets called several times before its actually up and running. I simply set a boolean to prevent registration being called several times and therefore it allows me to simply auto-register dependencies and off we go.
public MyMainPluginClass() : this(FactoryUtility.SetupIOC())
{
}
public MyMainPluginClass(IRepo repo)
{
}
public static class FactoryUtility
{
private static bool Initialized = false;
public static IRepo SetupIOC()
{
var container = TinyIoCContainer.Current;
if (!Initialized)
{
container.AutoRegister(new[] { Assembly.GetExecutingAssembly() });
Initialized = true;
}
var result = container.Resolve<IRepo>();
return result;
}
}
If I absolutely don't want to add a dependency to a DI container, I like to use my own TinyIOC (sorry about the name, didn't know it was taken), which for small projects gives me the same semantics as using a container, but clocks in at below 200 LOC.
If you are interested, here is the code: https://gist.github.com/ad7608e2ae10b0f04229

Categories

Resources