August 18, 2009

Audit using Log4Net

I had taken a web service off the hands of someone and it had no logging. I needed a quick way to log everything from every method in the code. I also needed to pull the user executing the method. In most cases this would be simple, but not in this webservice...I figured I would read it from a cookie that we had. Nothing would be easy as I knew I had to place statements in some methods, but I wanted to at least make a reusable class.

I used Log4Net and have the log spit out xml to make it easy to import or work with. The code is fairly simple to use:
//In the try
Auditor.Audit.Method(this.Context, "MethodName", new object[] { request });

//in the catch:
Auditor.Audit.Method(this.Context, "MethodName", new object[] { request }, ex);
The code that does the simple audit:
    public class Audit
{
private static AuditorCore m_core = new AuditorCore();
private static bool enabled = false;

static Audit()
{
log4net.Config.XmlConfigurator.Configure();

try
{
enabled = bool.Parse(ConfigurationSettings.AppSettings["Audit.Enabled"]);
}
catch(Exception)
{
enabled = false;
}
}

public static void Method(HttpContext context, string methodName, IEnumerable arguments, Exception exception)
{
if (enabled)
{
m_core.Method(context, methodName, arguments, exception);
}
}
public static void Method(HttpContext context, string methodName, IEnumerable arguments)
{
if (enabled)
{
m_core.Method(context, methodName, arguments);
}
}
}


The core class:

internal class AuditorCore
{
private log4net.ILog log = log4net.LogManager.GetLogger("Audit");

private Dictionary m_serializers =
new Dictionary();

public void Method(HttpContext context, string methodName, IEnumerable arguments)
{
Method(context, methodName, arguments, null);
}

public void Method(HttpContext context, string methodName, IEnumerable arguments, Exception exception)
{
lock (m_serializers)
{
log.Info(string.Format("",
methodName,
GetUserId(context)));

foreach (object argument in arguments)
{
string xmlText = SerializeToXmlString(argument);
log.Info(xmlText);
}

if (exception != null)
{
log.Error("");
}

log.Info("
");
}
}

private string SerializeToXmlString(object obj)
{
if(obj == null)
{
return "";
}

// Use below object to avoid namespaces in result xml.
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
xmlnsEmpty.Add("", "");

XmlSerializer serializer = GetSerializer(obj.GetType());
using (StringWriter stringWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter))
{
serializer.Serialize(xmlWriter, obj, xmlnsEmpty);
}

// Strip out the header.
string xmlText = stringWriter.ToString();
xmlText = xmlText.Substring(xmlText.IndexOf('>') + 1);

return xmlText;
}
}

private XmlSerializer GetSerializer(Type type)
{
if (!m_serializers.ContainsKey(type))
{
m_serializers[type] = new XmlSerializer(type);
}

return m_serializers[type];
}

private string GetUserId(HttpContext context)
{
if (context.Request.Cookies["MyCookie"] != null)
{
return context.Request.Cookies["MyCookie"]["userid"];
}
else
{
return null;
}
}
}

No comments:

Post a Comment