Click here to Skip to main content
15,881,709 members
Articles / Desktop Programming / WPF

Editing Log4NET Configuration Programatically

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
19 Apr 2016CPOL1 min read 12.7K   132   3   1
This article and associated project demonstrate how to use XDocument to edit log4net config files.

Introduction

I have a situation where I need to output logs generated by a specific class in a separate file. And there are lot of services in which it needs to be changed across many machines. So I need a utility which can do so programmatically. We basically need to add an appender and a logger to all log4net configuration files.

I will specifically focus on how to change config files, this is part of a larger utility.

Background

The approach here is to use XML editing to change log4net logging behavior across many components. The other approach of using string manipulation does not work reliably and sometimes renders log4net config corrupted and logging fails altogether.

Using the Code

There are two input Xelements provided, the first one doesn’t exist in the source and the other one exists but with different attribute values. The output will have all the existing elements and will include the updated values provided in inputs.

XML
<logger name = "LoggerName" >

< level value="DEBUG" />

<appender-ref ref="ConsoleAppender" /></logger>

    <appender name="RollingLogFileAppender" 
    type="log4net.Appender.RollingFileAppender">
  < file value = "C:\\TestProj\\TestLog.txt" /> 
   < appendToFile value = "true" />  
    < rollingStyle value = "Size" />   
     < maxSizeRollBackups value = "10" />    
      < maximumFileSize value = "10MB" />     
       < staticLogFileName value = "true" />      
        < layout type = "log4net.Layout.PatternLayout" >       
           < conversionPattern value = "%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />        
          </layout >
        </appender>

       <root>
  <level value="DEBUG" />
  < appender-ref ref= "RollingLogFileAppender" />
  </ root > ";

            txtInput2.Text = @"<logger name="LoggerName">
    < level value = "DEBUG" />
 
     < appender-ref ref= "RollingLogFileAppender" />
   
     </ logger >

First, we create XmlDocument from the input string. And then, we extract attributes which need to be updated.

C#
private void AppendConfigLog4net(string text1nput)
{
    text1nput = ClearTextFromInvalidChars(text1nput);

    XDocument xmlDoc1 = XDocument.Parse(text1nput, LoadOptions.None);

    foreach (var v1 in xmlDoc1.Descendants())
    {
        if (string.Compare(v1.Name.LocalName, "appender", true) == 0)
        {
            AddAndReplaceAppenderElementInExisitngConfig(v1, v1.Attribute("name").Value,
            v1.Element("file").Attribute("value").Value);
        }
        else if (string.Compare(v1.Name.LocalName, "logger", true) == 0)
        {
            AddorReplaceLoggerElementInExisitngConfig(v1, v1.Attribute("name").Value,
            v1.Element("appender-ref").Attribute("ref").Value);
        }
    }
}

Then, in the existing config file, we load in XmlDocument and replace attributes or add new element if it weren’t existing.

C#
private void AddorReplaceLoggerElementInExisitngConfig(XElement v1, string localName, string value)
{
    var query = from c in xDoc.Root.Descendants("logger")
                where (string)c.Attribute("name") == localName
                select c;
    if (query.Count() <= 0)
    {
        var v2 = xDoc.Root.Descendants("logger").LastOrDefault();
        xDoc.Root.Add(new XElement(v1));
    }
    else
        foreach (XElement node in query)
        {
            if ((string)node.Element("appender-ref").Attribute("ref") != value)
            {
                node.Element("appender-ref").Attribute("ref").Value = value;
            }
        }
}

private void AddAndReplaceAppenderElementInExisitngConfig
    (XElement xmlDoc1, string rfaAppender, string filePath)
{
    var query = from c in xDoc.Root.Descendants("appender")
                where (string)c.Attribute("name") == rfaAppender
                select c;
    if (query.Count() <= 0)
    {
        xDoc.Root.AddFirst(xmlDoc1);
    }
    else
        foreach (XElement node in query)
        {
            if ((string)node.Element("file").Attribute("value") != filePath)
            {
                node.Element("file").Attribute("value").Value = filePath;
            }
        }
}

private string ClearTextFromInvalidChars(string text1)
{
    text1 = text1.Replace(((char)0xFEFF), '\0');
    text1 = text1.Replace("< ", "<");
    text1 = text1.Replace(" >", ">");
    text1 = text1.Replace("</ ", "</");
    return text1;
}

I have attached the working project which has all the details.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhy? Pin
John Torjo19-Apr-16 12:57
professionalJohn Torjo19-Apr-16 12:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.